From 5577ab0f0bdd5837b1b2f13044bf495736abcd55 Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Sat, 19 Sep 2026 20:08:24 -0400 Subject: [PATCH] This code demonstrates the bug in framebuffers with the shadows. --- 33-shadow-mapping/config.json | 8 +--- 33-shadow-mapping/src/framebuffer.cpp | 66 ++++++++++----------------- 33-shadow-mapping/src/framebuffer.hpp | 10 ++-- 33-shadow-mapping/src/main.cpp | 2 +- 33-shadow-mapping/src/scene.cpp | 22 ++++++--- 33-shadow-mapping/src/screen.cpp | 2 +- 33-shadow-mapping/src/screen.hpp | 1 + 7 files changed, 50 insertions(+), 61 deletions(-) diff --git a/33-shadow-mapping/config.json b/33-shadow-mapping/config.json index c301f45..833a5a3 100644 --- a/33-shadow-mapping/config.json +++ b/33-shadow-mapping/config.json @@ -59,10 +59,6 @@ "directory": "assets", "model_path": "window.glb" }, - "human": { - "directory": "../assets", - "model_path": "human.glb" - }, "light_bulb": { "directory": "assets", "model_path": "light_bulb.glb" @@ -77,7 +73,7 @@ "rotation": {"angle": 0.0, "axes": [1.0, 1.0, 1.0]}, "scale": 1.0, "material": "shiny"}, - {"model": "human", "position": [1.28, 0.0, 1.33], + {"model": "marble_cube", "position": [1.28, 0.0, 1.33], "rotation": {"angle": 0.0, "axes": [1.0, 1.0, 1.0]}, "scale": 1.0, "material": "default"}, @@ -85,7 +81,7 @@ "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], + {"model": "marble_cube", "position": [3.13, 0.80, 3.04], "rotation": {"angle": 0.0, "axes": [1.0, 1.0, 1.0]}, "scale": 1.0, "material": "shiny"}, diff --git a/33-shadow-mapping/src/framebuffer.cpp b/33-shadow-mapping/src/framebuffer.cpp index 4d7a116..8055e8c 100644 --- a/33-shadow-mapping/src/framebuffer.cpp +++ b/33-shadow-mapping/src/framebuffer.cpp @@ -3,70 +3,52 @@ #include void FrameBuffer::init() { - // target_fb configuration - // ------------------------- glGenFramebuffers(1, &target_fb); glBindFramebuffer(GL_FRAMEBUFFER, target_fb); + glGenTextures(1, &texture_color_buffer); - // create the multisamples color attachment texture - glGenTextures(1, &texture_multi); - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture_multi); - glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGB, SCR_WIDTH, SCR_HEIGHT, GL_TRUE); - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, texture_multi, 0); - - // create a renderbuffer object for depth and stencil attachment (we won't be sampling these) - glGenRenderbuffers(1, &target_rbo); - glBindRenderbuffer(GL_RENDERBUFFER, target_rbo); - glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, SCR_WIDTH, SCR_HEIGHT); // use a single renderbuffer object for both a depth AND stencil buffer. - glBindRenderbuffer(GL_RENDERBUFFER, 0); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, target_rbo); // now actually attach it - // now that we actually created the target_fb and added all attachments we want to check if it is actually complete now - - dbc::check(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, "Frame buffer not complete."); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - // intermediate fbo here - glGenFramebuffers(1, &intermediate_fbo); - glBindFramebuffer(GL_FRAMEBUFFER, intermediate_fbo); - - // create a color attachment texture - glGenTextures(1, &texture_buffer); - glBindTexture(GL_TEXTURE_2D, texture_buffer); + glBindTexture(GL_TEXTURE_2D, texture_color_buffer); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_buffer, 0); - dbc::check(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, "Frame buffer not complete."); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_color_buffer, 0); + + glGenRenderbuffers(1, &target_rbo); + glBindRenderbuffer(GL_RENDERBUFFER, target_rbo); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, SCR_WIDTH, SCR_HEIGHT); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, target_rbo); + + dbc::check(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, "Failed to init framebuffer."); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + invariant(); } void FrameBuffer::begin() { - // target_fb stuff here glBindFramebuffer(GL_FRAMEBUFFER, target_fb); glEnable(GL_DEPTH_TEST); - - glClearColor(0.1f, 0.1f, 0.1f, 1.0f); + glClearColor(0.0f, 1.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } void FrameBuffer::commit() { - // disable the frame buffer - glBindFramebuffer(GL_READ_FRAMEBUFFER, target_fb); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, intermediate_fbo); - glBlitFramebuffer(0, 0, SCR_WIDTH, SCR_HEIGHT, 0, 0, SCR_WIDTH, SCR_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST); glBindFramebuffer(GL_FRAMEBUFFER, 0); + glDisable(GL_DEPTH_TEST); + glClearColor(0.0f, 0.0f, 1.0, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); } void FrameBuffer::draw(Screen& screen) { - glClearColor(0.0f, 1.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); - glDisable(GL_DEPTH_TEST); - screen.shader.use(); glBindVertexArray(screen.target_VAO); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, texture_buffer); + glActiveTexture(GL_TEXTURE0 + screen.texture_id); + glBindTexture(GL_TEXTURE_2D, texture_color_buffer); glDrawArrays(GL_TRIANGLES, 0, 6); } + +void FrameBuffer::invariant() { + dbc::check(target_fb != UINT_MAX, "target_fb not initialized"); + dbc::check(texture_color_buffer != UINT_MAX, "texture_color_buffer not initialized"); +} diff --git a/33-shadow-mapping/src/framebuffer.hpp b/33-shadow-mapping/src/framebuffer.hpp index 10bee23..21c54e4 100644 --- a/33-shadow-mapping/src/framebuffer.hpp +++ b/33-shadow-mapping/src/framebuffer.hpp @@ -4,14 +4,14 @@ #include "screen.hpp" struct FrameBuffer { - unsigned int target_fb = 0; - unsigned int intermediate_fbo = 0; - unsigned int target_rbo = 0; - unsigned int texture_buffer = 0; - unsigned int texture_multi = 0; + unsigned int target_fb = UINT_MAX; + unsigned int target_rbo = UINT_MAX; + unsigned int texture_color_buffer = UINT_MAX; + void init(); void begin(); void commit(); void draw(Screen& screen); + void invariant(); }; diff --git a/33-shadow-mapping/src/main.cpp b/33-shadow-mapping/src/main.cpp index 77dec1b..eae7f13 100644 --- a/33-shadow-mapping/src/main.cpp +++ b/33-shadow-mapping/src/main.cpp @@ -135,7 +135,7 @@ void update(GLFWwindow* window, std::shared_ptr scene) { void render(GLFWwindow* window, std::shared_ptr scene, Text &text) { scene->render(window); - text.render(text_content, 25.0f, 25.0f, 1.0f, glm::vec3(1.0, 0.0f, 0.0f)); + // 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/scene.cpp b/33-shadow-mapping/src/scene.cpp index 5c72987..b711d3f 100644 --- a/33-shadow-mapping/src/scene.cpp +++ b/33-shadow-mapping/src/scene.cpp @@ -53,6 +53,8 @@ void Scene::render_scene(GLFWwindow* window, Shader& with_shader) { } void Scene::render_shadows(GLFWwindow* window) { + glClearColor(0.1f, 0.1f, 0.1f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // temporarily use the config.json positioned even though this is doing a directional auto& light_pos = light.positioned.at(0).position; @@ -80,11 +82,9 @@ void Scene::render_shadows(GLFWwindow* window) { 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); + // set depth_map on TEXTURE0 glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, depth_map); @@ -95,14 +95,23 @@ void Scene::render(GLFWwindow* window) { with_shader.setVec3("lightPos", light.positioned.at(0).position); with_shader.setMat4("lightSpaceMatrix", light_space); + framebuffer.begin(); + + render_scene(window, with_shader); + + framebuffer.commit(); + framebuffer.draw(screen); + if(debug_on) { render_debug(window); - } else { - render_scene(window, with_shader); } } void Scene::render_debug(GLFWwindow* window) { + // set depth_map on TEXTURE0 + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, depth_map); + depth_dbg_shader.use(); depth_dbg_shader.setInt("shadowMap", 0); depth_dbg_shader.setFloat("near_plane", depth_near_plane); @@ -134,7 +143,9 @@ void Scene::cleanup() { void Scene::init_shadows() { glGenFramebuffers(1, &depth_FBO); + glBindFramebuffer(GL_FRAMEBUFFER, 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); @@ -142,7 +153,6 @@ void Scene::init_shadows() { 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); diff --git a/33-shadow-mapping/src/screen.cpp b/33-shadow-mapping/src/screen.cpp index cf420ac..f103dcc 100644 --- a/33-shadow-mapping/src/screen.cpp +++ b/33-shadow-mapping/src/screen.cpp @@ -4,7 +4,7 @@ void Screen::init() { shader.use(); - shader.setInt("screenTexture", 0); + shader.setInt("screenTexture", texture_id); glGenVertexArrays(1, &target_VAO); glGenBuffers(1, &target_VBO); diff --git a/33-shadow-mapping/src/screen.hpp b/33-shadow-mapping/src/screen.hpp index c7a3229..7026016 100644 --- a/33-shadow-mapping/src/screen.hpp +++ b/33-shadow-mapping/src/screen.hpp @@ -5,6 +5,7 @@ struct Screen { Shader shader; unsigned int target_VAO = 0; unsigned int target_VBO = 0; + unsigned int texture_id = 10; float vertices[24] = { // vertex attributes for a quad that fills the entire screen in Normalized Device Coordinates.