From 7060c08217cfd0cbaf1727559c6d344d78774952 Mon Sep 17 00:00:00 2001 From: Jack Christensen Date: Wed, 14 Aug 2024 02:16:53 -0400 Subject: [PATCH] Refactor, setup FBO, and render into ImGui window --- imgui.ini | 18 +++++--- include/Uniforms.h | 4 +- include/scene.h | 4 ++ shaders/fragment.glsl | 2 +- shaders/quad_fragment.glsl | 12 ++++++ shaders/quad_vertex.glsl | 12 ++++++ shaders/vertex.glsl | 22 +++++----- source/Uniforms.cpp | 86 +++++++++++++++++++------------------- source/fbo.cpp | 2 + source/scene.cpp | 71 +++++++++++++++++++++++++++++-- 10 files changed, 166 insertions(+), 67 deletions(-) create mode 100644 shaders/quad_fragment.glsl create mode 100644 shaders/quad_vertex.glsl diff --git a/imgui.ini b/imgui.ini index 3984d9f..29d1fe7 100644 --- a/imgui.ini +++ b/imgui.ini @@ -5,7 +5,7 @@ Collapsed=0 [Window][Terrain Controls] Pos=0,19 -Size=1280,86 +Size=1498,94 Collapsed=0 DockId=0x00000001,0 @@ -19,11 +19,17 @@ Collapsed=0 [Window][TerraVisor] Pos=0,0 -Size=1280,720 +Size=1498,720 Collapsed=0 -[Docking][Data] -DockSpace ID=0x6F42A598 Window=0xE80F322C Pos=0,19 Size=1280,701 Split=Y - DockNode ID=0x00000001 Parent=0x6F42A598 SizeRef=1280,86 Selected=0xF69494A7 - DockNode ID=0x00000002 Parent=0x6F42A598 SizeRef=1280,613 CentralNode=1 +[Window][Scene Window] +Pos=0,115 +Size=1498,605 +Collapsed=0 +DockId=0x00000002,0 + +[Docking][Data] +DockSpace ID=0x6F42A598 Window=0xE80F322C Pos=0,19 Size=1498,701 Split=Y Selected=0x9F2D9299 + DockNode ID=0x00000001 Parent=0x6F42A598 SizeRef=1280,94 Selected=0xF69494A7 + DockNode ID=0x00000002 Parent=0x6F42A598 SizeRef=1280,605 CentralNode=1 Selected=0x9F2D9299 diff --git a/include/Uniforms.h b/include/Uniforms.h index 4762dde..352e0a9 100644 --- a/include/Uniforms.h +++ b/include/Uniforms.h @@ -11,8 +11,8 @@ namespace Uniforms //This structure mirrors the uniform block declared in the shader struct SceneUniforms { - glm::mat4 PV; //camera projection * view matrix - glm::vec4 eye_w = glm::vec4(0.0f, 0.0f, 3.0f, 1.0f); //world-space eye position + glm::mat4 PV; //camera projection * view matrix + glm::vec4 eye_w = glm::vec4(0.0f, 0.0f, 3.0f, 1.0f); //world-space eye position }; struct LightUniforms diff --git a/include/scene.h b/include/scene.h index ef275b4..cf87509 100644 --- a/include/scene.h +++ b/include/scene.h @@ -22,11 +22,15 @@ class Scene { private: void InitBuffers(); + void InitQuadBuffers(); void InitShaders(); FBO fbo_; + FBO post_fbo_; GLuint shader_program_; + GLuint quad_shader_program_; GLuint vao_; + GLuint quad_vao_; float angle_; float scale_; float aspect_; diff --git a/shaders/fragment.glsl b/shaders/fragment.glsl index 3a80bde..e6ae42a 100644 --- a/shaders/fragment.glsl +++ b/shaders/fragment.glsl @@ -54,6 +54,6 @@ void main(void) // vec4 specular_term = atten*ks*Ls*pow(max(0.0, dot(rw, vw)), shininess); // fragcolor = ambient_term + diffuse_term + specular_term; - fragcolor = vec4(1.0, 0.0, 0.0, 1.0); + fragcolor = vec4(0.0, 0.0, 1.0, 1.0); } diff --git a/shaders/quad_fragment.glsl b/shaders/quad_fragment.glsl new file mode 100644 index 0000000..7a19693 --- /dev/null +++ b/shaders/quad_fragment.glsl @@ -0,0 +1,12 @@ +#version 330 core +out vec4 FragColor; + +in vec2 TexCoord; + +uniform sampler2D screenTexture; + +void main() +{ + FragColor = texture(screenTexture, TexCoord); + //FragColor = vec4(vec3(1.0 - texture(screenTexture, TexCoord)), 1.0); +} diff --git a/shaders/quad_vertex.glsl b/shaders/quad_vertex.glsl new file mode 100644 index 0000000..7a4f575 --- /dev/null +++ b/shaders/quad_vertex.glsl @@ -0,0 +1,12 @@ +#version 330 core +layout(location = 0) in vec3 pos_attrib; //this variable holds the position of mesh vertices +layout(location = 1) in vec2 tex_coord_attrib; +layout(location = 2) in vec3 normal_attrib; + +out vec2 TexCoord; + +void main() +{ + gl_Position = vec4(pos_attrib.xy, 0.0, 1.0); + TexCoord = tex_coord_attrib; +} diff --git a/shaders/vertex.glsl b/shaders/vertex.glsl index c847c18..74905dd 100644 --- a/shaders/vertex.glsl +++ b/shaders/vertex.glsl @@ -4,8 +4,8 @@ layout(location = 1) uniform float time; layout(std140, binding = 0) uniform SceneUniforms { - mat4 PV; //camera projection * view matrix - vec4 eye_w; //world-space eye position + mat4 PV; //camera projection * view matrix + vec4 eye_w; //world-space eye position }; layout(location = 0) in vec3 pos_attrib; //this variable holds the position of mesh vertices @@ -14,17 +14,17 @@ layout(location = 2) in vec3 normal_attrib; out VertexData { - vec2 tex_coord; - vec3 pw; //world-space vertex position - vec3 nw; //world-space normal vector + vec2 tex_coord; + vec3 pw; //world-space vertex position + vec3 nw; //world-space normal vector } outData; void main(void) { - gl_Position = PV*M*vec4(pos_attrib, 1.0); //transform vertices and send result into pipeline - - //Use dot notation to access members of the interface block - outData.tex_coord = tex_coord_attrib; //send tex_coord to fragment shader - outData.pw = vec3(M*vec4(pos_attrib, 1.0)); //world-space vertex position - outData.nw = vec3(M*vec4(normal_attrib, 0.0)); //world-space normal vector + gl_Position = PV*M*vec4(pos_attrib, 1.0); //transform vertices and send result into pipeline + + //Use dot notation to access members of the interface block + outData.tex_coord = tex_coord_attrib; //send tex_coord to fragment shader + outData.pw = vec3(M*vec4(pos_attrib, 1.0)); //world-space vertex position + outData.nw = vec3(M*vec4(normal_attrib, 0.0)); //world-space normal vector } \ No newline at end of file diff --git a/source/Uniforms.cpp b/source/Uniforms.cpp index e88588b..04d6c71 100644 --- a/source/Uniforms.cpp +++ b/source/Uniforms.cpp @@ -3,55 +3,55 @@ namespace Uniforms { - SceneUniforms SceneData; - LightUniforms LightData; - MaterialUniforms MaterialData; + SceneUniforms SceneData; + LightUniforms LightData; + MaterialUniforms MaterialData; - //IDs for the buffer objects holding the uniform block data - GLuint scene_ubo = -1; - GLuint light_ubo = -1; - GLuint material_ubo = -1; + //IDs for the buffer objects holding the uniform block data + GLuint scene_ubo = -1; + GLuint light_ubo = -1; + GLuint material_ubo = -1; - namespace UboBinding - { - //These values come from the binding value specified in the shader block layout - int scene = 0; - int light = 1; - int material = 2; - }; + namespace UboBinding + { + //These values come from the binding value specified in the shader block layout + int scene = 0; + int light = 1; + int material = 2; + }; - //Locations for the uniforms which are not in uniform blocks - namespace UniformLocs - { - int M = 0; //model matrix - int time = 1; - }; + //Locations for the uniforms which are not in uniform blocks + namespace UniformLocs + { + int M = 0; //model matrix + int time = 1; + }; - void Init() - { - //Create and initialize uniform buffers - glGenBuffers(1, &Uniforms::scene_ubo); - glBindBuffer(GL_UNIFORM_BUFFER, scene_ubo); - glBufferData(GL_UNIFORM_BUFFER, sizeof(SceneUniforms), nullptr, GL_STREAM_DRAW); //Allocate memory for the buffer, but don't copy (since pointer is null). - glBindBufferBase(GL_UNIFORM_BUFFER, UboBinding::scene, scene_ubo); //Associate this uniform buffer with the uniform block in the shader that has the same binding. + void Init() + { + //Create and initialize uniform buffers + glGenBuffers(1, &Uniforms::scene_ubo); + glBindBuffer(GL_UNIFORM_BUFFER, scene_ubo); + glBufferData(GL_UNIFORM_BUFFER, sizeof(SceneUniforms), nullptr, GL_STREAM_DRAW); //Allocate memory for the buffer, but don't copy (since pointer is null). + glBindBufferBase(GL_UNIFORM_BUFFER, UboBinding::scene, scene_ubo); //Associate this uniform buffer with the uniform block in the shader that has the same binding. - glGenBuffers(1, &light_ubo); - glBindBuffer(GL_UNIFORM_BUFFER, light_ubo); - glBufferData(GL_UNIFORM_BUFFER, sizeof(LightUniforms), &LightData, GL_STREAM_DRAW); //Allocate memory for the buffer, but don't copy (since pointer is null). - glBindBufferBase(GL_UNIFORM_BUFFER, UboBinding::light, light_ubo); //Associate this uniform buffer with the uniform block in the shader that has the same binding. + glGenBuffers(1, &light_ubo); + glBindBuffer(GL_UNIFORM_BUFFER, light_ubo); + glBufferData(GL_UNIFORM_BUFFER, sizeof(LightUniforms), &LightData, GL_STREAM_DRAW); //Allocate memory for the buffer, but don't copy (since pointer is null). + glBindBufferBase(GL_UNIFORM_BUFFER, UboBinding::light, light_ubo); //Associate this uniform buffer with the uniform block in the shader that has the same binding. - glGenBuffers(1, &material_ubo); - glBindBuffer(GL_UNIFORM_BUFFER, material_ubo); - glBufferData(GL_UNIFORM_BUFFER, sizeof(MaterialUniforms), &MaterialData, GL_STREAM_DRAW); //Allocate memory for the buffer, but don't copy (since pointer is null). - glBindBufferBase(GL_UNIFORM_BUFFER, UboBinding::material, material_ubo); //Associate this uniform buffer with the uniform block in the shader that has the same binding. + glGenBuffers(1, &material_ubo); + glBindBuffer(GL_UNIFORM_BUFFER, material_ubo); + glBufferData(GL_UNIFORM_BUFFER, sizeof(MaterialUniforms), &MaterialData, GL_STREAM_DRAW); //Allocate memory for the buffer, but don't copy (since pointer is null). + glBindBufferBase(GL_UNIFORM_BUFFER, UboBinding::material, material_ubo); //Associate this uniform buffer with the uniform block in the shader that has the same binding. - glBindBuffer(GL_UNIFORM_BUFFER, 0); - } + glBindBuffer(GL_UNIFORM_BUFFER, 0); + } - void BufferSceneData() - { - glBindBuffer(GL_UNIFORM_BUFFER, scene_ubo); //Bind the OpenGL UBO before we update the data. - glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(SceneData), &SceneData); //Upload the new uniform values. - glBindBuffer(GL_UNIFORM_BUFFER, 0); //unbind the ubo - } + void BufferSceneData() + { + glBindBuffer(GL_UNIFORM_BUFFER, scene_ubo); //Bind the OpenGL UBO before we update the data. + glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(SceneData), &SceneData); //Upload the new uniform values. + glBindBuffer(GL_UNIFORM_BUFFER, 0); //unbind the ubo + } }; diff --git a/source/fbo.cpp b/source/fbo.cpp index 256c6cb..7d90cfc 100644 --- a/source/fbo.cpp +++ b/source/fbo.cpp @@ -19,6 +19,8 @@ void FBO::Init(int width, int height) { glGenTextures(1, &color_texture_id_); glBindTexture(GL_TEXTURE_2D, color_texture_id_); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 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, color_texture_id_, 0); diff --git a/source/scene.cpp b/source/scene.cpp index 8897473..b480f8d 100644 --- a/source/scene.cpp +++ b/source/scene.cpp @@ -27,16 +27,21 @@ namespace { const std::string kVertexShaderPath = "shaders/vertex.glsl"; const std::string kFragmentShaderPath = "shaders/fragment.glsl"; +const std::string kQuadVertexPath = "shaders/quad_vertex.glsl"; +const std::string kQuadFragmentPath = "shaders/quad_fragment.glsl"; + } // namespace Scene::Scene(int width, int height) : window_width(width), window_height(height), - shader_program_(-1), + shader_program_(-1), + quad_shader_program_(-1), vao_(-1), + quad_vao_(-1), angle_(0.0f), scale_(1.0f), - aspect_(1280.0f / 720.0f), + aspect_(static_cast(width) / static_cast(height)), near_z_(0.1f), far_z_(100.0f), fov_(glm::pi() / 4.0f) {} @@ -46,6 +51,7 @@ Scene::~Scene() { glDeleteVertexArrays(1, &vao_); fbo_.~FBO(); + post_fbo_.~FBO(); } void Scene::Init() { @@ -55,9 +61,12 @@ void Scene::Init() { glEnable(GL_CULL_FACE); fbo_.Init(window_width, window_height); + post_fbo_.Init(window_width, window_height); InitBuffers(); ReloadShader(); + InitQuadBuffers(); + quad_shader_program_ = InitShader(kQuadVertexPath.c_str(), kQuadFragmentPath.c_str()); UpdateCamera(); Uniforms::Init(); @@ -82,6 +91,34 @@ void Scene::InitBuffers() { glEnableVertexAttribArray(0); } +void Scene::InitQuadBuffers() { + GLuint quad_vbo; + // Full-screen quad vertices (position and texture coordinates) + float quadVertices[] = { + // positions // texCoords + -1.0f, 1.0f, 0.0f, 1.0f, // Top-left + -1.0f, -1.0f, 0.0f, 0.0f, // Bottom-left + 1.0f, 1.0f, 1.0f, 1.0f, // Top-right + 1.0f, -1.0f, 1.0f, 0.0f // Bottom-right + }; + + glGenVertexArrays(1, &quad_vao_); + glGenBuffers(1, &quad_vbo); + glBindVertexArray(quad_vao_); + + glBindBuffer(GL_ARRAY_BUFFER, quad_vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW); + + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0); + + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float))); + + glBindVertexArray(0); +} + + // Allows for runtime shader updates void Scene::ReloadShader() { GLuint new_shader = InitShader(kVertexShaderPath.c_str(), kFragmentShaderPath.c_str()); @@ -102,6 +139,8 @@ void Scene::Display(GLFWwindow* window) { fbo_.Bind(); + glUseProgram(shader_program_); + view_matrix_ = glm::lookAt(glm::vec3(Uniforms::SceneData.eye_w), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f)); Uniforms::SceneData.PV = projection_matrix_ * view_matrix_; // Projection-View matrix Uniforms::BufferSceneData(); @@ -109,12 +148,30 @@ void Scene::Display(GLFWwindow* window) { glm::mat4 model_matrix = glm::rotate(angle_, glm::vec3(0.0f, 1.0f, 0.0f)) * glm::scale(glm::vec3(scale_)); glUniformMatrix4fv(Uniforms::UniformLocs::M, 1, false, glm::value_ptr(model_matrix)); - glUseProgram(shader_program_); glBindVertexArray(vao_); glDrawArrays(GL_TRIANGLES, 0, 3); fbo_.Unbind(); + // post_fbo_ currently renders with a nasty artifact. Need to fix + post_fbo_.Bind(); + glDisable(GL_DEPTH_TEST); + + glUseProgram(quad_shader_program_); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, fbo_.GetColorTexture()); + + GLint screenTextureLoc = glGetUniformLocation(quad_shader_program_, "screenTexture"); + glUniform1i(screenTextureLoc, 0); // Texture unit 0 + + // Render the full-screen quad + glBindVertexArray(quad_vao_); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + post_fbo_.Unbind(); + glEnable(GL_DEPTH_TEST); + DrawGui(window); glfwSwapBuffers(window); } @@ -168,7 +225,7 @@ void Scene::DrawGui(GLFWwindow* window) { ImGui::End(); - //Draw Gui + // Draw Gui ImGui::Begin("Terrain Controls"); if (ImGui::Button("Quit")) { glfwSetWindowShouldClose(window, GLFW_TRUE); @@ -177,6 +234,12 @@ void Scene::DrawGui(GLFWwindow* window) { ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); ImGui::End(); + // Draw FBO to ImGui window + ImGui::Begin("Scene Window"); + ImVec2 windowSize = ImGui::GetContentRegionAvail(); + ImGui::Image((void*)(intptr_t)post_fbo_.GetColorTexture(), windowSize, ImVec2(0, 1), ImVec2(1, 0)); + ImGui::End(); + ImGui::Render(); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); }