Added 4th shadow split and exposed per-split shadow map bias
parent
e9ba7f77cc
commit
0fd0b8409e
|
@ -6,7 +6,7 @@ uniform sampler2D uNormal;
|
|||
uniform sampler2D uColor;
|
||||
uniform sampler2D uAmbientOcclusion;
|
||||
|
||||
const int NUM_SPLITS = 3;
|
||||
const int NUM_SPLITS = 4;
|
||||
|
||||
#define USE_SAMPLER2D_SHADOW 1
|
||||
|
||||
|
@ -21,6 +21,7 @@ uniform mat4 uViewToLightMatrix[NUM_SPLITS];
|
|||
uniform float uNear;
|
||||
uniform float uFar;
|
||||
uniform vec4 uShadowSplits;
|
||||
uniform vec4 uShadowSplitBias;
|
||||
uniform vec3 uLightDirection;
|
||||
uniform float uShadowBias;
|
||||
|
||||
|
@ -29,9 +30,9 @@ in vec2 ioFragTexCoords;
|
|||
out vec3 outColor;
|
||||
|
||||
#ifdef USE_SAMPLER2D_SHADOW
|
||||
float ShadowCalculationPCF(sampler2DShadow shadow_map, vec4 frag_pos_light_space, vec3 frag_normal_light_space) {
|
||||
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 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;
|
||||
|
@ -43,7 +44,7 @@ float ShadowCalculationPCF(sampler2D shadow_map, vec4 frag_pos_light_space, vec3
|
|||
float current_depth = projected_coordinates.z;
|
||||
|
||||
float bias = 0.00;
|
||||
bias = max(0.001 * (1.0 - dot(frag_normal_light_space, uLightDirection)), uShadowBias);
|
||||
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);
|
||||
|
@ -101,19 +102,23 @@ void main() {
|
|||
float shadow = 0;
|
||||
float normalized_depth = (depth - uNear) / (uFar - uNear);
|
||||
|
||||
if (-position.z < uShadowSplits[1]) {
|
||||
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(uShadowMap[0], position_light_space, normal);
|
||||
} else if (-position.z< uShadowSplits[2]) {
|
||||
shadow = ShadowCalculationPCF(uShadowMap[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(uShadowMap[1], position_light_space, normal);
|
||||
} else {
|
||||
shadow = ShadowCalculationPCF(uShadowMap[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(uShadowMap[2], position_light_space, normal);
|
||||
shadow = ShadowCalculationPCF(uShadowMap[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(uShadowMap[3], position_light_space, normal, uShadowSplitBias[3]);
|
||||
}
|
||||
|
||||
// vec3 cascade = get_cascade_color(-position.z);
|
||||
|
|
|
@ -137,3 +137,8 @@ template <typename Serializer>
|
|||
bool SerializeVec3 (Serializer &serializer, const std::string &key, SimpleMath::Vector3f& value) {
|
||||
return serializer.SerializeData(key, reinterpret_cast<char*>(&value), sizeof(SimpleMath::Vector3f));
|
||||
}
|
||||
|
||||
template <typename Serializer>
|
||||
bool SerializeVec4 (Serializer &serializer, const std::string &key, SimpleMath::Vector4f& value) {
|
||||
return serializer.SerializeData(key, reinterpret_cast<char*>(&value), sizeof(SimpleMath::Vector4f));
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ using namespace SimpleMath::GL;
|
|||
struct Renderer;
|
||||
|
||||
float moving_factor = 1.0f;
|
||||
const int cNumSplits = 3;
|
||||
const int cNumSplits = 4;
|
||||
|
||||
struct RendererSettings {
|
||||
bool DrawLightDepth = false;
|
||||
|
@ -134,6 +134,9 @@ static void module_serialize (
|
|||
SerializeBool(*serializer, "protot.RenderModule.mLight.mDebugDrawSplitViewBounds", gRenderer->mLight.mDebugDrawSplitViewBounds);
|
||||
SerializeBool(*serializer, "protot.RenderModule.mLight.mDebugDrawSplitWorldBounds", gRenderer->mLight.mDebugDrawSplitWorldBounds);
|
||||
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) {
|
||||
|
@ -239,6 +242,7 @@ void Light::DrawGui() {
|
|||
ImGui::SliderFloat("Near", &mNear, -10.0f, 50.0f);
|
||||
ImGui::SliderFloat("Far", &mFar, -10.0f, 50.0f);
|
||||
ImGui::SliderFloat("Shadow Bias", &mShadowBias, 0.0f, 0.01f, "%.5f", 1.0f);
|
||||
ImGui::SliderFloat4("Shadow Splits Bias", mSplitBias.data(), 0.0f, 0.01f, "%.5f", 1.0f);
|
||||
ImGui::SliderFloat4("Shadow Splits", mShadowSplits.data(), 0.01f, 1.0f);
|
||||
|
||||
ImGui::Checkbox("Draw Split View Bounds", &mDebugDrawSplitViewBounds);
|
||||
|
@ -250,11 +254,12 @@ void Light::DrawGui() {
|
|||
ImGui::RadioButton("Split 0", &sRendererSettings.ActiveShadowMapSplit, 0); ImGui::SameLine();
|
||||
ImGui::RadioButton("Split 1", &sRendererSettings.ActiveShadowMapSplit, 1); ImGui::SameLine();
|
||||
ImGui::RadioButton("Split 2", &sRendererSettings.ActiveShadowMapSplit, 2); ImGui::SameLine();
|
||||
ImGui::RadioButton("Default", &sRendererSettings.ActiveShadowMapSplit, 3);
|
||||
ImGui::RadioButton("Split 3", &sRendererSettings.ActiveShadowMapSplit, 3); ImGui::SameLine();
|
||||
ImGui::RadioButton("Default", &sRendererSettings.ActiveShadowMapSplit, 4);
|
||||
|
||||
RenderTarget* shadow_split_target = nullptr;
|
||||
|
||||
if (sRendererSettings.ActiveShadowMapSplit == 3) {
|
||||
if (sRendererSettings.ActiveShadowMapSplit == 4) {
|
||||
shadow_split_target = &mShadowMapTarget;
|
||||
} else {
|
||||
shadow_split_target = &mSplitTarget[sRendererSettings.ActiveShadowMapSplit];
|
||||
|
@ -295,14 +300,16 @@ void Light::UpdateSplits(const Camera& camera) {
|
|||
Matrix44f light_matrix = LookAt (mPosition, mPosition + mDirection, Vector3f (0.f, 1.0f, 0.0f));
|
||||
Matrix44f light_matrix_inv = light_matrix.inverse();
|
||||
|
||||
mShadowSplits[0] = near;
|
||||
mShadowSplits[1] = near + length * 0.02;
|
||||
mShadowSplits[2] = near + length * 0.2;
|
||||
mShadowSplits[0] = near + length * 0.02;
|
||||
mShadowSplits[1] = near + length * 0.1;
|
||||
mShadowSplits[2] = near + length * 0.3;
|
||||
mShadowSplits[3] = far;
|
||||
|
||||
float prev_split_far = near;
|
||||
|
||||
for (int i = 0; i < cNumSplits; ++i) {
|
||||
split_near = mShadowSplits[i];
|
||||
float split_far = mShadowSplits[i + 1];
|
||||
split_near = prev_split_far;
|
||||
float split_far = mShadowSplits[i];
|
||||
|
||||
mSplitViewFrustum[i] = look_at * Perspective (camera.mFov, aspect, split_near, split_far);
|
||||
|
||||
|
@ -369,6 +376,8 @@ void Light::UpdateSplits(const Camera& camera) {
|
|||
|
||||
mSplitLightFrustum[i] = mSplitCamera[i].mViewMatrix
|
||||
* mSplitCamera[i].mProjectionMatrix;
|
||||
|
||||
prev_split_far = split_far;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -929,12 +938,15 @@ void Renderer::RenderGl() {
|
|||
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[3];
|
||||
GLint shadow_maps[4];
|
||||
shadow_maps[0] = 5;
|
||||
shadow_maps[1] = 6;
|
||||
shadow_maps[2] = 7;
|
||||
mDeferredLighting.SetIntArray("uShadowMap", 3, shadow_maps);
|
||||
shadow_maps[3] = 8;
|
||||
mDeferredLighting.SetIntArray("uShadowMap", cNumSplits, shadow_maps);
|
||||
|
||||
Matrix44f light_matrices[3];
|
||||
|
||||
|
@ -943,11 +955,12 @@ void Renderer::RenderGl() {
|
|||
* mLight.mSplitLightFrustum[i];
|
||||
}
|
||||
|
||||
mDeferredLighting.SetMat44Array("uViewToLightMatrix", 3, light_matrices);
|
||||
mDeferredLighting.SetMat44Array("uViewToLightMatrix", cNumSplits, light_matrices);
|
||||
|
||||
mDeferredLighting.SetFloat("uNear", mCamera.mNear);
|
||||
mDeferredLighting.SetFloat("uFar", mCamera.mFar);
|
||||
mDeferredLighting.SetVec4("uShadowSplits", mLight.mShadowSplits);
|
||||
mDeferredLighting.SetVec4("uShadowSplitBias", mLight.mSplitBias);
|
||||
|
||||
mDeferredLighting.SetMat44("uViewMatrix", mCamera.mViewMatrix);
|
||||
Matrix33f view_mat_rot = mCamera.mViewMatrix.block<3,3>(0,0);
|
||||
|
|
|
@ -39,12 +39,13 @@ struct Light {
|
|||
|
||||
Vector4f mShadowSplits = Vector4f (0.0, 0.1, 0.4, 1.0);
|
||||
|
||||
Matrix44f mSplitViewFrustum[3];
|
||||
Matrix44f mSplitLightFrustum[3];
|
||||
RenderTarget mSplitTarget[3];
|
||||
BBox mSplitBoundsLightSpace[3];
|
||||
BBox mSplitBoundsWorldSpace[3];
|
||||
Camera mSplitCamera[3];
|
||||
Matrix44f mSplitViewFrustum[4];
|
||||
Matrix44f mSplitLightFrustum[4];
|
||||
Vector4f mSplitBias = Vector4f (0.001f, 0.001f, 0.001f, 0.001f);
|
||||
RenderTarget mSplitTarget[4];
|
||||
BBox mSplitBoundsLightSpace[4];
|
||||
BBox mSplitBoundsWorldSpace[4];
|
||||
Camera mSplitCamera[4];
|
||||
|
||||
Light() :
|
||||
mPosition (Vector3f(0.f, 3, 0.0f)),
|
||||
|
|
Loading…
Reference in New Issue