diff --git a/data/shaders/fs_default.glsl b/data/shaders/fs_default.glsl index f661b6e..1dcdb5d 100644 --- a/data/shaders/fs_default.glsl +++ b/data/shaders/fs_default.glsl @@ -7,12 +7,33 @@ uniform sampler2D uAlbedoTexture; #define USE_SAMPLER2D_SHADOW 1 +// +// Single Shadow MAp +// + #ifdef USE_SAMPLER2D_SHADOW uniform sampler2DShadow uShadowMap; #else uniform sampler2D uShadowMap; #endif +// +// Cascaded Shadow Maps +// + +const int NUM_SPLITS = 4; + +#ifdef USE_SAMPLER2D_SHADOW +uniform sampler2DShadow uShadowMaps[NUM_SPLITS]; +#else +uniform sampler2D uShadowMaps[NUM_SPLITS]; +#endif + +uniform mat4 uViewToLightMatrix[NUM_SPLITS]; +uniform float uShowCascadesAlpha; +uniform vec4 uShadowSplits; +uniform vec4 uShadowSplitBias; + uniform mat4 uModelMatrix; uniform mat4 uViewMatrix; @@ -26,7 +47,7 @@ out vec4 outColor; out vec3 outPosition; out vec3 outNormal; -float ShadowCalculationPCF(vec4 frag_pos_light_space) { +float ShadowCalculationPCF_OLD(vec4 frag_pos_light_space) { vec3 projected_coordinates = frag_pos_light_space.xyz / frag_pos_light_space.w; projected_coordinates = projected_coordinates * 0.5 + 0.5; @@ -54,46 +75,101 @@ float ShadowCalculationPCF(vec4 frag_pos_light_space) { return shadow; } -float ShadowCalculation(vec4 frag_pos_light_space) { +#ifdef USE_SAMPLER2D_SHADOW +float ShadowCalculationPCF(sampler2DShadow shadow_map, vec4 frag_pos_light_space, vec3 frag_normal_light_space, float shadow_bias) { +#else +float ShadowCalculationPCF(sampler2D shadow_map, vec4 frag_pos_light_space, vec3 frag_normal_light_space, float shadow_bias) { +#endif vec3 projected_coordinates = frag_pos_light_space.xyz / frag_pos_light_space.w; projected_coordinates = projected_coordinates * 0.5 + 0.5; + if (abs(projected_coordinates.z) > 1.0 ) { + return 0.0; + } + float current_depth = projected_coordinates.z; - float bias = 0.01; + float bias = 0.00; + bias = max(shadow_bias * (1.0 - dot(frag_normal_light_space, uLightDirection)), shadow_bias); + float shadow = 0.0; + vec2 texel_size = 1.0 / textureSize(shadow_map, 0); + for (int x = -1; x <= 1; ++x) { + for (int y = -1; y <= 1; ++y) { #ifdef USE_SAMPLER2D_SHADOW - float closest_depth = texture(uShadowMap, vec3(projected_coordinates.xy, current_depth - bias)); + vec2 coordinate = projected_coordinates.xy + vec2(x, y) * texel_size; + float pcf_depth = texture(shadow_map, vec3(coordinate, current_depth - bias)); #else - float closest_depth = texture(uShadowMap, projected_coordinates.xy).r; - bias = max(0.005 * (1.0 - dot(ioFragNormal, uLightDirection)), 0.003); + float pcf_depth = texture(shadow_map, projected_coordinates.xy).r; #endif + shadow += current_depth - bias > pcf_depth ? 1.0 : 0.0; + } + } - return current_depth - bias > closest_depth ? 1.0 : 0.0; + shadow /= 9.0; + + return shadow; +} + +vec3 get_cascade_color (float depth) { + if (depth < uShadowSplits[0]) { + return vec3 (1.0, 0.0, 0.0); + } else if (depth < uShadowSplits[1]) { + return vec3 (1.0, 1.0, 0.0); + } else if (depth < uShadowSplits[2]) { + return vec3 (0.0, 1.0, 0.0); + } + + return vec3 (0.0, 0.0, 1.0); } void main() { vec4 albedo_color = texture(uAlbedoTexture, ioFragTexCoords) * ioFragColor * uColor; + vec3 position = ioFragPosition.xyz; // ambient lighting float ambient_strength = 0.2; vec4 ambient = ambient_strength * albedo_color; // diffuse lighting - vec3 normal_dir = normalize(ioFragNormal); + vec3 normal = normalize(ioFragNormal); vec3 light_dir = -(mat3(uViewMatrix)) * uLightDirection; - float diff = max(dot(normal_dir, light_dir), 0.0); + float diff = max(dot(normal, light_dir), 0.0); vec4 diffuse = diff * albedo_color; // specular lighting vec3 view_dir = normalize(-ioFragPosition); vec3 halfway_dir = normalize(light_dir + view_dir); - float spec = pow(max(dot(normal_dir, halfway_dir), 0.0), 32); + float spec = pow(max(dot(normal, halfway_dir), 0.0), 32); vec4 specular = spec * vec4(0.5); // shadow - float shadow = ShadowCalculationPCF(ioFragPosLightSpace); + float shadow = 0; + if (-position.z < uShadowSplits[0]) { + // shadow (need to transform position and normal to light space) + vec4 position_light_space = uViewToLightMatrix[0] * vec4(position, 1.0); + vec3 normal_light_space = (transpose(inverse(uViewToLightMatrix[0])) * vec4(normal, 1.0)).xyz; + shadow = ShadowCalculationPCF(uShadowMaps[0], position_light_space, normal, uShadowSplitBias[0]); + } else if (-position.z< uShadowSplits[1]) { + vec4 position_light_space = uViewToLightMatrix[1] * vec4(position, 1.0); + vec3 normal_light_space = (transpose(inverse(uViewToLightMatrix[1])) * vec4(normal, 1.0)).xyz; + shadow = ShadowCalculationPCF(uShadowMaps[1], position_light_space, normal, uShadowSplitBias[1]); + } else if (-position.z< uShadowSplits[2]) { + vec4 position_light_space = uViewToLightMatrix[2] * vec4(position, 1.0); + vec3 normal_light_space = (transpose(inverse(uViewToLightMatrix[2])) * vec4(normal, 1.0)).xyz; + shadow = ShadowCalculationPCF(uShadowMaps[2], position_light_space, normal, uShadowSplitBias[2]); + } else { + vec4 position_light_space = uViewToLightMatrix[3] * vec4(position, 1.0); + vec3 normal_light_space = (transpose(inverse(uViewToLightMatrix[3])) * vec4(normal, 1.0)).xyz; + shadow = ShadowCalculationPCF(uShadowMaps[3], position_light_space, normal, uShadowSplitBias[3]); + } + + vec4 cascade = vec4(get_cascade_color(-position.z), 1.0); + ambient = (uShowCascadesAlpha * cascade) + (1.0 - uShowCascadesAlpha) * ambient; + outColor = (ambient + (1.0 - shadow) * (diffuse + specular)); + +// float shadow = ShadowCalculationPCF(uShadowMap, ioFragPosLightSpace, normal, 0.001); outColor = ambient + (1.0 - shadow) * (diffuse + specular); outPosition = ioFragPosition.xyz; diff --git a/data/shaders/fs_deferred_lighting.glsl b/data/shaders/fs_deferred_lighting.glsl index e348690..2ad6a19 100644 --- a/data/shaders/fs_deferred_lighting.glsl +++ b/data/shaders/fs_deferred_lighting.glsl @@ -126,7 +126,7 @@ void main() { vec3 cascade = get_cascade_color(-position.z); ambient = (uShowCascadesAlpha * cascade) + (1.0 - uShowCascadesAlpha) * ambient; - outColor = (ambient + (1.0 - shadow) * (diffuse + specular)) * ambient_occlusion; + outColor = (ambient + (1.0 - shadow) * (diffuse + specular)) * ambient_occlusion; // outColor = diffuse; // outColor = (ambient + (diffuse + specular)) * ambient_occlusion; diff --git a/data/shaders/vs_default.glsl b/data/shaders/vs_default.glsl index 938d4af..cc6f8d4 100644 --- a/data/shaders/vs_default.glsl +++ b/data/shaders/vs_default.glsl @@ -22,7 +22,7 @@ out vec4 ioFragPosLightSpace; void main() { mat4 model_view_matrix = uViewMatrix * uModelMatrix; - ioFragPosition = (model_view_matrix* inCoord).xyz; + ioFragPosition = (model_view_matrix * inCoord).xyz; ioFragNormal = transpose(inverse(mat3(model_view_matrix))) * inNormal; ioFragTexCoords = inUV; ioFragColor = inColor; diff --git a/data/shaders/vs_deferred_geometry.glsl b/data/shaders/vs_deferred_geometry.glsl index 60c8b83..53ce7f8 100644 --- a/data/shaders/vs_deferred_geometry.glsl +++ b/data/shaders/vs_deferred_geometry.glsl @@ -8,11 +8,13 @@ in vec4 inColor; uniform mat4 uModelMatrix; uniform mat4 uViewMatrix; uniform mat4 uProjectionMatrix; +uniform mat4 uLightSpaceMatrix; out vec3 ioFragPosition; out vec3 ioFragNormal; out vec2 ioFragTexCoords; out vec4 ioFragColor; +out vec4 ioFragPosLightSpace; void main() { mat4 model_view_matrix = uViewMatrix * uModelMatrix; @@ -21,6 +23,7 @@ void main() { ioFragNormal = transpose(inverse(mat3(model_view_matrix))) * inNormal; ioFragTexCoords = inUV; ioFragColor = inColor; + ioFragPosLightSpace = uLightSpaceMatrix * uModelMatrix * inCoord; gl_Position = uProjectionMatrix * model_view_matrix * inCoord; } diff --git a/src/modules/RenderModule.cc b/src/modules/RenderModule.cc index bf2f0da..f8c57a8 100644 --- a/src/modules/RenderModule.cc +++ b/src/modules/RenderModule.cc @@ -124,7 +124,6 @@ static void module_serialize ( SerializeBool(*serializer, "protot.RenderModule.mLight.mDebugDrawSplitLightBounds", gRenderer->mLight.mDebugDrawSplitLightBounds); SerializeVec4 (*serializer, "protot.RenderModule.mLight.mSplitBias", gRenderer->mLight.mSplitBias); SerializeVec4 (*serializer, "protot.RenderModule.mLight.mShadowSplits", gRenderer->mLight.mShadowSplits); - } static void module_finalize(struct module_state *state) { @@ -584,12 +583,6 @@ void Renderer::CheckRenderBuffers() { } } -void Renderer::ResizeTargets(int width, int height) { - mSSAOTarget.Resize(mSceneAreaWidth, mSceneAreaHeight, RenderTarget::EnableColor); - mSSAOBlurTarget.Resize(mSceneAreaWidth, mSceneAreaHeight, RenderTarget::EnableColor); - -} - void Renderer::RenderGl() { CheckRenderBuffers(); @@ -652,12 +645,21 @@ void Renderer::RenderGl() { * mCamera.mViewMatrix * mCamera.mProjectionMatrix; - // enable the render target - mForwardRenderingTarget.Bind(); + // Clear the SSAO Blur target + if (!mIsSSAOEnabled) { + mSSAOBlurTarget.Bind(); + GLenum draw_attachment_0[] = {GL_COLOR_ATTACHMENT0 }; + glDrawBuffers(1, draw_attachment_0); + glClearColor(1.f, 1.f, 1.f, 1.f); + glClear(GL_COLOR_BUFFER_BIT); + glDisable(GL_DEPTH_TEST); + } - if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { - gLog ("Cannot render: frame buffer invalid!"); - } + // enable the render target + mForwardRenderingTarget.Bind(); + GLenum draw_attachment_0[] = {GL_COLOR_ATTACHMENT0 }; + glDrawBuffers(1, draw_attachment_0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST); RenderProgram *program = &mDefaultProgram; @@ -711,29 +713,54 @@ void Renderer::RenderGl() { gVertexArray.Bind(); gXZPlaneGrid.Draw(GL_LINES); - if (!mIsSSAOEnabled) { - // Clear the SSAO Blur target - mSSAOBlurTarget.Bind(); - glViewport(0, 0, mCamera.mWidth, mCamera.mHeight); - GLenum draw_attachment_0[] = {GL_COLOR_ATTACHMENT0 }; - glDrawBuffers(1, draw_attachment_0); - glClearColor(255, 255, 255, 255); - glClear(GL_COLOR_BUFFER_BIT); - glDisable(GL_DEPTH_TEST); - gVertexArray.Bind(); - gScreenQuad.Draw(GL_TRIANGLES); - } - // Scene glUseProgram(program->mProgramId); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, mLight.mShadowMapTarget.mDepthTexture); + program->SetInt("uShadowMap", 0); + + if (!mUseDeferred) { + // Shadow Map Cascades + glActiveTexture(GL_TEXTURE5); + glBindTexture(GL_TEXTURE_2D, mLight.mSplitTarget[0].mDepthTexture); + glActiveTexture(GL_TEXTURE6); + glBindTexture(GL_TEXTURE_2D, mLight.mSplitTarget[1].mDepthTexture); + glActiveTexture(GL_TEXTURE7); + glBindTexture(GL_TEXTURE_2D, mLight.mSplitTarget[2].mDepthTexture); + glActiveTexture(GL_TEXTURE8); + glBindTexture(GL_TEXTURE_2D, mLight.mSplitTarget[3].mDepthTexture); + + GLint shadow_maps[cNumSplits]; + shadow_maps[0] = 5; + shadow_maps[1] = 6; + shadow_maps[2] = 7; + shadow_maps[3] = 8; + program->SetIntArray("uShadowMaps", cNumSplits, shadow_maps); + + Matrix44f light_matrices[cNumSplits]; + + for (int i = 0; i < cNumSplits; ++i) { + light_matrices[i] = mCamera.mViewMatrix.inverse() + * mLight.mSplitLightFrustum[i]; + } + program->SetFloat("uNear", mCamera.mNear); + program->SetFloat("uFar", mCamera.mFar); + program->SetVec4("uShadowSplits", mLight.mShadowSplits); + program->SetVec4("uShadowSplitBias", mLight.mSplitBias); + program->SetFloat("uShowCascadesAlpha", mLight.mShowCascadesAlpha); + + program->SetMat44Array("uViewToLightMatrix", cNumSplits, light_matrices); + program->SetMat44("uLightSpaceMatrix", mLight.mLightSpaceMatrix); + } + RenderScene(*program, mCamera); if (mSettings->RenderMode == SceneRenderModeDepth) { mForwardRenderingTarget.RenderToLinearizedDepth(mCamera.mNear, mCamera.mFar, mCamera.mIsOrthographic); } - if (mUseDeferred && mIsSSAOEnabled) { + if (mIsSSAOEnabled) { mSSAOTarget.Bind(); glViewport(0, 0, mCamera.mWidth, mCamera.mHeight); GLenum draw_attachment_0[] = {GL_COLOR_ATTACHMENT0 }; @@ -774,6 +801,7 @@ void Renderer::RenderGl() { mSSAOBlurTarget.Bind(); glViewport(0, 0, mCamera.mWidth, mCamera.mHeight); glDrawBuffers(1, draw_attachment_0); + glClearColor(1.f, 1.f, 1.f, 1.f); glClear(GL_COLOR_BUFFER_BIT); glDisable(GL_DEPTH_TEST); @@ -830,14 +858,14 @@ void Renderer::RenderGl() { glActiveTexture(GL_TEXTURE8); glBindTexture(GL_TEXTURE_2D, mLight.mSplitTarget[3].mDepthTexture); - GLint shadow_maps[4]; + GLint shadow_maps[cNumSplits]; shadow_maps[0] = 5; shadow_maps[1] = 6; shadow_maps[2] = 7; shadow_maps[3] = 8; mDeferredLighting.SetIntArray("uShadowMap", cNumSplits, shadow_maps); - Matrix44f light_matrices[3]; + Matrix44f light_matrices[cNumSplits]; for (int i = 0; i < cNumSplits; ++i) { light_matrices[i] = mCamera.mViewMatrix.inverse() @@ -860,6 +888,7 @@ void Renderer::RenderGl() { mDeferredLighting.SetVec3("uLightDirection", light_direction.normalized()); mDeferredLighting.SetFloat("uShadowBias", mLight.mShadowBias); + glDisable(GL_DEPTH_TEST); gVertexArray.Bind(); gScreenQuad.Draw(GL_TRIANGLES); } @@ -945,12 +974,6 @@ void Renderer::SubmitRenderCommands (RenderProgram &program, const Camera &camer program.SetVec3("uLightDirection", mLight.mDirection); program.SetVec3("uViewPosition", camera.mEye); - program.SetMat44("uLightSpaceMatrix", mLight.mLightSpaceMatrix); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, mLight.mShadowMapTarget.mDepthTexture); - program.SetInt("uShadowMap", 0); - glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, mDefaultTexture.mTextureId); program.SetInt("uAlbedoTexture", 1); @@ -1081,38 +1104,38 @@ void Renderer::DrawGui() { ImGui::RadioButton("Positions", &sRendererSettings.RenderMode, 4); ImGui::SameLine(); ImGui::RadioButton("AO", &sRendererSettings.RenderMode, 5); - if (mUseDeferred) { - glBindFramebuffer(GL_READ_FRAMEBUFFER, mDeferredLightingTarget.mFrameBufferId); - } else { - glBindFramebuffer(GL_READ_FRAMEBUFFER, mForwardRenderingTarget.mFrameBufferId); - } + if (mUseDeferred) { + glBindFramebuffer(GL_READ_FRAMEBUFFER, mDeferredLightingTarget.mFrameBufferId); + } else { + glBindFramebuffer(GL_READ_FRAMEBUFFER, mForwardRenderingTarget.mFrameBufferId); + } - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mRenderOutput.mFrameBufferId); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mRenderOutput.mFrameBufferId); - glBlitFramebuffer(0, 0, mSceneAreaWidth, mSceneAreaHeight, - 0, 0, mSceneAreaWidth, mSceneAreaHeight, - GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBlitFramebuffer(0, 0, mSceneAreaWidth, mSceneAreaHeight, + 0, 0, mSceneAreaWidth, mSceneAreaHeight, + GL_COLOR_BUFFER_BIT, GL_NEAREST); - glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); switch (sRendererSettings.RenderMode) { case SceneRenderModeDefault: - mRenderTextureRef.mTextureIdPtr = &mRenderOutput.mColorTexture; + mRenderTextureRef.mTextureIdPtr = &mRenderOutput.mColorTexture; break; - case SceneRenderModeColor: + case SceneRenderModeColor: mRenderTextureRef.mTextureIdPtr = &mForwardRenderingTarget.mColorTexture; break; - case SceneRenderModeDepth: + case SceneRenderModeDepth: mRenderTextureRef.mTextureIdPtr = &mForwardRenderingTarget.mLinearizedDepthTexture; break; - case SceneRenderModeNormals: + case SceneRenderModeNormals: mRenderTextureRef.mTextureIdPtr = &mForwardRenderingTarget.mNormalTexture; break; - case SceneRenderModePositions: + case SceneRenderModePositions: mRenderTextureRef.mTextureIdPtr = &mForwardRenderingTarget.mPositionTexture; break; - case SceneRenderModeAmbientOcclusion: + case SceneRenderModeAmbientOcclusion: mRenderTextureRef.mTextureIdPtr = &mSSAOBlurTarget.mColorTexture; break; }