From 482ec07fb37e5da5a27aa1bed1fb21d8852703e9 Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Sat, 19 Sep 2026 15:09:46 -0400 Subject: [PATCH] Shadows working but look dumb. The issue so far was that framebuffer.cpp interferes with the framebuffer used to create the shadow map. --- 26-geometry-shaders/config.json | 14 +- 33-shadow-mapping/config.json | 16 +- 33-shadow-mapping/shaders/33-depth.frag.glsl | 6 + 33-shadow-mapping/shaders/33-depth.vert.glsl | 10 + .../shaders/33-framebuffers.frag.glsl | 186 ++++-------------- .../shaders/33-framebuffers.vert.glsl | 16 +- .../shaders/33-shadow_dbg.frag.glsl | 22 +++ .../shaders/33-shadow_dbg.vert.glsl | 11 ++ .../shaders/33-shadows.frag.glsl | 1 - .../shaders/33-shadows.vert.glsl | 4 - 33-shadow-mapping/src/components.hpp | 4 +- 33-shadow-mapping/src/framebuffer.cpp | 2 +- 33-shadow-mapping/src/main.cpp | 9 +- 33-shadow-mapping/src/mesh.cpp | 13 +- 33-shadow-mapping/src/scene.cpp | 108 ++++++++-- 33-shadow-mapping/src/scene.hpp | 40 +++- 33-shadow-mapping/src/shader.cpp | 2 +- 33-shadow-mapping/src/shader.hpp | 1 + 33-shadow-mapping/tests/model_tests.cpp | 2 +- 19 files changed, 261 insertions(+), 206 deletions(-) create mode 100644 33-shadow-mapping/shaders/33-depth.frag.glsl create mode 100644 33-shadow-mapping/shaders/33-depth.vert.glsl create mode 100644 33-shadow-mapping/shaders/33-shadow_dbg.frag.glsl create mode 100644 33-shadow-mapping/shaders/33-shadow_dbg.vert.glsl delete mode 100644 33-shadow-mapping/shaders/33-shadows.frag.glsl delete mode 100644 33-shadow-mapping/shaders/33-shadows.vert.glsl diff --git a/26-geometry-shaders/config.json b/26-geometry-shaders/config.json index 4bf8839..3d910ae 100644 --- a/26-geometry-shaders/config.json +++ b/26-geometry-shaders/config.json @@ -43,9 +43,9 @@ } }, "models": { - "marble_cube": { - "directory": "assets", - "model_path": "marble_cube.glb" + "backpack": { + "directory": "../assets/backpack/", + "model_path": "backpack.obj" }, "metal_floor": { "directory": "assets", @@ -61,14 +61,10 @@ } }, "things": [ - {"model": "marble_cube", "position": [1.5, 0.0, -1.0], + {"model": "backpack", "position": [1.5, 0.0, -1.0], "rotation": {"angle": 0.0, "axes": [1.0, 1.0, 1.0]}, "scale": 3.0, - "material": "default"}, - {"model": "marble_cube", "position": [1.5, 0.25, 0.0], - "rotation": {"angle": 90.0, "axes": [1.0,0.0,0.0]}, - "scale": 1.0, - "material": "shiny"} + "material": "default"} ], "camera": { "position": [0.0, 0.1, 3.0], diff --git a/33-shadow-mapping/config.json b/33-shadow-mapping/config.json index 08e65e0..c301f45 100644 --- a/33-shadow-mapping/config.json +++ b/33-shadow-mapping/config.json @@ -81,7 +81,11 @@ "rotation": {"angle": 0.0, "axes": [1.0, 1.0, 1.0]}, "scale": 1.0, "material": "default"}, - {"model": "human", "position": [-0.032, 0.0, 0.11], + {"model": "marble_cube", "position": [1.28, 0.0, 1.85], + "rotation": {"angle": 0.0, "axes": [1.0, 1.0, 1.0]}, + "scale": 1.0, + "material": "shiny"}, + {"model": "human", "position": [3.13, 0.80, 3.04], "rotation": {"angle": 0.0, "axes": [1.0, 1.0, 1.0]}, "scale": 1.0, "material": "shiny"}, @@ -92,11 +96,7 @@ {"model": "window", "position": [1.75, 0.25, 0.25], "rotation": {"angle": 90.0, "axes": [1.0,0.0,0.0]}, "scale": 1.0, - "material": "shiny"}, - {"model": "light_bulb", "position": [3.84, 3.45, 4.73], - "rotation": {"angle": 0.0, "axes": [1.0,1.0,1.0]}, - "scale": 0.03, - "material": "default"} + "material": "shiny"} ], "camera": { "position": [0.0, 0.1, 3.0], @@ -110,8 +110,8 @@ ], "positioned": [ { - "position": [3.84, 3.45, 4.73], - "direction":[-0.5, -1.0, -0.3], + "position": [-2.0, 4.0, -1.0], + "direction":[0.0, 0.0, 0.0], "ambient":[0.3, 0.3, 0.3], "diffuse":[0.9, 0.9, 0.9], "specular":[1.0, 1.0, 1.0], diff --git a/33-shadow-mapping/shaders/33-depth.frag.glsl b/33-shadow-mapping/shaders/33-depth.frag.glsl new file mode 100644 index 0000000..e494509 --- /dev/null +++ b/33-shadow-mapping/shaders/33-depth.frag.glsl @@ -0,0 +1,6 @@ +#version 330 core + +void main() +{ + // gl_FragDepth = gl_FragCoord.z; +} diff --git a/33-shadow-mapping/shaders/33-depth.vert.glsl b/33-shadow-mapping/shaders/33-depth.vert.glsl new file mode 100644 index 0000000..72dea9a --- /dev/null +++ b/33-shadow-mapping/shaders/33-depth.vert.glsl @@ -0,0 +1,10 @@ +#version 330 core +layout (location = 0) in vec3 aPos; + +uniform mat4 lightSpaceMatrix; +uniform mat4 model; + +void main() +{ + gl_Position = lightSpaceMatrix * model * vec4(aPos, 1.0); +} diff --git a/33-shadow-mapping/shaders/33-framebuffers.frag.glsl b/33-shadow-mapping/shaders/33-framebuffers.frag.glsl index 73c218f..7602e8b 100644 --- a/33-shadow-mapping/shaders/33-framebuffers.frag.glsl +++ b/33-shadow-mapping/shaders/33-framebuffers.frag.glsl @@ -1,168 +1,58 @@ #version 330 core -struct Material { - sampler2D diffuse; - sampler2D specular; - float shininess; -}; - out vec4 FragColor; + in vec3 FragPos; in vec3 Normal; in vec2 TexCoords; +in vec4 FragPosLightSpace; +uniform vec3 lightPos; uniform vec3 viewPos; -uniform Material material; +uniform sampler2D shadowMap; +uniform sampler2D texture_diffuse1; +uniform sampler2D texture_specular1; -struct DirLight { - vec3 direction; - vec3 ambient; - vec3 diffuse; - vec3 specular; -}; - -struct PointLight { - vec3 position; - vec3 ambient; - vec3 diffuse; - vec3 specular; - float constant; - float linear; - float quadratic; -}; - -struct SpotLight { - vec3 direction; - vec3 position; - vec3 diffuse; - vec3 specular; - vec3 ambient; - - float constant; - float linear; - float quadratic; - float cut_off; - float outer_cut_off; -}; - - -#define MAX_LIGHTS 4 -uniform int pointLightCount = 0; -uniform PointLight pointLights[MAX_LIGHTS]; - -uniform int dirLightCount = 0; -uniform DirLight dirLights[MAX_LIGHTS]; - -uniform int spotLightCount = 0; -uniform SpotLight spotLights[MAX_LIGHTS]; - - -float near = 0.1; -float far = 100.0; - -vec4 CalcDirLight(vec4 mat_tex, vec4 spec_tex, DirLight light, vec3 normal, vec3 viewDir) +float ShadowCalculation(vec4 fragPosLightSpace, float bias) { - vec3 lightDir = normalize(-light.direction); - // diffuse shading - float diff = max(dot(normal, lightDir), 0.0); + // perform perspective divide + vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w; + // transform to [0,1] range + projCoords = projCoords * 0.5 + 0.5; + // get closest depth value from light's perspective (using [0,1] range fragPosLight as coords) + float closestDepth = texture(shadowMap, projCoords.xy).r; + // get depth of current fragment from light's perspective + float currentDepth = projCoords.z; + // check whether current frag pos is in shadow - // specular shading - vec3 reflectDir = reflect(-lightDir, normal); - float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); + float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0; - vec4 ambient = vec4(light.ambient, 1.0) * mat_tex; - vec4 diffuse = vec4(light.diffuse, 1.0) * diff * mat_tex; - vec4 specular = vec4(light.specular, 1.0) * spec * spec_tex; - - return ambient + diffuse + specular; -} - -vec4 CalcPointLight(vec4 mat_tex, vec4 spec_tex, PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir) -{ - vec3 lightDir = normalize(light.position - fragPos); - - // diffuse shading - float diff = max(dot(normal, lightDir), 0.0); - - // specular shading - vec3 reflectDir = reflect(-lightDir, normal); - float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); - - // attenuation - float distance = length(light.position - fragPos); - float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance)); - - vec4 ambient = vec4(light.ambient, 1.0) * mat_tex; - vec4 diffuse = vec4(light.diffuse, 1.0) * diff * mat_tex; - vec4 specular = vec4(light.specular, 1.0) * spec * spec_tex; - - ambient *= attenuation; - diffuse *= attenuation; - specular *= attenuation; - - return ambient + diffuse + specular; -} - -vec4 CalcSpotLight(vec4 mat_tex, vec4 spec_tex, SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir) -{ - vec3 lightDir = normalize(light.position - fragPos); - - // diffuse shading - float diff = max(dot(normal, lightDir), 0.0); - - // specular shading - vec3 reflectDir = reflect(-lightDir, normal); - float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); - - // attenuation - float distance = length(light.position - fragPos); - float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance)); - - vec4 ambient = vec4(light.ambient, 1.0) * mat_tex; - vec4 diffuse = vec4(light.diffuse, 1.0) * diff * mat_tex; - vec4 specular = vec4(light.specular, 1.0) * spec * spec_tex; - - float theta = dot(lightDir, normalize(-light.direction)); - float epsilon = light.cut_off - light.outer_cut_off; - float intensity = clamp((theta - light.outer_cut_off) / epsilon, 0.0, 1.0); - diffuse *= intensity; - specular *= intensity; - - ambient *= attenuation; - diffuse *= attenuation; - specular *= attenuation; - - return ambient + diffuse + specular; -} - -float LinearizeDepth(float depth) -{ - float ndc = depth * 2.0 - 1.0; - return (2.0 * near * far) / (far + near - ndc * (far - near)); + return shadow; } void main() { - vec4 mat_tex = texture(material.diffuse, TexCoords); - vec4 spec_tex = texture(material.specular, TexCoords); - - vec3 norm = normalize(Normal); + vec3 color = texture(texture_diffuse1, TexCoords).rgb; + vec3 normal = normalize(Normal); + vec3 lightColor = vec3(0.7); + // ambient + vec3 ambient = 0.3 * lightColor; + // diffuse + vec3 lightDir = normalize(lightPos - FragPos); + float diff = max(dot(lightDir, normal), 0.0); + vec3 diffuse = diff * lightColor; + // specular vec3 viewDir = normalize(viewPos - FragPos); + vec3 reflectDir = reflect(-lightDir, normal); + float spec = 0.0; + vec3 halfwayDir = normalize(lightDir + viewDir); + spec = pow(max(dot(normal, halfwayDir), 0.0), 64.0); + vec3 specular = spec * lightColor; + // calculate shadow - // kick it off with the first dirlight - vec4 result = CalcDirLight(mat_tex, spec_tex, dirLights[0], norm, viewDir); + float bias = max(0.05 * (1.0 - dot(normal, lightDir)), 0.005); + float shadow = ShadowCalculation(FragPosLightSpace, bias); - // then augment with more (off by one) - for(int i = 1; i < dirLightCount; i++) { - result += CalcDirLight(mat_tex, spec_tex, dirLights[i], norm, viewDir); - } + vec3 lighting = (ambient + (1.0 - shadow) * (diffuse + specular)) * color; - for(int i = 0; i < pointLightCount; i++) { - result += CalcPointLight(mat_tex, spec_tex, pointLights[i], norm, FragPos, viewDir); - } - - for(int i = 0; i < spotLightCount; i++) { - result += CalcSpotLight(mat_tex, spec_tex, spotLights[i], norm, FragPos, viewDir); - } - - FragColor = result; + FragColor = vec4(lighting, 1.0); } diff --git a/33-shadow-mapping/shaders/33-framebuffers.vert.glsl b/33-shadow-mapping/shaders/33-framebuffers.vert.glsl index e1c881f..aa32b3f 100644 --- a/33-shadow-mapping/shaders/33-framebuffers.vert.glsl +++ b/33-shadow-mapping/shaders/33-framebuffers.vert.glsl @@ -6,16 +6,18 @@ layout (location = 2) in vec2 aTexCoords; out vec3 FragPos; out vec3 Normal; out vec2 TexCoords; +out vec4 FragPosLightSpace; -uniform mat4 model; -uniform mat4 view; uniform mat4 projection; +uniform mat4 view; +uniform mat4 model; +uniform mat4 lightSpaceMatrix; void main() { - vec4 pos = vec4(aPos, 1.0); - gl_Position = projection * view * model * pos; - FragPos = vec3(model * pos); - Normal = transpose(inverse(mat3(model))) * aNormal; - TexCoords = aTexCoords; + FragPos = vec3(model * vec4(aPos, 1.0)); + Normal = transpose(inverse(mat3(model))) * aNormal; + TexCoords = aTexCoords; + FragPosLightSpace = lightSpaceMatrix * vec4(FragPos, 1.0); + gl_Position = projection * view * model * vec4(aPos, 1.0); } diff --git a/33-shadow-mapping/shaders/33-shadow_dbg.frag.glsl b/33-shadow-mapping/shaders/33-shadow_dbg.frag.glsl new file mode 100644 index 0000000..793af71 --- /dev/null +++ b/33-shadow-mapping/shaders/33-shadow_dbg.frag.glsl @@ -0,0 +1,22 @@ +#version 330 core +out vec4 FragColor; + +in vec2 TexCoords; + +uniform sampler2D shadowMap; +uniform float near_plane; +uniform float far_plane; + +// required when using a perspective projection matrix +float LinearizeDepth(float depth) +{ + float z = depth * 2.0 - 1.0; // Back to NDC + return (2.0 * near_plane * far_plane) / (far_plane + near_plane - z * (far_plane - near_plane)); +} + +void main() +{ + float depthValue = texture(shadowMap, TexCoords).r; + // FragColor = vec4(vec3(LinearizeDepth(depthValue) / far_plane), 1.0); // perspective + FragColor = vec4(vec3(depthValue), 1.0); // orthographic +} diff --git a/33-shadow-mapping/shaders/33-shadow_dbg.vert.glsl b/33-shadow-mapping/shaders/33-shadow_dbg.vert.glsl new file mode 100644 index 0000000..38324be --- /dev/null +++ b/33-shadow-mapping/shaders/33-shadow_dbg.vert.glsl @@ -0,0 +1,11 @@ +#version 330 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec2 aTexCoords; + +out vec2 TexCoords; + +void main() +{ + TexCoords = aTexCoords; + gl_Position = vec4(aPos, 1.0); +} diff --git a/33-shadow-mapping/shaders/33-shadows.frag.glsl b/33-shadow-mapping/shaders/33-shadows.frag.glsl deleted file mode 100644 index 5ae7f43..0000000 --- a/33-shadow-mapping/shaders/33-shadows.frag.glsl +++ /dev/null @@ -1 +0,0 @@ -#version 330 core diff --git a/33-shadow-mapping/shaders/33-shadows.vert.glsl b/33-shadow-mapping/shaders/33-shadows.vert.glsl deleted file mode 100644 index 64cfd0f..0000000 --- a/33-shadow-mapping/shaders/33-shadows.vert.glsl +++ /dev/null @@ -1,4 +0,0 @@ -#version 330 core -layout (location = 0) in vec3 aPos; -layout (location = 1) in vec3 aNormal; -layout (location = 2) in vec2 aTexCoords; diff --git a/33-shadow-mapping/src/components.hpp b/33-shadow-mapping/src/components.hpp index 4b55ef6..f6f80e5 100644 --- a/33-shadow-mapping/src/components.hpp +++ b/33-shadow-mapping/src/components.hpp @@ -12,11 +12,9 @@ namespace components { struct Material { glm::vec3 ambient{0.1f,0.1f,0.1f}; float shininess{32.0f}; - unsigned int diffuseMap = 0; - unsigned int specularMap = 0; }; - ENROLL_COMPONENT(Material, ambient, shininess, diffuseMap, specularMap); + ENROLL_COMPONENT(Material, ambient, shininess); struct Light { glm::vec3 position{0.0f, 0.0f, 0.0f}; diff --git a/33-shadow-mapping/src/framebuffer.cpp b/33-shadow-mapping/src/framebuffer.cpp index 4207ad0..4d7a116 100644 --- a/33-shadow-mapping/src/framebuffer.cpp +++ b/33-shadow-mapping/src/framebuffer.cpp @@ -60,7 +60,7 @@ void FrameBuffer::commit() { } void FrameBuffer::draw(Screen& screen) { - glClearColor(1.0f, 0.0f, 0.0f, 1.0f); + glClearColor(0.0f, 1.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glDisable(GL_DEPTH_TEST); diff --git a/33-shadow-mapping/src/main.cpp b/33-shadow-mapping/src/main.cpp index 194c86b..27527d4 100644 --- a/33-shadow-mapping/src/main.cpp +++ b/33-shadow-mapping/src/main.cpp @@ -4,8 +4,10 @@ #include "utils.hpp" #include #include +#include "text.hpp" void framebuffer_size_callback(GLFWwindow *window, int width, int height); + std::string text_content{""}; void init_glfw() { @@ -77,6 +79,10 @@ void process_input(GLFWwindow *window, Scene& scene) { scene.reflect_on = !scene.reflect_on; } + if(glfwGetKey(window, GLFW_KEY_J) == GLFW_PRESS) { + scene.debug_on = !scene.debug_on; + } + if(glfwGetKey(window, GLFW_KEY_H) == GLFW_PRESS) { scene.spawn("human"); glm::vec3 pos = scene.camera.position; @@ -127,10 +133,9 @@ void update(GLFWwindow* window, Scene& scene) { scene.update(); } -void render(GLFWwindow* window, Scene& scene, Text& text) { +void render(GLFWwindow* window, Scene& scene, Text &text) { scene.render(window); text.render(text_content, 25.0f, 25.0f, 1.0f, glm::vec3(1.0, 0.0f, 0.0f)); - glfwSwapBuffers(window); } diff --git a/33-shadow-mapping/src/mesh.cpp b/33-shadow-mapping/src/mesh.cpp index 8a07d4a..c95277b 100644 --- a/33-shadow-mapping/src/mesh.cpp +++ b/33-shadow-mapping/src/mesh.cpp @@ -10,19 +10,20 @@ void Mesh::draw(Shader &shader, bool with_textures) { glBindVertexArray(VAO); glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0); glBindVertexArray(0); - glActiveTexture(GL_TEXTURE0); } void Mesh::apply_textures(const Shader& shader) { - for(unsigned int i = 0; i < textures.size(); i++) { - Texture& texture = textures[i]; + int texture_i = 1; + for(auto& texture : textures) { texture.uniform_id = glGetUniformLocation(shader.ID, texture.target.c_str()); - glActiveTexture(GL_TEXTURE0 + i); + if(texture.uniform_id == -1) continue; - // move this to setup_mesh - glUniform1i(texture.uniform_id, i); + glActiveTexture(GL_TEXTURE0 + texture_i); glBindTexture(GL_TEXTURE_2D, texture.id); + glUniform1i(texture.uniform_id, texture_i); + + texture_i++; } } diff --git a/33-shadow-mapping/src/scene.cpp b/33-shadow-mapping/src/scene.cpp index 1efafcd..5c72987 100644 --- a/33-shadow-mapping/src/scene.cpp +++ b/33-shadow-mapping/src/scene.cpp @@ -36,32 +36,94 @@ void Scene::draw_thing(Shader& with_shader, Thing& thing) thing.model.draw(with_shader, !reflect_on); } -void Scene::render(GLFWwindow* window) { +void Scene::render_scene(GLFWwindow* window, Shader& with_shader) { glm::mat4 view = camera.look_at(); - glm::mat4 projection = glm::mat4(1.0f); - auto& with_shader = reflect_on ? reflect_shader : shader; // fov, aspect, near plane, far plane - projection = glm::perspective(glm::radians(camera.fov), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f); - - framebuffer.begin(); + projection = glm::perspective(glm::radians(camera.fov), (float)SCR_WIDTH / (float)SCR_HEIGHT, near_plane, far_plane); // render the scene with_shader.use(); with_shader.setMat4("view", view); with_shader.setMat4("projection", projection); - with_shader.setVec3("cameraPos", camera.position); - with_shader.setFloat("time", glfwGetTime()); for(auto& thing : things) { draw_thing(with_shader, thing); } +} - render_skybox(projection); +void Scene::render_shadows(GLFWwindow* window) { + // temporarily use the config.json positioned even though this is doing a directional + auto& light_pos = light.positioned.at(0).position; - framebuffer.commit(); + glm::mat4 proj = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, depth_near_plane, depth_far_plane); + glm::mat4 view = glm::lookAt(light_pos, glm::vec3(0.0f), glm::vec3(0.0f, 1.0f, 0.0f)); - framebuffer.draw(screen); + light_space = proj * view; + + depth_shader.use(); + depth_shader.setMat4("lightSpaceMatrix", light_space); + depth_shader.setFloat("near_plane", depth_near_plane); + depth_shader.setFloat("far_plane", depth_far_plane); + + glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT); + glBindFramebuffer(GL_FRAMEBUFFER, depth_FBO); + glClear(GL_DEPTH_BUFFER_BIT); + + render_scene(window, depth_shader); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +} + +void Scene::render(GLFWwindow* window) { + auto& with_shader = reflect_on ? reflect_shader : shader; + + glClearColor(0.1f, 0.1f, 0.1f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + render_shadows(window); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, depth_map); + + with_shader.use(); + with_shader.setInt("shadowMap", 0); + // NOTE: in the shader is it viewPos or cameraPos? + with_shader.setVec3("viewPos", camera.position); + with_shader.setVec3("lightPos", light.positioned.at(0).position); + with_shader.setMat4("lightSpaceMatrix", light_space); + + if(debug_on) { + render_debug(window); + } else { + render_scene(window, with_shader); + } +} + +void Scene::render_debug(GLFWwindow* window) { + depth_dbg_shader.use(); + depth_dbg_shader.setInt("shadowMap", 0); + depth_dbg_shader.setFloat("near_plane", depth_near_plane); + depth_dbg_shader.setFloat("far_plane", depth_far_plane); + + glBindVertexArray(quadVAO); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + glBindVertexArray(0); +} + +void Scene::init_debug() { + // setup plane VAO + glGenVertexArrays(1, &quadVAO); + glGenBuffers(1, &quadVBO); + glBindVertexArray(quadVAO); + glBindBuffer(GL_ARRAY_BUFFER, quadVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); } void Scene::cleanup() { @@ -70,7 +132,28 @@ void Scene::cleanup() { skybox_shader.cleanup(); } +void Scene::init_shadows() { + glGenFramebuffers(1, &depth_FBO); + glGenTextures(1, &depth_map); + glBindTexture(GL_TEXTURE_2D, depth_map); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, SHADOW_WIDTH, SHADOW_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + + glBindFramebuffer(GL_FRAMEBUFFER, depth_FBO); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_map, 0); + glDrawBuffer(GL_NONE); + glReadBuffer(GL_NONE); + + dbc::check(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, "Frame buffer not complete."); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); +} + void Scene::init_skybox() { + dbc::sentinel("DISABLED, do not run me."); glBindVertexArray(skyboxVAO); glBindBuffer(GL_ARRAY_BUFFER, skyboxVBO); glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices, GL_STATIC_DRAW); @@ -122,7 +205,8 @@ void Scene::load_skybox_textures() { glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); } -void Scene::render_skybox(const glm::mat4& projection) { +void Scene::render_skybox() { + dbc::sentinel("DISABLED, do not run me."); glDepthFunc(GL_LEQUAL); skybox_shader.use(); glm::mat4 view = glm::mat4(glm::mat3(camera.look_at())); diff --git a/33-shadow-mapping/src/scene.hpp b/33-shadow-mapping/src/scene.hpp index 4ebe465..b7d1279 100644 --- a/33-shadow-mapping/src/scene.hpp +++ b/33-shadow-mapping/src/scene.hpp @@ -15,7 +15,6 @@ #include #include #include "config.hpp" -#include "text.hpp" struct Thing { std::string name; @@ -45,8 +44,36 @@ struct Scene { unsigned int skyboxVAO = UINT_MAX; unsigned int skyboxVBO = UINT_MAX; unsigned int skybox_texture_id = UINT_MAX; + glm::mat4 projection = glm::mat4(1.0f); bool reflect_on = false; + // shadow stuff + Shader depth_shader{{"shaders/33-depth.vert.glsl", "shaders/33-depth.frag.glsl", ""}}; + Shader depth_dbg_shader{{"shaders/33-shadow_dbg.vert.glsl", "shaders/33-shadow_dbg.frag.glsl", ""}}; + unsigned int depth_FBO = UINT_MAX; + unsigned int depth_map = UINT_MAX; + const unsigned int SHADOW_WIDTH = 1024, SHADOW_HEIGHT = 1024; + float near_plane = 1.0f; + float far_plane = 100.0f; + + float depth_near_plane = 1.0f; + float depth_far_plane = 7.5f; + + glm::mat4 light_space; + bool debug_on = false; + + float quadVertices[20] = { + // positions // texture Coords + -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, + }; + + + unsigned int quadVAO = UINT_MAX; + unsigned int quadVBO = UINT_MAX; + Scene(components::Scene& config): shader{config.shader}, reflect_shader{config.reflect_shader}, @@ -90,7 +117,9 @@ struct Scene { framebuffer.init(); screen.init(); - init_skybox(); + // init_skybox(); + init_shadows(); + init_debug(); } void update(); @@ -98,7 +127,12 @@ struct Scene { void render(GLFWwindow* window); void cleanup(); void init_skybox(); + void init_shadows(); + void init_debug(); void load_skybox_textures(); - void render_skybox(const glm::mat4& projection); + void render_skybox(); void spawn(const std::string& name); + void render_scene(GLFWwindow* window, Shader& with_shader); + void render_shadows(GLFWwindow* window); + void render_debug(GLFWwindow* window); }; diff --git a/33-shadow-mapping/src/shader.cpp b/33-shadow-mapping/src/shader.cpp index cb45a3e..c79ecc8 100644 --- a/33-shadow-mapping/src/shader.cpp +++ b/33-shadow-mapping/src/shader.cpp @@ -62,7 +62,7 @@ unsigned int Shader::load_shader(const std::string& filename, GLenum shader_type } -Shader::Shader(components::Shader config) { +Shader::Shader(components::Shader c) : config(c) { dbc::log($F("Loading shaders vert={}, frag={}, geom={}", config.vertex_path, config.frag_path, config.geometry_path)); unsigned int vertex = load_shader(config.vertex_path, GL_VERTEX_SHADER); diff --git a/33-shadow-mapping/src/shader.hpp b/33-shadow-mapping/src/shader.hpp index 59bebb9..c9f4502 100644 --- a/33-shadow-mapping/src/shader.hpp +++ b/33-shadow-mapping/src/shader.hpp @@ -15,6 +15,7 @@ class Shader { public: unsigned int ID = UINT_MAX; + components::Shader config; Shader(components::Shader config); diff --git a/33-shadow-mapping/tests/model_tests.cpp b/33-shadow-mapping/tests/model_tests.cpp index 84b6e71..4199886 100644 --- a/33-shadow-mapping/tests/model_tests.cpp +++ b/33-shadow-mapping/tests/model_tests.cpp @@ -11,7 +11,7 @@ using namespace fuc2; */ namespace model_tests { void test_load_textures() { - Shader shader({"shaders/14-vert.glsl", "shaders/14-frag.glsl", ""}); + Shader shader({"shaders/33-framebuffers.vert.glsl", "shaders/33-framebuffers.frag.glsl", ""}); Model popcorn{"assets", "popcorn_model_a.glb"}; popcorn.draw(shader, true);