From 07eb17246409ab9bd2aa65c3765a871fdef5ff37 Mon Sep 17 00:00:00 2001 From: Jack Christensen Date: Tue, 13 Aug 2024 16:25:56 -0400 Subject: [PATCH] Refactorize and started shader pipline --- imgui.ini | 9 +- include/scene.h | 61 +++++++-- shaders/fragment.glsl | 25 ++-- source/main.cpp | 107 +++++++++------ source/scene.cpp | 300 +++++++++++++++++++++++++++++++++--------- 5 files changed, 377 insertions(+), 125 deletions(-) diff --git a/imgui.ini b/imgui.ini index 1329d8c..3984d9f 100644 --- a/imgui.ini +++ b/imgui.ini @@ -4,9 +4,10 @@ Size=400,400 Collapsed=0 [Window][Terrain Controls] -Pos=178,120 -Size=568,264 +Pos=0,19 +Size=1280,86 Collapsed=0 +DockId=0x00000001,0 [Window][DockSpaceViewport_11111111] Size=1280,720 @@ -22,5 +23,7 @@ Size=1280,720 Collapsed=0 [Docking][Data] -DockSpace ID=0x6F42A598 Window=0xE80F322C Pos=0,19 Size=1280,701 CentralNode=1 +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 diff --git a/include/scene.h b/include/scene.h index 8c4bc23..ac07787 100644 --- a/include/scene.h +++ b/include/scene.h @@ -1,11 +1,50 @@ -namespace Scene -{ - void Display(GLFWwindow* window); - void DrawGUI(GLFWwindow* window); - void Idle(); - void ReloadShader(); - void Init(); - - extern const int InitWindowWidth; - extern const int InitWindowHeight; -} +#ifndef SCENE_H_ +#define SCENE_H_ + +#include +#include + +class Scene { + public: + Scene(); + ~Scene(); + + void Init(); + void Display(GLFWwindow* window); + void DrawGui(GLFWwindow* window); + void Idle(); + void ReloadShader(); + + private: + void InitBuffers(); + void InitShaders(); + + GLuint shader_program_; + GLuint vao_; + float angle_; + float scale_; + float aspect_; + float near_z_; + float far_z_; + float fov_; + + glm::mat4 view_matrix_; + glm::mat4 projection_matrix_; + + void UpdateCamera(); + +}; + +#endif // SCENE_H_ + +// namespace scene +// { +// extern const int kInitWindowWidth; +// extern const int kInitWindowHeight; + +// void Display(GLFWwindow* window); +// void DrawGUI(GLFWwindow* window); +// void Idle(); +// void ReloadShader(); +// void Init(); +// } // namespace scene \ No newline at end of file diff --git a/shaders/fragment.glsl b/shaders/fragment.glsl index 247042a..d1cdd11 100644 --- a/shaders/fragment.glsl +++ b/shaders/fragment.glsl @@ -36,23 +36,24 @@ out vec4 fragcolor; //the output color for this fragment void main(void) { //Compute per-fragment Phong lighting - vec4 ktex = texture(diffuse_tex, inData.tex_coord); + // vec4 ktex = texture(diffuse_tex, inData.tex_coord); - vec4 ambient_term = ka*ktex*La; + // vec4 ambient_term = ka*ktex*La; - const float eps = 1e-8; //small value to avoid division by 0 - float d = distance(light_w.xyz, inData.pw.xyz); - float atten = 1.0/(d*d+eps); //d-squared attenuation + // const float eps = 1e-8; //small value to avoid division by 0 + // float d = distance(light_w.xyz, inData.pw.xyz); + // float atten = 1.0/(d*d+eps); //d-squared attenuation - vec3 nw = normalize(inData.nw); //world-space unit normal vector - vec3 lw = normalize(light_w.xyz - inData.pw.xyz); //world-space unit light vector - vec4 diffuse_term = atten*kd*ktex*Ld*max(0.0, dot(nw, lw)); + // vec3 nw = normalize(inData.nw); //world-space unit normal vector + // vec3 lw = normalize(light_w.xyz - inData.pw.xyz); //world-space unit light vector + // vec4 diffuse_term = atten*kd*ktex*Ld*max(0.0, dot(nw, lw)); - vec3 vw = normalize(eye_w.xyz - inData.pw.xyz); //world-space unit view vector - vec3 rw = reflect(-lw, nw); //world-space unit reflection vector + // vec3 vw = normalize(eye_w.xyz - inData.pw.xyz); //world-space unit view vector + // vec3 rw = reflect(-lw, nw); //world-space unit reflection vector - vec4 specular_term = atten*ks*Ls*pow(max(0.0, dot(rw, vw)), shininess); + // vec4 specular_term = atten*ks*Ls*pow(max(0.0, dot(rw, vw)), shininess); - fragcolor = ambient_term + diffuse_term + specular_term; + // fragcolor = ambient_term + diffuse_term + specular_term; + fragcolor = vec4(1.0, 0.0, 0.0, 1.0); } diff --git a/source/main.cpp b/source/main.cpp index fe12259..c62dbfd 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -37,70 +37,101 @@ #include "scene.h" -const int TARGET_FPS = 60; -const auto FRAME_DURATION = std::chrono::milliseconds(1000 / TARGET_FPS); +namespace { -int main(){ +const int kTargetFps = 60; +const auto kFrameDuration = std::chrono::milliseconds(1000 / kTargetFps); + +bool InitializeGlfw() { if (!glfwInit()) { std::cerr << "Failed to initialize GLFW" << std::endl; - return -1; + return false; } + return true; +} - #ifdef _DEBUG - glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE); - #endif +GLFWwindow* CreateGlfwWindow() { +#ifdef _DEBUG + glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE); +#endif GLFWwindow* window = glfwCreateWindow(1280, 720, "TerraVisor", nullptr, nullptr); - if(!window) { + if (!window) { std::cerr << "Failed to create GLFW window" << std::endl; glfwTerminate(); - return -1; + return nullptr; } glfwMakeContextCurrent(window); + return window; +} + +bool InitializeGlew() { glewExperimental = GL_TRUE; - if(glewInit() != GLEW_OK) { + if (glewInit() != GLEW_OK) { std::cerr << "Failed to initialize GLEW" << std::endl; - return -1; + return false; } + return true; +} - Scene::Init(); - - //Init ImGui +void InitializeImGui(GLFWwindow* window) { IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGui_ImplGlfw_InitForOpenGL(window, true); ImGui_ImplOpenGL3_Init("#version 150"); +} - auto lastFrameTime = std::chrono::high_resolution_clock::now(); - - while (!glfwWindowShouldClose(window)) { - auto frameStart = std::chrono::high_resolution_clock::now(); - - Scene::Idle(); - Scene::Display(window); - - glfwPollEvents(); - - auto frameEnd = std::chrono::high_resolution_clock::now(); - auto frameDuration = frameEnd - frameStart; - - if (frameDuration < FRAME_DURATION) { - std::this_thread::sleep_for(FRAME_DURATION - frameDuration); - } - - auto currentFrameTime = std::chrono::high_resolution_clock::now(); - auto actualFrameDuration = std::chrono::duration_cast(currentFrameTime - lastFrameTime).count(); - - lastFrameTime = currentFrameTime; - } - - // Cleanup ImGui +void CleanupImGui() { ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplGlfw_Shutdown(); ImGui::DestroyContext(); +} +void MainLoop(GLFWwindow* window, Scene& scene) { + auto last_frame_time = std::chrono::high_resolution_clock::now(); + + while (!glfwWindowShouldClose(window)) { + auto frame_start = std::chrono::high_resolution_clock::now(); + + scene.Idle(); + scene.Display(window); + + glfwPollEvents(); + + auto frame_end = std::chrono::high_resolution_clock::now(); + auto frame_duration = frame_end - frame_start; + + if (frame_duration < kFrameDuration) { + std::this_thread::sleep_for(kFrameDuration - frame_duration); + } + + auto current_frame_time = std::chrono::high_resolution_clock::now(); + auto actual_frame_duration = std::chrono::duration_cast(current_frame_time - last_frame_time).count(); + + last_frame_time = current_frame_time; + } +} + +} // namespace + +int main() { + if (!InitializeGlfw()) return -1; + + GLFWwindow* window = CreateGlfwWindow(); + if (!window) return -1; + + if (!InitializeGlew()) return -1; + + Scene scene; + scene.Init(); + InitializeImGui(window); + + MainLoop(window, scene); + + CleanupImGui(); glfwDestroyWindow(window); glfwTerminate(); + return 0; } diff --git a/source/scene.cpp b/source/scene.cpp index c10aa46..b64c6fc 100644 --- a/source/scene.cpp +++ b/source/scene.cpp @@ -19,53 +19,88 @@ #include "scene.h" #include "Uniforms.h" #include "InitShader.h" //Functions for loading shaders from text files -//#include "LoadMesh.h" //Functions for creating OpenGL buffers from mesh files -//#include "LoadTexture.h" //Functions for creating OpenGL textures from image files -//#include "VideoRecorder.h" //Functions for saving videos #include "DebugCallback.h" #include "PlatformUtils.h" -static const std::string vertex_shader("shaders/vertex.glsl"); -static const std::string fragment_shader("shaders/fragment.glsl"); -GLuint shader_program = -1; +namespace { -float angle = 0.0f; -float scale = 1.0f; +const std::string kVertexShaderPath = "shaders/vertex.glsl"; +const std::string kFragmentShaderPath = "shaders/fragment.glsl"; -namespace Camera { - glm::mat4 V, P; +} // namespace - float Aspect = 1.0f; - float NearZ = 0.1f; - float FarZ = 100.0f; - float Fov = glm::pi() / 4.0f; +Scene::Scene() : shader_program_(-1), vao_(-1), angle_(0.0f), scale_(1.0f), aspect_(1280.0f / 720.0f), near_z_(0.1f), far_z_(100.0f), fov_(glm::pi() / 4.0f) {}; - void UpdateP() { - P = glm::perspective(Fov, Aspect, NearZ, FarZ); +Scene::~Scene() { + glDeleteProgram(shader_program_); + glDeleteVertexArrays(1, &vao_); +} + +void Scene::Init() { + glewInit(); + + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + + //InitTri(); + InitBuffers(); + ReloadShader(); + + UpdateCamera(); + Uniforms::Init(); +} + +void Scene::InitBuffers() { + GLuint vbo; + float vertices[] = { + -0.5f, -0.5f, 0.0f, + 0.5f, -0.5f, 0.0f, + 0.0f, 0.5f, 0.0f + }; + + glGenBuffers(1, &vbo); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + + glGenVertexArrays(1, &vao_); + glBindVertexArray(vao_); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); + glEnableVertexAttribArray(0); +} + +void Scene::ReloadShader() { + GLuint new_shader = InitShader(kVertexShaderPath.c_str(), kFragmentShaderPath.c_str()); + if (new_shader == -1) { + DEBUG_BREAK(); + glClearColor(1.0f, 0.0f, 1.0f, 0.0f); + } else { + glClearColor(0.35f, 0.35f, 0.35f, 0.0f); + if (shader_program_ != -1) { + glDeleteProgram(shader_program_); + } + shader_program_ = new_shader; } } void Scene::Display(GLFWwindow* window) { - glClear(GL_COLOR_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - Camera::V = 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 = Camera::P * Camera::V; + 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(); - glUseProgram(shader_program); + 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)); - glm::mat4 M = 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(M)); - - //glBindVertexArray(mesh_data.mVao); - //glDrawElements(GL_TRIANGLES, mesh_data.mSubmesh[0].mNumIndices, GL_UNSIGNED_INT, 0); - - Scene::DrawGUI(window); + glUseProgram(shader_program_); + glBindVertexArray(vao_); + glDrawArrays(GL_TRIANGLES, 0, 3); + DrawGui(window); glfwSwapBuffers(window); } -void Scene::DrawGUI(GLFWwindow* window) { +void Scene::DrawGui(GLFWwindow* window) { // Begin ImGui frame ImGui_ImplOpenGL3_NewFrame(); ImGui_ImplGlfw_NewFrame(); @@ -97,16 +132,13 @@ void Scene::DrawGUI(GLFWwindow* window) { ImGui::PopStyleVar(3); // Submit the DockSpace - if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable) - { + if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable) { ImGuiID dockspace_id = ImGui::GetID("MyDockSpace"); ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags); } - if (ImGui::BeginMenuBar()) - { - if (ImGui::BeginMenu("Options")) - { + if (ImGui::BeginMenuBar()) { + if (ImGui::BeginMenu("Options")) { ImGui::Text("Nothing Here Yet, Check Back Later!"); ImGui::EndMenu(); @@ -119,8 +151,7 @@ void Scene::DrawGUI(GLFWwindow* window) { //Draw Gui ImGui::Begin("Terrain Controls"); - if (ImGui::Button("Quit")) - { + if (ImGui::Button("Quit")) { glfwSetWindowShouldClose(window, GLFW_TRUE); } @@ -132,34 +163,181 @@ void Scene::DrawGUI(GLFWwindow* window) { } void Scene::Idle() { + } -void Scene::ReloadShader() -{ - GLuint new_shader = InitShader(vertex_shader.c_str(), fragment_shader.c_str()); - - if (new_shader == -1) // loading failed - { - DEBUG_BREAK(); //alert user by breaking and showing debugger - glClearColor(1.0f, 0.0f, 1.0f, 0.0f); //change clear color if shader can't be compiled - } - else - { - glClearColor(0.35f, 0.35f, 0.35f, 0.0f); - - if (shader_program != -1) - { - glDeleteProgram(shader_program); - } - shader_program = new_shader; - } +void Scene::UpdateCamera() { + projection_matrix_ = glm::perspective(fov_, aspect_, near_z_, far_z_); } -void Scene::Init() { - glewInit(); +// namespace scene { - glEnable(GL_DEPTH_TEST); - glEnable(GL_CULL_FACE); +// const int kInitWindowWidth = 1280; +// const int kInitWindowHeight = 720; - ReloadShader(); -} +// static const std::string kVertexShader("shaders/vertex.glsl"); +// static const std::string kFragmentShader("shaders/fragment.glsl"); + +// GLuint shader_program = -1; + +// // Vertex data for a basic triangle. Testing use only +// float vertices[] = { +// -0.5f, -0.5f, 0.0f, +// 0.5f, -0.5f, 0.0f, +// 0.0f, 0.5f, 0.0f +// }; + +// unsigned int VAO = -1; + +// float angle = 0.0f; +// float scale = 1.0f; + +// namespace camera { +// glm::mat4 V, P; + +// float aspect = static_cast(kInitWindowWidth) / static_cast(kInitWindowHeight); +// float near_z = 0.1f; +// float far_z = 100.0f; +// float fov = glm::pi() / 4.0f; + +// void UpdateP() { +// P = glm::perspective(fov, aspect, near_z, far_z); +// } +// } // namespace camera + +// // Temp function to test shader pipline with basic triangle +// void InitTri() { +// unsigned int vbo; +// glGenBuffers(1, &vbo); +// glBindBuffer(GL_ARRAY_BUFFER, vbo); +// glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + +// glGenVertexArrays(1, &VAO); +// glBindVertexArray(VAO); +// glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); +// glEnableVertexAttribArray(0); +// } + + +// void Display(GLFWwindow* window) { +// // Clear the color and depth buffers +// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + +// camera::V = 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 = camera::P * camera::V; // Projection-View matrix +// Uniforms::BufferSceneData(); + +// // Model matrix +// glm::mat4 M = 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(M)); + +// glUseProgram(shader_program); + +// glBindVertexArray(VAO); +// glDrawArrays(GL_TRIANGLES, 0, 3); + +// DrawGUI(window); +// glfwSwapBuffers(window); +// } + + + +// void DrawGUI(GLFWwindow* window) { +// // Begin ImGui frame +// ImGui_ImplOpenGL3_NewFrame(); +// ImGui_ImplGlfw_NewFrame(); + +// // Enable docking +// ImGuiIO& io = ImGui::GetIO(); +// io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; + +// ImGui::NewFrame(); + +// static ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_PassthruCentralNode; + +// // Add menu bar +// ImGuiWindowFlags window_flags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking; + +// // Style windows +// const ImGuiViewport* viewport = ImGui::GetMainViewport(); +// ImGui::SetNextWindowPos(viewport->WorkPos); +// ImGui::SetNextWindowSize(viewport->WorkSize); +// ImGui::SetNextWindowViewport(viewport->ID); +// ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); +// ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f); +// window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove; +// window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus; +// window_flags |= ImGuiWindowFlags_NoBackground; + +// ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); +// ImGui::Begin("TerraVisor", nullptr, window_flags); +// ImGui::PopStyleVar(3); + +// // Submit the DockSpace +// if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable) { +// ImGuiID dockspace_id = ImGui::GetID("MyDockSpace"); +// ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags); +// } + +// if (ImGui::BeginMenuBar()) { +// if (ImGui::BeginMenu("Options")) { +// ImGui::Text("Nothing Here Yet, Check Back Later!"); + +// ImGui::EndMenu(); +// } + +// ImGui::EndMenuBar(); +// } + +// ImGui::End(); + +// //Draw Gui +// ImGui::Begin("Terrain Controls"); +// if (ImGui::Button("Quit")) { +// glfwSetWindowShouldClose(window, GLFW_TRUE); +// } + +// ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); +// ImGui::End(); + +// ImGui::Render(); +// ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); +// } + +// void Idle() { +// // Idle function to update the scene when no rendering is performed. +// } + +// void ReloadShader() +// { +// GLuint new_shader = InitShader(kVertexShader.c_str(), kFragmentShader.c_str()); + +// if (new_shader == -1) { // loading failed +// DEBUG_BREAK(); //alert user by breaking and showing debugger +// glClearColor(1.0f, 0.0f, 1.0f, 0.0f); //change clear color if shader can't be compiled +// } +// else { +// glClearColor(0.35f, 0.35f, 0.35f, 0.0f); + +// if (shader_program != -1) { +// glDeleteProgram(shader_program); +// } +// shader_program = new_shader; +// } +// } + +// void Init() { +// glewInit(); + +// glEnable(GL_DEPTH_TEST); +// glEnable(GL_CULL_FACE); + +// InitTri(); + +// ReloadShader(); + +// camera::UpdateP(); +// Uniforms::Init(); +// } + +// } // namespace scene \ No newline at end of file