From 178402e9646b11e3b0a61e189ba082161a228ac1 Mon Sep 17 00:00:00 2001 From: FakeShemp Date: Thu, 18 Feb 2016 10:08:29 +0100 Subject: [PATCH] cascade shadow wip --- include/Engine/Rendering/ShadowPass.h | 20 +++++- resources/Shaders/ForwardPlus.frag.glsl | 6 +- src/Engine/Editor/EditorRenderSystem.cpp | 2 +- src/Engine/Rendering/RenderSystem.cpp | 2 +- src/Engine/Rendering/ShadowPass.cpp | 91 ++++++++++++++++++++++-- 5 files changed, 108 insertions(+), 13 deletions(-) diff --git a/include/Engine/Rendering/ShadowPass.h b/include/Engine/Rendering/ShadowPass.h index c5bf038e..685432c8 100644 --- a/include/Engine/Rendering/ShadowPass.h +++ b/include/Engine/Rendering/ShadowPass.h @@ -9,11 +9,18 @@ #include "ShadowPassState.h" #include "imgui/imgui.h" +#define MAX_SPLITS 5 + //#include "ShadowPassState.h" // not created yet enum NearFar { Near = 0, Far = 1 }; enum LRBT { Left = 0, Right = 1, Bottom = 2, Top = 3 }; +struct ShadowCamera{ + Camera* camera; + std::array frustumCorners; +}; + class ShadowPass { public: @@ -37,7 +44,10 @@ public: private: - + void CalculateFrustum(RenderScene & scene, std::shared_ptr directionalLightJob); + glm::vec3 LightDirectionToPoint(glm::vec4 direction); + std::array UpdateFrustumPoints(Camera* cam, glm::vec3 center, glm::vec3 view_dir); + void UpdateSplitDist(std::array shadow_cams, float far_distance, float near_distance); EventBroker* m_EventBroker; @@ -52,7 +62,8 @@ private: GLuint m_DepthFBO; GLfloat m_NearFarPlane[2] = { -34.f, 27.f }; - GLfloat m_LRBT[4] = { -77.f, 75.f, -89.f, 89.f }; + //GLfloat m_LRBT[4] = { -77.f, 75.f, -89.f, 89.f }; + GLfloat m_LRBT[4] = { -10.f, 10.f, -10.f, 10.f }; glm::mat4 m_LightProjection; glm::mat4 m_LightView; @@ -62,6 +73,11 @@ private: GLuint resolutionSizeHeigth = 1024 * 8; bool m_ShadowOn = true; + + int m_CurrentNrOfSplits = 3; + float m_SplitWeight = 0.75f; + + std::array shadCams; }; #endif \ No newline at end of file diff --git a/resources/Shaders/ForwardPlus.frag.glsl b/resources/Shaders/ForwardPlus.frag.glsl index 1157a019..205f1c5d 100644 --- a/resources/Shaders/ForwardPlus.frag.glsl +++ b/resources/Shaders/ForwardPlus.frag.glsl @@ -228,8 +228,10 @@ void main() totalLighting.Specular += light_result.Specular; } - totalLighting.Diffuse *= (1.5 + vec4(AmbientColor.rgb, 1.0)) - vec4(vec3(shadowFactor), 0.0); - totalLighting.Specular *= (1.5 + vec4(AmbientColor.rgb, 1.0)) - vec4(vec3(shadowFactor), 0.0); + //totalLighting.Diffuse *= (1.5 + vec4(AmbientColor.rgb, 1.0)) - vec4(vec3(shadowFactor), 0.0); + //totalLighting.Specular *= (1.5 + vec4(AmbientColor.rgb, 1.0)) - vec4(vec3(shadowFactor), 0.0); + totalLighting.Diffuse *= (1.0 + vec4(AmbientColor.rgb, 1.0)) + vec4(vec3(shadowFactor, shadowFactor, 0.0), 0.0); + totalLighting.Specular *= (1.0 + vec4(AmbientColor.rgb, 1.0)) + vec4(vec3(shadowFactor, shadowFactor, 0.0), 0.0); //LightResult getInformation; diff --git a/src/Engine/Editor/EditorRenderSystem.cpp b/src/Engine/Editor/EditorRenderSystem.cpp index 4d65e9d3..1a521b88 100644 --- a/src/Engine/Editor/EditorRenderSystem.cpp +++ b/src/Engine/Editor/EditorRenderSystem.cpp @@ -7,7 +7,7 @@ EditorRenderSystem::EditorRenderSystem(World* m_World, EventBroker* eventBroker, { EVENT_SUBSCRIBE_MEMBER(m_ESetCamera, &EditorRenderSystem::OnSetCamera); auto resolution = Rectangle::Rectangle(1280, 720); - m_EditorCamera = new Camera((float)resolution.Width / resolution.Height, glm::radians(45.f), 0.01f, 5000.f); + m_EditorCamera = new Camera((float)resolution.Width / resolution.Height, glm::radians(45.f), 0.01f, 500.f); } void EditorRenderSystem::Update(double dt) diff --git a/src/Engine/Rendering/RenderSystem.cpp b/src/Engine/Rendering/RenderSystem.cpp index eaecf99e..03613842 100644 --- a/src/Engine/Rendering/RenderSystem.cpp +++ b/src/Engine/Rendering/RenderSystem.cpp @@ -10,7 +10,7 @@ RenderSystem::RenderSystem(World* world, EventBroker* eventBroker, const IRender EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &RenderSystem::OnInputCommand); EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &RenderSystem::OnPlayerSpawned); - m_Camera = new Camera((float)m_Renderer->Resolution().Width / m_Renderer->Resolution().Height, glm::radians(45.f), 0.01f, 5000.f); + m_Camera = new Camera((float)m_Renderer->Resolution().Width / m_Renderer->Resolution().Height, glm::radians(45.f), 0.01f, 300.f); } RenderSystem::~RenderSystem() diff --git a/src/Engine/Rendering/ShadowPass.cpp b/src/Engine/Rendering/ShadowPass.cpp index fbf25219..ca7b59f0 100644 --- a/src/Engine/Rendering/ShadowPass.cpp +++ b/src/Engine/Rendering/ShadowPass.cpp @@ -14,6 +14,86 @@ ShadowPass::~ShadowPass() } +// Compute the 8 corner points of the current view frustum +std::array ShadowPass::UpdateFrustumPoints(Camera* cam, glm::vec3 center, glm::vec3 view_dir) +{ + glm::vec3 up = glm::vec3(0.f, 1.f, 0.f); + glm::vec3 right = glm::normalize(glm::cross(view_dir, up)); + + glm::vec3 farCenter = center + view_dir * cam->FarClip(); + glm::vec3 nearCenter = center + view_dir * cam->NearClip(); + + up = glm::normalize(glm::cross(right, view_dir)); + + float near_height = tan(cam->FOV() / 2.0f) * cam->NearClip(); + float near_width = near_height * cam->AspectRatio(); + float far_height = tan(cam->FOV() / 2.0f) * cam->FarClip(); + float far_width = far_height * cam->AspectRatio(); + + std::array frustumPoints; + frustumPoints[0] = nearCenter - up*near_height - right*near_width; + frustumPoints[1] = nearCenter + up*near_height - right*near_width; + frustumPoints[2] = nearCenter + up*near_height + right*near_width; + frustumPoints[3] = nearCenter - up*near_height + right*near_width; + + frustumPoints[4] = farCenter - up*far_height - right*far_width; + frustumPoints[5] = farCenter + up*far_height - right*far_width; + frustumPoints[6] = farCenter + up*far_height + right*far_width; + frustumPoints[7] = farCenter - up*far_height + right*far_width; + + return frustumPoints; +} + +// UpdateSplitDist computes the near and far distances for every frustum slice +// in camera eye space - that is, at what distance does a slice start and end +void ShadowPass::UpdateSplitDist(std::array shadow_cams, float far_distance, float near_distance) +{ + float lambda = m_SplitWeight; + float ratio = far_distance / near_distance; + + shadow_cams[0].camera->SetNearClip(near_distance); + + for (int i = 1; i < m_CurrentNrOfSplits; i++) { + float si = i / static_cast(m_CurrentNrOfSplits); + + shadow_cams[i].camera->SetNearClip(lambda * (near_distance * powf(ratio, si)) + (1 - lambda) * (near_distance + (far_distance - near_distance) * si)); + shadow_cams[i - 1].camera->SetFarClip(shadow_cams[i].camera->NearClip() * 1.005f); + } + + shadow_cams[m_CurrentNrOfSplits - 1].camera->SetFarClip(far_distance); +} + +float applyCropMatrix() +{ + +} + +// GLM wants a point for glm::lookAt, brute out a point that is on the light direction's tangent. +glm::vec3 ShadowPass::LightDirectionToPoint(glm::vec4 direction) +{ + return -glm::normalize(glm::vec3(direction)); +} + +void ShadowPass::CalculateFrustum(RenderScene & scene, std::shared_ptr directionalLightJob) +{ + //m_LightView = glm::lookAt(LightDirectionToPoint(directionalLightJob->Direction), glm::vec3(0.f, 0.f, 0.f), glm::vec3(0.f, 1.f, 0.f)); + + m_LightProjection = glm::ortho(m_LRBT[Left], m_LRBT[Right], m_LRBT[Bottom], m_LRBT[Top], m_NearFarPlane[Near], m_NearFarPlane[Far]); + + glm::vec3 LightPoint = LightDirectionToPoint(directionalLightJob->Direction); + + float CameraDistance = scene.Camera->FarClip() - scene.Camera->NearClip(); + float CameraPercentiles[3] = { 0.f, CameraDistance * 0.2f, CameraDistance * 0.65f }; + + + glm::vec3 point = scene.Camera->Position() + (scene.Camera->Forward() * 30.f); + + m_LightView = glm::lookAt(LightPoint + point, point, glm::vec3(0.f, 1.f, 0.f)); + + m_LightSpaceMatrix = m_LightProjection * m_LightView; + + //scene.Camera-> +} void ShadowPass::InitializeFrameBuffers() { @@ -29,9 +109,10 @@ void ShadowPass::InitializeFrameBuffers() //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height, 0, GL_RGB, GL_FLOAT, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - 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_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_COMPARE_R_TO_TEXTURE); + glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, glm::vec4(1.f).data); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); //glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY); @@ -84,11 +165,7 @@ void ShadowPass::Draw(RenderScene & scene) auto directionalLightJob = std::dynamic_pointer_cast(job); if(directionalLightJob) { - //m_LightProjection = glm::ortho(m_LRBT[Left], m_LRBT[Right], m_LRBT[Bottom], m_LRBT[Top], m_NearFarPlane[Near], m_NearFarPlane[Far]); - m_LightProjection = glm::ortho(m_LRBT[Left], m_LRBT[Right], m_LRBT[Bottom], m_LRBT[Top], m_NearFarPlane[Near], m_NearFarPlane[Far]); - m_LightView = glm::lookAt(-glm::normalize(glm::vec3(directionalLightJob->Direction)), glm::vec3(0.f,0.f,0.f), glm::vec3(0.f,1.f,0.f)); - //m_LightView = glm::lookAt(glm::vec3(-20.0f, 20.0f, -20.0f), glm::vec3(0.0f), glm::vec3(1.0)); - m_LightSpaceMatrix = m_LightProjection * m_LightView; + CalculateFrustum(scene, directionalLightJob); glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(m_LightProjection)); glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(m_LightView));