diff --git a/assets b/assets index 6428e252..a08447dd 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 6428e2528c4a5692f277eed6041e97b9d8e70b2f +Subproject commit a08447ddb3aaf9ebdc7e18979291567a7032b6a2 diff --git a/include/Engine/Rendering/Renderer.h b/include/Engine/Rendering/Renderer.h index 423365f6..f9a51d4e 100644 --- a/include/Engine/Rendering/Renderer.h +++ b/include/Engine/Rendering/Renderer.h @@ -7,6 +7,7 @@ #include "ShaderProgram.h" //TODO: Temp resourceManager #include "../Core/ResourceManager.h" +#include "Util/UnorderedMapVec2.h" class Renderer : public IRenderer { @@ -20,16 +21,41 @@ private: RenderQueueCollection m_TempRQ; Texture* m_ErrorTexture; Texture* m_WhiteTexture; - float m_CameraMoveSpeed = 3.f; + float m_CameraMoveSpeed; + GLuint m_PickingBuffer; + GLuint m_PickingTexture; + GLuint m_DepthBuffer; + + Model* m_ScreenQuad; + Model* m_UnitQuad; + Model* m_UnitSphere; + + //Temporary + Model* m; + Model* m2; + Model* m3; + Model* MapModel; + + + std::unordered_map m_PickingColorsToModels; + //----------------------Functions----------------------// void InitializeWindow(); void InitializeShaders(); + void InitializeTextures(); + void InitializeFrameBuffers(); //TODO: Render: Remove ModelsToDraw from Renderer. void ModelsToDraw(); void EnqueueModel(Model* model); void InputUpdate(double dt); + void PickingPass(); + void DrawScreenQuad(GLuint textureToDraw); + glm::vec3 GetClickedPixelData(float x, float y); + void DrawScene(RenderQueueCollection& rq); //--------------------ShaderPrograms-------------------// ShaderProgram m_BasicForwardProgram; + ShaderProgram m_PickingProgram; + ShaderProgram m_DrawScreenQuadProgram; }; #endif \ No newline at end of file diff --git a/include/Engine/Rendering/ShaderProgram.h b/include/Engine/Rendering/ShaderProgram.h index 97f64e60..1b87650e 100644 --- a/include/Engine/Rendering/ShaderProgram.h +++ b/include/Engine/Rendering/ShaderProgram.h @@ -18,7 +18,6 @@ public: std::string GetFileName() const; GLuint GetHandle() const; bool IsCompiled() const; - protected: GLenum m_ShaderType; std::string m_FileName; @@ -74,6 +73,7 @@ public: GLuint GetHandle(); void Bind(); void Unbind(); + void BindFragDataLocation(int index, std::string name); private: GLuint m_ShaderProgramHandle; diff --git a/resources/Shaders/DrawScreenQuad.frag.glsl b/resources/Shaders/DrawScreenQuad.frag.glsl new file mode 100644 index 00000000..17837a7b --- /dev/null +++ b/resources/Shaders/DrawScreenQuad.frag.glsl @@ -0,0 +1,19 @@ +#version 430 + +layout (binding = 0) uniform sampler2D Texture; + +in VertexData{ + vec2 TextureCoordinate; +}Input; + +out vec4 fragmentColor; + +void main() +{ + vec4 texel = texture(Texture, Input.TextureCoordinate); + + fragmentColor = texel; + //fragmentColor = vec4(1,0.5,0.7,1); +} + + diff --git a/resources/Shaders/DrawScreenQuad.vert.glsl b/resources/Shaders/DrawScreenQuad.vert.glsl new file mode 100644 index 00000000..346bc141 --- /dev/null +++ b/resources/Shaders/DrawScreenQuad.vert.glsl @@ -0,0 +1,13 @@ +#version 430 + +layout (location = 0) in vec3 Position; + +out VertexData{ + vec2 TextureCoordinate; +}Output; + +void main() +{ + gl_Position = vec4(Position, 1.0); + Output.TextureCoordinate = (vec2(Position) + 1) / 2; +} \ No newline at end of file diff --git a/resources/Shaders/Picking.frag.glsl b/resources/Shaders/Picking.frag.glsl new file mode 100644 index 00000000..11f529b0 --- /dev/null +++ b/resources/Shaders/Picking.frag.glsl @@ -0,0 +1,19 @@ +#version 430 + +uniform mat4 M; +uniform mat4 V; +uniform mat4 P; +uniform vec2 PickingColor; + +in VertexData{ + vec3 Position; +}Input; + +out vec4 TextureFragment; + +void main() +{ + TextureFragment = vec4(PickingColor, 0, 1); +} + + diff --git a/resources/Shaders/Picking.vert.glsl b/resources/Shaders/Picking.vert.glsl new file mode 100644 index 00000000..47c0ecd7 --- /dev/null +++ b/resources/Shaders/Picking.vert.glsl @@ -0,0 +1,28 @@ +#version 430 + +uniform mat4 M; +uniform mat4 V; +uniform mat4 P; + +layout(location = 0) in vec3 Position; +layout(location = 1) in vec3 Normal; +layout(location = 2) in vec3 Tangent; +layout(location = 3) in vec3 BiTangent; +layout(location = 4) in vec2 TextureCoords; +layout(location = 5) in vec4 DiffuseVertexColor; +layout(location = 6) in vec4 SpecularVertexColor; +layout(location = 7) in vec4 BoneIndices1; +layout(location = 8) in vec4 BoneIndices2; +layout(location = 9) in vec4 BoneWeights1; +layout(location = 10) in vec4 BoneWeights2; + +out VertexData{ + vec3 Position; +}Output; + +void main() +{ + gl_Position = P*V*M * vec4(Position, 1.0); + + Output.Position = Position; +} \ No newline at end of file diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index d17eaeae..ef18d631 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -12,9 +12,9 @@ void Renderer::Initialize() } glfwSwapInterval(m_VSYNC); - m_ErrorTexture = ResourceManager::Load("Textures/Core/ErrorTexture.png"); - m_WhiteTexture = ResourceManager::Load("Textures/Core/Blank.png"); InitializeShaders(); + InitializeTextures(); + InitializeFrameBuffers(); ModelsToDraw(); } @@ -64,16 +64,35 @@ void Renderer::InitializeShaders() m_BasicForwardProgram.AddShader(std::shared_ptr(new FragmentShader("Shaders/BasicForward.frag.glsl"))); m_BasicForwardProgram.Compile(); m_BasicForwardProgram.Link(); + + m_PickingProgram.AddShader(std::shared_ptr(new VertexShader("Shaders/Picking.vert.glsl"))); + m_PickingProgram.AddShader(std::shared_ptr(new FragmentShader("Shaders/Picking.frag.glsl"))); + m_PickingProgram.Compile(); + m_PickingProgram.BindFragDataLocation(0, "TextureFragment"); + m_PickingProgram.Link(); + + m_DrawScreenQuadProgram.AddShader(std::shared_ptr(new VertexShader("Shaders/DrawScreenQuad.vert.glsl"))); + m_DrawScreenQuadProgram.AddShader(std::shared_ptr(new FragmentShader("Shaders/DrawScreenQuad.frag.glsl"))); + m_DrawScreenQuadProgram.Compile(); + m_DrawScreenQuadProgram.Link(); + } void Renderer::ModelsToDraw() { - Model *m = ResourceManager::Load("Models/ScaleWidget.obj"); + m = ResourceManager::Load("Models/ScaleWidget.obj"); EnqueueModel(m); - Model *m2 = ResourceManager::Load("Models/TranslationWidget.obj"); + m2 = ResourceManager::Load("Models/TranslationWidget.obj"); EnqueueModel(m2); - Model *m3 = ResourceManager::Load("Models/RotationWidget.obj"); + m3 = ResourceManager::Load("Models/RotationWidget.obj"); EnqueueModel(m3); + m_UnitSphere = ResourceManager::Load("Models/Core/UnitSphere.obj"); + EnqueueModel(m_UnitSphere); + m_UnitQuad = ResourceManager::Load("Models/Core/UnitQuad.obj"); + m_ScreenQuad = ResourceManager::Load("Models/Core/ScreenQuad.obj"); + + MapModel = ResourceManager::Load("Models/DummyScene.obj"); + EnqueueModel(MapModel); } void Renderer::EnqueueModel(Model* model) @@ -136,10 +155,26 @@ void Renderer::InputUpdate(double dt) m_CameraMoveSpeed = 0.5f; } - if (glfwGetKey(m_Window, GLFW_KEY_SPACE) == GLFW_PRESS) { - static double mousePosX, mousePosY; - glfwGetCursorPos(m_Window, &mousePosX, &mousePosY); + static double mousePosX, mousePosY; + glfwGetCursorPos(m_Window, &mousePosX, &mousePosY); + if (glfwGetMouseButton(m_Window, GLFW_MOUSE_BUTTON_1) == GLFW_PRESS) { + glm::vec3 data = GetClickedPixelData(mousePosX, m_Resolution.Height - mousePosY); + glm::vec2 pixelData = glm::vec2(data); + float depthData = data.z; + printf("R: %f, G: %f, Depth: %f\n", pixelData.r, pixelData.g, depthData); + + + if (pixelData != glm::vec2(0, 0)) { + const Model* pickModel = m_PickingColorsToModels[pixelData]; + + } + } + + + if (glfwGetKey(m_Window, GLFW_KEY_SPACE) == GLFW_PRESS) { + + double deltaX, deltaY; deltaX = mousePosX - (float)Resolution().Width / 2; deltaY = mousePosY - (float)Resolution().Height / 2; @@ -166,42 +201,173 @@ void Renderer::Update(double dt) void Renderer::Draw(RenderQueueCollection& rq) { - //TODO: Render: Clean up draw code - glEnable(GL_DEPTH_TEST); - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); - - glClearColor(255.f / 255, 163.f / 255, 176.f / 255, 0.f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - //TODO: Render: Add code for more jobs than modeljobs. - for (auto &job : m_TempRQ.Forward) { - auto modelJob = std::dynamic_pointer_cast(job); - if (modelJob) { - GLuint ShaderHandle = m_BasicForwardProgram.GetHandle(); - - m_BasicForwardProgram.Bind(); - //TODO: Kolla upp "header/include/common" shader saken så man slipper skicka in asmycket uniforms - glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(glm::mat4(1))); - glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(m_Camera->ViewMatrix())); - glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(m_Camera->ProjectionMatrix())); - - //TODO: Renderer: bättre textur felhantering samt fler texturer stöd - if (modelJob->DiffuseTexture != nullptr) { - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, modelJob->DiffuseTexture->m_Texture); - } else { - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture); - } - - glBindVertexArray(modelJob->Model->VAO); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer); - glDrawElementsBaseVertex(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, 0, modelJob->StartIndex); - - continue; - } - } + //TODO: Renderer: Kanske borde vara längst upp i update. + PickingPass(); + DrawScreenQuad(m_PickingTexture); + //DrawScene(rq); glfwSwapBuffers(m_Window); } +void Renderer::DrawScene(RenderQueueCollection& rq) +{ + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + //TODO: Render: Clean up draw code + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + + glClearColor(255.f / 255, 163.f / 255, 176.f / 255, 0.f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + //TODO: Render: Add code for more jobs than modeljobs. + for (auto &job : m_TempRQ.Forward) { + auto modelJob = std::dynamic_pointer_cast(job); + if (modelJob) { + GLuint ShaderHandle = m_BasicForwardProgram.GetHandle(); + + m_BasicForwardProgram.Bind(); + //TODO: Kolla upp "header/include/common" shader saken så man slipper skicka in asmycket uniforms + glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(glm::mat4(1))); + glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(m_Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(m_Camera->ProjectionMatrix())); + + //TODO: Renderer: bättre textur felhantering samt fler texturer stöd + if (modelJob->DiffuseTexture != nullptr) { + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, modelJob->DiffuseTexture->m_Texture); + } else { + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture); + } + + glBindVertexArray(modelJob->Model->VAO); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer); + glDrawElementsBaseVertex(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, 0, modelJob->StartIndex); + + continue; + } + } +} + +void Renderer::PickingPass() +{ + glBindFramebuffer(GL_FRAMEBUFFER, m_PickingBuffer); + + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + + glClearColor(0.f, 0.f, 0.f, 1.f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + int r = 30; + int g = 0; + //TODO: Render: Add code for more jobs than modeljobs. + + + GLuint ShaderHandle = m_PickingProgram.GetHandle(); + m_PickingProgram.Bind(); + + for (auto &job : m_TempRQ.Forward) { + auto modelJob = std::dynamic_pointer_cast(job); + + if (modelJob) { + glm::vec2 pickColor = glm::vec2(r/255.f, g/255.f); + m_PickingColorsToModels[pickColor] = modelJob->Model; + + //Render picking stuff + //TODO: Kolla upp "header/include/common" shader saken så man slipper skicka in asmycket uniforms + glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(glm::mat4(1))); + glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(m_Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(m_Camera->ProjectionMatrix())); + glUniform2fv(glGetUniformLocation(ShaderHandle, "PickingColor"), 1, glm::value_ptr(pickColor)); + + glBindVertexArray(modelJob->Model->VAO); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer); + glDrawElementsBaseVertex(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, 0, modelJob->StartIndex); + r+=50; + if(r > 255) { + r = 0; + g+=50; + } + } + } + +} + + +void Renderer::DrawScreenQuad(GLuint textureToDraw) +{ + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + + glClearColor(0.f, 0.f, 0.f, 1.f); + glClear(GL_COLOR_BUFFER_BIT); + + + m_DrawScreenQuadProgram.Bind(); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, textureToDraw); + + glBindVertexArray(m_ScreenQuad->VAO); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ScreenQuad->ElementBuffer); + glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->TextureGroups[0].EndIndex - m_ScreenQuad->TextureGroups[0].StartIndex +1 + , GL_UNSIGNED_INT, 0, m_ScreenQuad->TextureGroups[0].StartIndex); +} + + + +// Will return a vec3 where RG is the PickColor and B is the Depth +glm::vec3 Renderer::GetClickedPixelData(float x, float y) +{ + glBindFramebuffer(GL_FRAMEBUFFER, m_PickingBuffer); + glm::vec2 pixelData; + glReadPixels(x, y, 1, 1, GL_RG, GL_FLOAT, &pixelData); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + glBindFramebuffer(GL_FRAMEBUFFER, m_DepthBuffer); + float depthData; + glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depthData); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + return glm::vec3(pixelData, depthData); +} + +void Renderer::InitializeTextures() +{ + m_ErrorTexture=ResourceManager::Load("Textures/Core/ErrorTexture.png"); + m_WhiteTexture=ResourceManager::Load("Textures/Core/Blank.png"); + + glGenTextures(1, &m_PickingTexture); + glBindTexture(GL_TEXTURE_2D, m_PickingTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RG8, m_Resolution.Width, m_Resolution.Height, 0, GL_RGB, GL_FLOAT, NULL);//TODO: Renderer: Fix the precision and Resolution + GLERROR("m_PickingTexture initialization failed"); +} + +void Renderer::InitializeFrameBuffers()//TODO: Renderer: Get this to a better location, as its really big +{ + glGenRenderbuffers(1, &m_DepthBuffer); + glBindRenderbuffer(GL_RENDERBUFFER, m_DepthBuffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, m_Resolution.Width, m_Resolution.Height); + + + glGenFramebuffers(1, &m_PickingBuffer); + glBindFramebuffer(GL_FRAMEBUFFER, m_PickingBuffer); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_DepthBuffer); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_PickingTexture, 0); + GLenum PickingBufferTextures[] = { GL_COLOR_ATTACHMENT0 }; + glDrawBuffers(1, PickingBufferTextures); + + if (GLenum fbStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + LOG_ERROR("m_FbDeferred2 incomplete: 0x%x\n", fbStatus); + exit(EXIT_FAILURE); + } + + +} \ No newline at end of file diff --git a/src/Engine/Rendering/ShaderProgram.cpp b/src/Engine/Rendering/ShaderProgram.cpp index 5200ff22..f713cd03 100644 --- a/src/Engine/Rendering/ShaderProgram.cpp +++ b/src/Engine/Rendering/ShaderProgram.cpp @@ -150,4 +150,14 @@ void ShaderProgram::Bind() void ShaderProgram::Unbind() { glActiveShaderProgram(0, 0); -} \ No newline at end of file +} + +void ShaderProgram::BindFragDataLocation(int index, std::string name) +{ + + if (m_ShaderProgramHandle == 0) + return; + + glBindFragDataLocation(m_ShaderProgramHandle, index, name.c_str()); +} +