From 77aff3c078120c75cf1b4f4662ac9c5d1f9437e8 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Wed, 12 Mar 2014 21:40:19 +0100 Subject: [PATCH] WIP Shadow Mapping --- Escape-the-Dawn/Escape-the-Dawn.vcxproj | 4 + .../Escape-the-Dawn.vcxproj.filters | 12 + Escape-the-Dawn/GameWorld.cpp | 14 + Escape-the-Dawn/Model.cpp | 40 ++- Escape-the-Dawn/OBJ.cpp | 5 - Escape-the-Dawn/OBJ.h | 6 +- Escape-the-Dawn/Renderer.cpp | 244 ++++++++++++++---- Escape-the-Dawn/Renderer.h | 17 +- Escape-the-Dawn/Shaders/Fragment.glsl | 77 +++--- Escape-the-Dawn/Shaders/ShadowMap.frag.glsl | 9 + Escape-the-Dawn/Shaders/ShadowMap.vert.glsl | 22 ++ Escape-the-Dawn/Shaders/Vertex.glsl | 3 + .../Shaders/VisualizeDepth.frag.glsl | 24 ++ .../Shaders/VisualizeDepth.vert.glsl | 17 ++ Escape-the-Dawn/plane.mtl | 4 +- 15 files changed, 395 insertions(+), 103 deletions(-) create mode 100644 Escape-the-Dawn/Shaders/ShadowMap.frag.glsl create mode 100644 Escape-the-Dawn/Shaders/ShadowMap.vert.glsl create mode 100644 Escape-the-Dawn/Shaders/VisualizeDepth.frag.glsl create mode 100644 Escape-the-Dawn/Shaders/VisualizeDepth.vert.glsl diff --git a/Escape-the-Dawn/Escape-the-Dawn.vcxproj b/Escape-the-Dawn/Escape-the-Dawn.vcxproj index f34b012..8a6c3db 100644 --- a/Escape-the-Dawn/Escape-the-Dawn.vcxproj +++ b/Escape-the-Dawn/Escape-the-Dawn.vcxproj @@ -169,6 +169,10 @@ + + + + diff --git a/Escape-the-Dawn/Escape-the-Dawn.vcxproj.filters b/Escape-the-Dawn/Escape-the-Dawn.vcxproj.filters index 2ce6bb5..da3ea10 100644 --- a/Escape-the-Dawn/Escape-the-Dawn.vcxproj.filters +++ b/Escape-the-Dawn/Escape-the-Dawn.vcxproj.filters @@ -164,6 +164,18 @@ Shaders + + Shaders + + + Shaders + + + Shaders + + + Shaders + diff --git a/Escape-the-Dawn/GameWorld.cpp b/Escape-the-Dawn/GameWorld.cpp index 3844113..c19fe46 100644 --- a/Escape-the-Dawn/GameWorld.cpp +++ b/Escape-the-Dawn/GameWorld.cpp @@ -19,6 +19,18 @@ void GameWorld::Initialize() std::shared_ptr camera; EntityID ent; + // Camera + ent = CreateEntity(); + SetProperty(ent, "Name", std::string("Camera")); + transform = AddComponent(ent, "Transform"); + AddComponent(ent, "Input"); + transform->Position = glm::vec3(0.f, 2.f, 10.f); + camera = AddComponent(ent, "Camera"); + camera->FOV = 45.f; + camera->FarClip = 1000.f; + camera->NearClip = 0.01f; + transform->Orientation = glm::angleAxis(glm::radians(25.0f),glm::vec3(1,0,0)); + // Fucking lights ent = CreateEntity(); transform = AddComponent(ent, "Transform"); @@ -83,6 +95,8 @@ void GameWorld::Initialize() transform->Position = glm::vec3(10.f, 0.f, 0.f); model = AddComponent(ent, "Model"); model->ModelFile = "ship.obj"; + + // Camera } void GameWorld::Update(double dt) diff --git a/Escape-the-Dawn/Model.cpp b/Escape-the-Dawn/Model.cpp index 4ae2126..b6eacf6 100644 --- a/Escape-the-Dawn/Model.cpp +++ b/Escape-the-Dawn/Model.cpp @@ -13,6 +13,10 @@ Model::Model(OBJ &obj) TextureGroup* currentTexGroup = nullptr; int index = 0; for (auto face : obj.Faces) { + if (face.Material == nullptr) { + LOG_ERROR("Missing material for .obj file \"%s\"", obj.Path().string().c_str()); + return; + } // New material if (face.Material != currentMaterial) { currentMaterial = face.Material; @@ -49,7 +53,9 @@ Model::Model(OBJ &obj) } } - CreateBuffers(Vertices, Normals, TextureCoords); + if (Vertices.size() > 0) { + CreateBuffers(Vertices, Normals, TextureCoords); + } } bool Model::Loadobj(const char* path, std::vector & out_vertices, std::vector &out_normals, std::vector & out_TextureCoords) @@ -186,27 +192,39 @@ bool Model::Loadobj(const char* path, std::vector & out_vertices, st } -void Model::CreateBuffers( std::vector _Vertices, std::vector _Normals, std::vector_TextureCoords) +void Model::CreateBuffers( std::vector vertices, std::vector normals, std::vectortextureCoords) { LOG_INFO("Generating VertexBuffer"); glGenBuffers(1, &VertexBuffer); - glBindBuffer(GL_ARRAY_BUFFER, VertexBuffer); - glBufferData(GL_ARRAY_BUFFER, _Vertices.size() * sizeof(glm::vec3), &_Vertices[0], GL_STATIC_DRAW); - GLERROR("GLEW: BufferFail, VertexBuffer"); + if (vertices.size() > 0) { + glBindBuffer(GL_ARRAY_BUFFER, VertexBuffer); + glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), &vertices[0], GL_STATIC_DRAW); + GLERROR("GLEW: BufferFail, VertexBuffer"); + } else { + LOG_WARNING("Created empty vertex buffer!"); + } LOG_INFO("Generating NormalBuffer"); glGenBuffers(1, &NormalBuffer); - glBindBuffer(GL_ARRAY_BUFFER, NormalBuffer); - glBufferData(GL_ARRAY_BUFFER, _Normals.size() * sizeof(glm::vec3), &_Normals[0], GL_STATIC_DRAW); - GLERROR("GLEW: BufferFail, NormalBuffer"); + if (normals.size() > 0) { + glBindBuffer(GL_ARRAY_BUFFER, NormalBuffer); + glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(glm::vec3), &normals[0], GL_STATIC_DRAW); + GLERROR("GLEW: BufferFail, NormalBuffer"); + } else { + LOG_WARNING("Created empty normal buffer!"); + } LOG_INFO("Generating textureCoordBuffer"); glGenBuffers(1, &TextureCoordBuffer); - glBindBuffer(GL_ARRAY_BUFFER, TextureCoordBuffer); - glBufferData(GL_ARRAY_BUFFER, _TextureCoords.size() * sizeof(glm::vec2), &_TextureCoords[0], GL_STATIC_DRAW); - GLERROR("GLEW: BufferFail, TextureCoordBuffer"); + if (textureCoords.size() > 0) { + glBindBuffer(GL_ARRAY_BUFFER, TextureCoordBuffer); + glBufferData(GL_ARRAY_BUFFER, textureCoords.size() * sizeof(glm::vec2), &textureCoords[0], GL_STATIC_DRAW); + GLERROR("GLEW: BufferFail, TextureCoordBuffer"); + } else { + LOG_WARNING("Created empty texture coordinate buffer!"); + } glGenVertexArrays(1, &VAO); glBindVertexArray(VAO); diff --git a/Escape-the-Dawn/OBJ.cpp b/Escape-the-Dawn/OBJ.cpp index 4615466..df3ece7 100644 --- a/Escape-the-Dawn/OBJ.cpp +++ b/Escape-the-Dawn/OBJ.cpp @@ -1,10 +1,5 @@ #include "OBJ.h" -OBJ::OBJ() -{ - m_CurrentMaterial = nullptr; -} - bool OBJ::LoadFromFile(std::string filename) { m_Path = boost::filesystem::path(filename); diff --git a/Escape-the-Dawn/OBJ.h b/Escape-the-Dawn/OBJ.h index aa157fa..9aeed54 100644 --- a/Escape-the-Dawn/OBJ.h +++ b/Escape-the-Dawn/OBJ.h @@ -38,12 +38,13 @@ public: struct Face { + Face() : Material(nullptr) { } std::vector Definitions; MaterialInfo* Material; }; - OBJ(); - OBJ(std::string filename) { LoadFromFile(filename); } + OBJ() : m_CurrentMaterial(nullptr) { } + OBJ(std::string filename) : m_CurrentMaterial(nullptr) { LoadFromFile(filename); } std::vector> Vertices; std::vector> Normals; @@ -52,6 +53,7 @@ public: std::map Materials; bool LoadFromFile(std::string filename); + boost::filesystem::path Path() const { return m_Path; } private: boost::filesystem::path m_Path; diff --git a/Escape-the-Dawn/Renderer.cpp b/Escape-the-Dawn/Renderer.cpp index 84f1273..bffbaae 100644 --- a/Escape-the-Dawn/Renderer.cpp +++ b/Escape-the-Dawn/Renderer.cpp @@ -5,6 +5,10 @@ Renderer::Renderer() m_VSync = false; m_DrawNormals = false; m_DrawWireframe = false; + + m_SunPosition = glm::vec3(0, 10, 10); + m_SunTarget = glm::vec3(0); + m_SunProjection = glm::ortho(-20, 20, -20, 20, -10, 20); } void Renderer::Initialize() @@ -55,49 +59,178 @@ void Renderer::Initialize() LoadContent(); } +void Renderer::LoadContent() +{ + auto standardVS = std::shared_ptr(new VertexShader("Shaders/Vertex.glsl")); + auto standardFS = std::shared_ptr(new FragmentShader("Shaders/Fragment.glsl")); + + m_ShaderProgram.AddShader(standardVS); + m_ShaderProgram.AddShader(standardFS); + m_ShaderProgram.Compile(); + m_ShaderProgram.Link(); + + m_ShaderProgramNormals.AddShader(std::shared_ptr(new GeometryShader("Shaders/Normals.geo.glsl"))); + m_ShaderProgramNormals.AddShader(standardVS); + m_ShaderProgramNormals.AddShader(std::shared_ptr(new FragmentShader("Shaders/Normals.frag.glsl"))); + m_ShaderProgramNormals.Compile(); + m_ShaderProgramNormals.Link(); + + m_ShaderProgramShadows.AddShader(std::shared_ptr(new VertexShader("Shaders/ShadowMap.vert.glsl"))); + m_ShaderProgramShadows.AddShader(std::shared_ptr(new FragmentShader("Shaders/ShadowMap.frag.glsl"))); + m_ShaderProgramShadows.Compile(); + m_ShaderProgramShadows.Link(); + + m_ShaderProgramShadowsDrawDepth.AddShader(std::shared_ptr(new VertexShader("Shaders/VisualizeDepth.vert.glsl"))); + m_ShaderProgramShadowsDrawDepth.AddShader(std::shared_ptr(new FragmentShader("Shaders/VisualizeDepth.frag.glsl"))); + m_ShaderProgramShadowsDrawDepth.Compile(); + m_ShaderProgramShadowsDrawDepth.Link(); + + m_ScreenQuad = CreateQuad(); + CreateShadowMap(2048*2); +} + +void Renderer::CreateShadowMap(int resolution) +{ + glGenFramebuffers(1, &m_ShadowFrameBuffer); + glBindFramebuffer(GL_FRAMEBUFFER, m_ShadowFrameBuffer); + + // Depth texture + glGenTextures(1, &m_ShadowDepthTexture); + glBindTexture(GL_TEXTURE_2D, m_ShadowDepthTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, resolution, resolution, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + 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_COMPARE_MODE, GL_NONE ); + //glTexParameteri( GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY ); + + glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, m_ShadowDepthTexture, 0); + glDrawBuffer(GL_NONE); + + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + LOG_ERROR("Framebuffer incomplete!"); + return; + } +} void Renderer::Draw(double dt) { + DrawShadowMap(); + DrawScene(); + + DrawDebugShadowMap(); + + ModelsToRender.clear(); + glfwSwapBuffers(m_Window); +} + +void Renderer::DrawScene() +{ + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glViewport(0, 0, WIDTH, HEIGHT); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClearColor(1.0f, 1.0f, 0.0f, 1.0f); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); #ifdef DEBUG glDisable(GL_CULL_FACE); glPolygonMode(GL_BACK, GL_LINE); #endif // Draw models + glm::mat4 depthViewMatrix = glm::lookAt(m_SunPosition, m_SunTarget, glm::vec3(0, 1, 0)); + glm::mat4 depthCamera = m_SunProjection * depthViewMatrix; + glm::mat4 depthMVP = depthCamera; + glm::mat4 biasMatrix( + 0.5, 0.0, 0.0, 0.0, + 0.0, 0.5, 0.0, 0.0, + 0.0, 0.0, 0.5, 0.0, + 0.5, 0.5, 0.5, 1.0 + ); + glm::mat4 depthBiasMVP = biasMatrix * depthMVP; + m_ShaderProgram.Bind(); - glPolygonMode(GL_FRONT_AND_BACK, m_DrawWireframe ? GL_LINE : GL_FILL); - DrawModels(); - + glUniformMatrix4fv(glGetUniformLocation(m_ShaderProgram.GetHandle(), "DepthMVP"), 1, GL_FALSE, glm::value_ptr(depthBiasMVP)); + glUniform3fv(glGetUniformLocation(m_ShaderProgram.GetHandle(), "position"), 3, Light_position.data()); + glUniform3fv(glGetUniformLocation(m_ShaderProgram.GetHandle(), "specular"), 3, Light_specular.data()); + glUniform3fv(glGetUniformLocation(m_ShaderProgram.GetHandle(), "diffuse"), 3, Light_diffuse.data()); + glUniform1fv(glGetUniformLocation(m_ShaderProgram.GetHandle(), "constantAttenuation"), 3, Light_constantAttenuation.data()); + glUniform1fv(glGetUniformLocation(m_ShaderProgram.GetHandle(), "linearAttenuation"), 3, Light_linearAttenuation.data()); + glUniform1fv(glGetUniformLocation(m_ShaderProgram.GetHandle(), "quadraticAttenuation"), 3, Light_quadraticAttenuation.data()); + glUniform1fv(glGetUniformLocation(m_ShaderProgram.GetHandle(), "spotExponent"), 3, Light_spotExponent.data()); + if (m_DrawWireframe) { + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + } + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, m_ShadowDepthTexture); + DrawModels(m_ShaderProgram); + #ifdef DEBUG - // Debug draw normals + // Debug draw model normals if (m_DrawNormals) { m_ShaderProgramNormals.Bind(); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - DrawModels(); + DrawModels(m_ShaderProgramNormals); } #endif - - ModelsToRender.clear(); - -#ifdef DEBUG - // Debug draw normals - if (m_DrawNormals) { - m_ShaderProgramNormals.Bind(); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - DrawModels(); - } -#endif - - ModelsToRender.clear(); - - glfwSwapBuffers(m_Window); } -void Renderer::DrawModels() +void Renderer::DrawShadowMap() +{ + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + + glBindFramebuffer(GL_FRAMEBUFFER, m_ShadowFrameBuffer); + glViewport(0, 0, 2048*2, 2048*2); + + glClear(GL_DEPTH_BUFFER_BIT); + //glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + + glm::mat4 depthViewMatrix = glm::lookAt(m_SunPosition, m_SunTarget, glm::vec3(0, 1, 0)); + glm::mat4 depthCamera = m_SunProjection * depthViewMatrix; + + //glm::mat4 cameraMatrix = depthProjectionMatrix * m_Camera->ViewMatrix(); + + glm::mat4 MVP; + + m_ShaderProgramShadows.Bind(); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + for (int i = 0; i < ModelsToRender.size(); i++) + { + ModelData* modelData = ModelsToRender.at(i); + auto model = modelData->model; + + MVP = depthCamera * modelData->ModelMatrix; + glUniformMatrix4fv(glGetUniformLocation(m_ShaderProgramShadows.GetHandle(), "MVP"), 1, GL_FALSE, glm::value_ptr(MVP)); + + glBindVertexArray(model->VAO); + for (auto texGroup : model->TextureGroups) { + glDrawArrays(GL_TRIANGLES, texGroup.StartIndex, texGroup.EndIndex - texGroup.StartIndex + 1); + } + } +} + +void Renderer::DrawDebugShadowMap() +{ + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glViewport(0, 0, 200*(16.f/9.f), 200); + + glClear(GL_DEPTH_BUFFER_BIT); + //glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + + m_ShaderProgramShadowsDrawDepth.Bind(); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, m_ShadowDepthTexture); + glBindVertexArray(m_ScreenQuad); + glDrawArrays(GL_TRIANGLES, 0, 6); +} + +void Renderer::DrawModels(ShaderProgram &shader) { glm::mat4 cameraMatrix = m_Camera->ProjectionMatrix() * m_Camera->ViewMatrix(); @@ -108,23 +241,14 @@ void Renderer::DrawModels() auto model = modelData->model; MVP = cameraMatrix * modelData->ModelMatrix; - glUniformMatrix4fv(glGetUniformLocation(m_ShaderProgram.GetHandle(), "MVP"), 1, GL_FALSE, glm::value_ptr(MVP)); - glUniformMatrix4fv(glGetUniformLocation(m_ShaderProgram.GetHandle(), "model"), 1, GL_FALSE, glm::value_ptr(modelData->ModelMatrix)); - glUniformMatrix4fv(glGetUniformLocation(m_ShaderProgram.GetHandle(), "view"), 1, GL_FALSE, glm::value_ptr(m_Camera->ViewMatrix())); - glUniform3fv(glGetUniformLocation(m_ShaderProgram.GetHandle(), "position"), 3, Light_position.data()); - glUniform3fv(glGetUniformLocation(m_ShaderProgram.GetHandle(), "specular"), 3, Light_specular.data()); - glUniform3fv(glGetUniformLocation(m_ShaderProgram.GetHandle(), "diffuse"), 3, Light_diffuse.data()); - glUniform1fv(glGetUniformLocation(m_ShaderProgram.GetHandle(), "constantAttenuation"), 3, Light_constantAttenuation.data()); - glUniform1fv(glGetUniformLocation(m_ShaderProgram.GetHandle(), "linearAttenuation"), 3, Light_linearAttenuation.data()); - glUniform1fv(glGetUniformLocation(m_ShaderProgram.GetHandle(), "quadraticAttenuation"), 3, Light_quadraticAttenuation.data()); - glUniform1fv(glGetUniformLocation(m_ShaderProgram.GetHandle(), "spotExponent"), 3, Light_spotExponent.data()); - - + glUniformMatrix4fv(glGetUniformLocation(shader.GetHandle(), "MVP"), 1, GL_FALSE, glm::value_ptr(MVP)); + glUniformMatrix4fv(glGetUniformLocation(shader.GetHandle(), "model"), 1, GL_FALSE, glm::value_ptr(modelData->ModelMatrix)); + glUniformMatrix4fv(glGetUniformLocation(shader.GetHandle(), "view"), 1, GL_FALSE, glm::value_ptr(m_Camera->ViewMatrix())); glBindVertexArray(model->VAO); for (auto texGroup : model->TextureGroups) { glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texGroup.Texture->texture); - glDrawArrays(GL_TRIANGLES, texGroup.StartIndex, (texGroup.EndIndex - texGroup.StartIndex + 1) * abs(sin(glfwGetTime()))); + glDrawArrays(GL_TRIANGLES, texGroup.StartIndex, texGroup.EndIndex - texGroup.StartIndex + 1); } } } @@ -173,23 +297,43 @@ void Renderer::AddPointLightToDraw( } - -void Renderer::LoadContent() +GLuint Renderer::CreateQuad() { - auto standardVS = std::shared_ptr(new VertexShader("Shaders/Vertex.glsl")); - auto standardFS = std::shared_ptr(new FragmentShader("Shaders/Fragment.glsl")); + float quadVertices[] = { + -1.0f, -1.0f, 0.0f, + 1.0f, 1.0f, 0.0f, + -1.0f, 1.0f, 0.0f, - auto normalsGS = std::shared_ptr(new GeometryShader("Shaders/Normals.geo.glsl")); - auto normalsFS = std::shared_ptr(new FragmentShader("Shaders/Normals.frag.glsl")); + -1.0f, -1.0f, 0.0f, + 1.0f, -1.0f, 0.0f, + 1.0f, 1.0f, 0.0f, + }; + float quadTexCoords[] = { + 0.0f, 0.0f, + 1.0f, 1.0f, + 0.0f, 1.0f, - m_ShaderProgram.AddShader(standardVS); - m_ShaderProgram.AddShader(standardFS); - m_ShaderProgram.Compile(); - m_ShaderProgram.Link(); + 0.0f, 0.0f, + 1.0f, 0.0f, + 1.0f, 1.0f, + }; + GLuint vbo[2], vao; + glGenBuffers(2, vbo); + glBindBuffer(GL_ARRAY_BUFFER, vbo[0]); + glBufferData(GL_ARRAY_BUFFER, 3 * 6 * sizeof(float), quadVertices, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, vbo[1]); + glBufferData(GL_ARRAY_BUFFER, 2 * 6 * sizeof(float), quadTexCoords, GL_STATIC_DRAW); + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + glBindBuffer(GL_ARRAY_BUFFER, vbo[0]); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); + glBindBuffer(GL_ARRAY_BUFFER, vbo[1]); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, 0); + glEnableVertexAttribArray(0); + glEnableVertexAttribArray(2); - m_ShaderProgramNormals.AddShader(normalsGS); - m_ShaderProgramNormals.AddShader(standardVS); - m_ShaderProgramNormals.AddShader(normalsFS); - m_ShaderProgramNormals.Compile(); - m_ShaderProgramNormals.Link(); -} + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + return vao; +} \ No newline at end of file diff --git a/Escape-the-Dawn/Renderer.h b/Escape-the-Dawn/Renderer.h index b75f6bd..7fcca0d 100644 --- a/Escape-the-Dawn/Renderer.h +++ b/Escape-the-Dawn/Renderer.h @@ -83,12 +83,27 @@ private: bool m_DrawNormals; bool m_DrawWireframe; + glm::vec3 m_SunPosition; + glm::vec3 m_SunTarget; + glm::mat4 m_SunProjection; + + GLuint m_ScreenQuad; + GLuint m_ShadowFrameBuffer; + GLuint m_ShadowDepthTexture; + std::shared_ptr m_Camera; ShaderProgram m_ShaderProgram; ShaderProgram m_ShaderProgramNormals; + ShaderProgram m_ShaderProgramShadows; + ShaderProgram m_ShaderProgramShadowsDrawDepth; - void DrawModels(); + void DrawScene(); + void DrawModels(ShaderProgram &shader); + void DrawShadowMap(); + void CreateShadowMap(int resolution); + GLuint CreateQuad(); + void DrawDebugShadowMap(); }; diff --git a/Escape-the-Dawn/Shaders/Fragment.glsl b/Escape-the-Dawn/Shaders/Fragment.glsl index d4e1733..a852e1b 100644 --- a/Escape-the-Dawn/Shaders/Fragment.glsl +++ b/Escape-the-Dawn/Shaders/Fragment.glsl @@ -3,7 +3,8 @@ uniform mat4 model; uniform mat4 view; -layout(binding=0) uniform sampler2D texture; +layout(binding=0) uniform sampler2D texture0; +layout(binding=1) uniform sampler2D shadowMap; const int numberOfLights = 3; @@ -15,20 +16,21 @@ uniform float linearAttenuation[numberOfLights]; uniform float quadraticAttenuation[numberOfLights]; uniform float spotExponent[numberOfLights]; - in VertexData { +in VertexData { vec3 Position; vec3 Normal; vec2 TextureCoord; + vec3 ShadowCoord; } Input; -vec3 scene_ambient = vec3(0.5, 0.5, 0.5); +vec3 scene_ambient = vec3(0.2); out vec4 fragmentColor; void main() { // Texture - vec4 texel = texture2D(texture, Input.TextureCoord); + vec4 texel = texture2D(texture0, Input.TextureCoord); //vec4 texel = (blend.x * texel0) + (blend.y * texel1) + (blend.z * texel2); // @@ -43,48 +45,59 @@ void main() { vec3 Is; vec3 Id; - vec3 totalLighting = La * Ka; + // Shadows + //float cosTheta = clamp(dot(Input.Normal, vec3(0, 1, 0)), 0.0, 1.0); + //float bias = 0.001 * tan(acos(cosTheta)); // cosTheta is dot( n,l ), clamped between 0 and 1 + //bias = clamp(bias, 0.0, 0.01); + float bias = 0.003; + float visibility = 1.0; + vec4 shadowMapValue = texture(shadowMap, Input.ShadowCoord.xy); + if (shadowMapValue.z < Input.ShadowCoord.z - bias) { + visibility = 0.5; + } + + vec3 totalLighting = La * Ka * visibility; float attenuation; for(int i = 0; i < numberOfLights; i++) { - // Light - //vec3 lightPosition = vec3(0, 0, 2); - vec3 Ls = specular[i]; // Specular light - vec3 Ld = diffuse[i]; // Diffuse light + // Light + //vec3 lightPosition = vec3(0, 0, 2); + vec3 Ls = specular[i]; // Specular light + vec3 Ld = diffuse[i]; // Diffuse light + vec3 lightPosView = vec3(view * vec4(position[i], 1.0)); + vec3 surfacePosition = vec3(model * vec4(Input.Position, 1.0)); + vec3 surfacePosView = vec3(view * vec4(surfacePosition, 1.0)); + vec3 surfaceToLight = normalize(lightPosView - surfacePosView); + mat3 normalMatrix = transpose(inverse(mat3(view * model))); + vec3 surfaceNormal = normalize(normalMatrix * Input.Normal); - vec3 lightPosView = vec3(view * vec4(position[i], 1.0)); - vec3 surfacePosition = vec3(model * vec4(Input.Position, 1.0)); - vec3 surfacePosView = vec3(view * vec4(surfacePosition, 1.0)); - vec3 surfaceToLight = normalize(lightPosView - surfacePosView); - mat3 normalMatrix = transpose(inverse(mat3(view * model))); - vec3 surfaceNormal = normalize(normalMatrix * Input.Normal); - - float dist = length(position[i] - surfacePosition); + float dist = length(position[i] - surfacePosition); - attenuation = 1.0 / (constantAttenuation[i] - + linearAttenuation[i] * dist - + quadraticAttenuation[i] * pow(dist, 2.0)); - //attenuation = attenuation * pow(clampedCosine, spotExponent[i]); + attenuation = 1.0 / (constantAttenuation[i] + + linearAttenuation[i] * dist + + quadraticAttenuation[i] * pow(dist, 2.0)); + //attenuation = attenuation * pow(clampedCosine, spotExponent[i]); - // Diffuse light - float dotProd = dot(surfaceToLight, surfaceNormal); - dotProd = max(dotProd, 0.0); + // Diffuse light + float dotProd = dot(surfaceToLight, surfaceNormal); + dotProd = max(dotProd, 0.0); - Id = Ld * Kd * abs(dotProd) * attenuation; + Id = Ld * Kd * abs(dotProd) * attenuation; - // Specular light - vec3 reflection = reflect(-surfaceToLight, surfaceNormal); - float dotSpecular = dot(reflection, normalize(-surfacePosView)); - dotSpecular = max(dotSpecular, 0.0); - float specularFactor = pow(dotSpecular, 30.0); // Specular factor + // Specular light + vec3 reflection = reflect(-surfaceToLight, surfaceNormal); + float dotSpecular = dot(reflection, normalize(-surfacePosView)); + dotSpecular = max(dotSpecular, 0.0); + float specularFactor = pow(dotSpecular, 30.0); // Specular factor - Is = attenuation * Ls * Ks * specularFactor; + Is = attenuation * Ls * Ks * specularFactor; - totalLighting = totalLighting + Id + Is; + totalLighting = totalLighting + Id + Is; } + fragmentColor = vec4(totalLighting, 1.0) * texel; diff --git a/Escape-the-Dawn/Shaders/ShadowMap.frag.glsl b/Escape-the-Dawn/Shaders/ShadowMap.frag.glsl new file mode 100644 index 0000000..adae8d5 --- /dev/null +++ b/Escape-the-Dawn/Shaders/ShadowMap.frag.glsl @@ -0,0 +1,9 @@ +#version 430 + +uniform mat4 MVP; + +layout(location = 0) out float FragmentDepth; + +void main() { + FragmentDepth = gl_FragCoord.z; +} \ No newline at end of file diff --git a/Escape-the-Dawn/Shaders/ShadowMap.vert.glsl b/Escape-the-Dawn/Shaders/ShadowMap.vert.glsl new file mode 100644 index 0000000..042411c --- /dev/null +++ b/Escape-the-Dawn/Shaders/ShadowMap.vert.glsl @@ -0,0 +1,22 @@ +#version 430 + +uniform mat4 MVP; + +layout(location = 0) in vec3 Position; +layout(location = 1) in vec3 Normal; +layout(location = 2) in vec2 TextureCoord; + +out VertexData { + vec3 Position; + vec3 Normal; + vec2 TextureCoord; +} Output; + +void main() +{ + gl_Position = MVP * vec4(Position, 1.0); + + Output.Position = Position; + Output.Normal = Normal; + Output.TextureCoord = TextureCoord; +} \ No newline at end of file diff --git a/Escape-the-Dawn/Shaders/Vertex.glsl b/Escape-the-Dawn/Shaders/Vertex.glsl index 042411c..2b5b0e5 100644 --- a/Escape-the-Dawn/Shaders/Vertex.glsl +++ b/Escape-the-Dawn/Shaders/Vertex.glsl @@ -1,6 +1,7 @@ #version 430 uniform mat4 MVP; +uniform mat4 DepthMVP; layout(location = 0) in vec3 Position; layout(location = 1) in vec3 Normal; @@ -10,6 +11,7 @@ out VertexData { vec3 Position; vec3 Normal; vec2 TextureCoord; + vec3 ShadowCoord; } Output; void main() @@ -19,4 +21,5 @@ void main() Output.Position = Position; Output.Normal = Normal; Output.TextureCoord = TextureCoord; + Output.ShadowCoord = vec3(DepthMVP * vec4(Position, 1.0)); } \ No newline at end of file diff --git a/Escape-the-Dawn/Shaders/VisualizeDepth.frag.glsl b/Escape-the-Dawn/Shaders/VisualizeDepth.frag.glsl new file mode 100644 index 0000000..eef8e6e --- /dev/null +++ b/Escape-the-Dawn/Shaders/VisualizeDepth.frag.glsl @@ -0,0 +1,24 @@ +#version 430 + +layout(binding = 0) uniform sampler2D DepthTexture; + +in VertexData { + vec3 Position; + vec2 TextureCoord; +} Input; + +out vec4 FragmentColor; + +float LinearizeDepth(float z) +{ + float n = 0.1; // camera z near + float f = 10.0; // camera z far + return (2.0 * n) / (f + n - z * (f - n)); +} + +void main() { + float z = texture(DepthTexture, Input.TextureCoord).x; + vec4 color = vec4(z, z, z, 0); + + FragmentColor = color; +} \ No newline at end of file diff --git a/Escape-the-Dawn/Shaders/VisualizeDepth.vert.glsl b/Escape-the-Dawn/Shaders/VisualizeDepth.vert.glsl new file mode 100644 index 0000000..32e6205 --- /dev/null +++ b/Escape-the-Dawn/Shaders/VisualizeDepth.vert.glsl @@ -0,0 +1,17 @@ +#version 430 + +layout(location = 0) in vec3 Position; +layout(location = 2) in vec2 TextureCoord; + +out VertexData { + vec3 Position; + vec2 TextureCoord; +} Output; + +void main() +{ + gl_Position = vec4(Position, 1.0); + + Output.Position = Position; + Output.TextureCoord = TextureCoord; +} \ No newline at end of file diff --git a/Escape-the-Dawn/plane.mtl b/Escape-the-Dawn/plane.mtl index 750fa40..2961836 100644 --- a/Escape-the-Dawn/plane.mtl +++ b/Escape-the-Dawn/plane.mtl @@ -1,7 +1,7 @@ -# Blender MTL File: 'obstaclesandstuff.blend' +# Blender MTL File: 'None' # Material Count: 1 -newmtl Material.004 +newmtl Material.001 Ns 96.078431 Ka 0.000000 0.000000 0.000000 Kd 0.640000 0.640000 0.640000