Refactor, setup FBO, and render into ImGui window

This commit is contained in:
Jack Christensen 2024-08-14 02:16:53 -04:00
parent 0e348944b1
commit 7060c08217
10 changed files with 166 additions and 67 deletions

View File

@ -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

View File

@ -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

View File

@ -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_;

View File

@ -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);
}

View File

@ -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);
}

12
shaders/quad_vertex.glsl Normal file
View File

@ -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;
}

View File

@ -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
}

View File

@ -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
}
};

View File

@ -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);

View File

@ -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<float>(width) / static_cast<float>(height)),
near_z_(0.1f), far_z_(100.0f),
fov_(glm::pi<float>() / 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());
}