another brick in the wall

This commit is contained in:
2026-02-04 15:44:37 +01:00
parent 56f5b8a904
commit a59becd9cc
5 changed files with 74 additions and 49 deletions

View File

@@ -13,6 +13,11 @@ uniform LightSource lights[3];
uniform vec3 cameraPosition;
uniform vec3 ballPosition;
layout(binding = 0) uniform sampler2D normalSampler;
layout(binding = 1) uniform sampler2D diffuseSampler;
uniform int normalMapped;
out vec4 fragColor;
const vec3 baseColor = vec3(1.0);
@@ -39,44 +44,49 @@ float dither(vec2 uv) {
void main()
{
vec3 N = normalize(normal);
vec3 V = normalize(cameraPosition - worldPosition);
if (!bool(normalMapped)) {
vec3 N = normalize(normal);
vec3 V = normalize(cameraPosition - worldPosition);
// start with ambience
vec3 result = ambientStrength * baseColor;
// start with ambience
vec3 result = ambientStrength * baseColor;
for (int i = 0; i < 1; i++) {
vec3 toLight = lights[i].position - worldPosition;
vec3 L = normalize(toLight);
float dist = length(toLight);
for (int i = 0; i < 1; i++) {
vec3 toLight = lights[i].position - worldPosition;
vec3 L = normalize(toLight);
float dist = length(toLight);
float attenuation = 1.0 / (la + lb * dist + lc * dist * dist);
float attenuation = 1.0 / (la + lb * dist + lc * dist * dist);
float diff = max(dot(N, L), 0.0);
vec3 diffuse = diff * lights[i].color;
float diff = max(dot(N, L), 0.0);
vec3 diffuse = diff * lights[i].color;
// blinn-phong half-vector
vec3 H = normalize(L + V);
float spec = pow(max(dot(N, H), 0.0), shininess);
vec3 specular = specularStrength * spec * lights[i].color;
// blinn-phong half-vector
vec3 H = normalize(L + V);
float spec = pow(max(dot(N, H), 0.0), shininess);
vec3 specular = specularStrength * spec * lights[i].color;
vec3 toBall = ballPosition - worldPosition;
float projDist = dot(toBall, L); // distance along light ray
float perpDist = length(toBall - projDist * L); // perpendicular distance to ray
bool inShadowCone = (projDist > 0.0) && (projDist < dist);
vec3 toBall = ballPosition - worldPosition;
float projDist = dot(toBall, L); // distance along light ray
float perpDist = length(toBall - projDist * L); // perpendicular distance to ray
bool inShadowCone = (projDist > 0.0) && (projDist < dist);
float shadow = 1.0;
// skip ball's own light (index 2) to avoid self-shadowing the whole scene
if (inShadowCone) {
if (perpDist <= hardRadius) {
shadow = 0.0;
} else if (perpDist < softRadius) {
shadow = (perpDist - hardRadius) / (softRadius - hardRadius);
float shadow = 1.0;
// skip ball's own light (index 2) to avoid self-shadowing the whole scene
if (inShadowCone) {
if (perpDist <= hardRadius) {
shadow = 0.0;
} else if (perpDist < softRadius) {
shadow = (perpDist - hardRadius) / (softRadius - hardRadius);
}
}
result += shadow * attenuation * (diffuse + specular) * baseColor;
}
result += shadow * attenuation * (diffuse + specular) * baseColor;
fragColor = vec4(result + dither(textureCoordinates), 1.0);
} else {
fragColor = texture(textureSampler, textureCoordinates);
// fragColor = vec4(1, 0, 0, 1);
}
fragColor = vec4(result + dither(textureCoordinates), 1.0);
}

View File

@@ -16,6 +16,6 @@ void main()
{
worldSpaceVertices = vec3(modelMatrix * vec4(position, 1.0));
normal_out = normalize(normalMatrix * normal_in);
textureCoordinates_out = textureCoordinates_in;
gl_Position = MVP * vec4(position, 1.0f);
textureCoordinates_out = textureCoordinates_in;
}

View File

@@ -2,7 +2,7 @@
in layout(location = 1) vec2 textureCoordinates;
layout(binding = 0) uniform sampler2D textureSampler;
layout(binding = 4) uniform sampler2D textureSampler;
out vec4 fragColor;

View File

@@ -1,6 +1,8 @@
#include "glm/fwd.hpp"
#include "utilities/window.hpp"
#include <chrono>
#include <GLFW/glfw3.h>
#include <cstdio>
#include <glad/glad.h>
#include <SFML/Audio/SoundBuffer.hpp>
#include <SFML/Audio/Sound.hpp>
@@ -44,7 +46,7 @@ SceneNode* rootNode;
SceneNode* boxNode;
SceneNode* ballNode;
SceneNode* padNode;
SceneNode* textureNode;
SceneNode* textNode;
std::vector<SceneNode*> lightNodes;
std::vector<LightSource> lights;
@@ -102,9 +104,8 @@ unsigned int createTextureFromImage(PNGImage *img) {
glGenTextures(1, &tid);
glBindTexture(GL_TEXTURE_2D, tid);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img->width, img->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, img->pixels.data());
glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
return tid;
}
@@ -160,17 +161,23 @@ void initGame(GLFWwindow* window, CommandLineOptions gameOptions) {
textureShader = new Gloom::Shader();
textureShader->makeBasicShader("../res/shaders/texture.vert", "../res/shaders/texture.frag");
textureNode = createSceneNode();
textNode = createSceneNode();
auto img = loadPNGFile("../res/textures/charmap.png");
textureNode->textureID = createTextureFromImage(&img);
auto textureMesh = generateTextGeometryBuffer("foo", 39.0 / 29, windowWidth);
textureNode->vertexArrayObjectID = generateBuffer(textureMesh);
textureNode->VAOIndexCount = textureMesh.indices.size();
textureNode->nodeType = FLAT_GEOMETRY;
auto charmap = loadPNGFile("../res/textures/charmap.png");
textNode->textureID = createTextureFromImage(&charmap);
auto textMesh = generateTextGeometryBuffer("made with love", 39.0 / 29, windowWidth/8.0);
textNode->vertexArrayObjectID = generateBuffer(textMesh);
textNode->VAOIndexCount = textMesh.indices.size();
textNode->nodeType = FLAT_GEOMETRY;
rootNode->children.push_back(textureNode);
textureNode->position = {0, 0, 0};
rootNode->children.push_back(textNode);
textNode->position = glm::vec3(0);
auto normalImg = loadPNGFile("../res/textures/Brick03_nrm.png");
boxNode->normalMapID = createTextureFromImage(&normalImg);
auto diffuseImg = loadPNGFile("../res/textures/Brick03_col.png");
boxNode->diffuseID = createTextureFromImage(&diffuseImg);
boxNode->nodeType = NORMAL_MAPPED_GEOMETRY;
std::cout << "loaded textures" << std::endl;
@@ -352,7 +359,6 @@ void renderNode(SceneNode* node) {
glUniformMatrix4fv(3, 1, GL_FALSE, glm::value_ptr(node->currentTransformationMatrix));
glUniformMatrix4fv(4, 1, GL_FALSE, glm::value_ptr(node->modelMatrix));
glUniformMatrix3fv(5, 1, GL_FALSE, glm::value_ptr(node->normalMatrix));
glUniform3fv(shader->getUniformFromName("cameraPosition"), 1, glm::value_ptr(cameraPosition));
glUniform3fv(shader->getUniformFromName("ballPosition"), 1, glm::value_ptr(ballPosition));
@@ -363,6 +369,13 @@ void renderNode(SceneNode* node) {
}
if (node->nodeType == GEOMETRY && node->vertexArrayObjectID != -1) {
glUniform1i(shader->getUniformFromName("normalMapped"), GL_FALSE);
glBindVertexArray(node->vertexArrayObjectID);
glDrawElements(GL_TRIANGLES, node->VAOIndexCount, GL_UNSIGNED_INT, nullptr);
} else if (node->nodeType == NORMAL_MAPPED_GEOMETRY) {
glUniform1i(shader->getUniformFromName("normalMapped"), GL_TRUE);
glBindTextureUnit(0, node->normalMapID);
glBindTextureUnit(1, node->diffuseID);
glBindVertexArray(node->vertexArrayObjectID);
glDrawElements(GL_TRIANGLES, node->VAOIndexCount, GL_UNSIGNED_INT, nullptr);
}
@@ -373,11 +386,11 @@ void renderNode(SceneNode* node) {
}
void renderTexture(SceneNode *node) {
auto orthoMatrix = glm::ortho(0.0f, static_cast<float>(windowWidth), 0.0f, static_cast<float>(windowHeight));
GLint orthoLoc = textureShader->getUniformFromName("orthoMatrix");
glUniformMatrix4fv(orthoLoc, 1, GL_FALSE, glm::value_ptr(orthoMatrix));
if (node->nodeType == FLAT_GEOMETRY) {
glBindTextureUnit(0, node->textureID);
auto orthoMatrix = glm::ortho(0.0f, static_cast<float>(windowWidth), 0.0f, static_cast<float>(windowHeight));
GLint orthoLoc = textureShader->getUniformFromName("orthoMatrix");
glUniformMatrix4fv(orthoLoc, 1, GL_FALSE, glm::value_ptr(orthoMatrix));
glBindTextureUnit(4, node->textureID);
glBindVertexArray(node->vertexArrayObjectID);
glDrawElements(GL_TRIANGLES, node->VAOIndexCount, GL_UNSIGNED_INT, nullptr);
}

View File

@@ -71,6 +71,8 @@ struct SceneNode {
// normal map texture id
unsigned int normalMapID;
unsigned int diffuseID;
};
SceneNode* createSceneNode();