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 uColor;
|
||||||
uniform sampler2D uAmbientOcclusion;
|
uniform sampler2D uAmbientOcclusion;
|
||||||
|
|
||||||
const int NUM_SPLITS = 3;
|
const int NUM_SPLITS = 4;
|
||||||
|
|
||||||
#define USE_SAMPLER2D_SHADOW 1
|
#define USE_SAMPLER2D_SHADOW 1
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ uniform mat4 uViewToLightMatrix[NUM_SPLITS];
|
||||||
uniform float uNear;
|
uniform float uNear;
|
||||||
uniform float uFar;
|
uniform float uFar;
|
||||||
uniform vec4 uShadowSplits;
|
uniform vec4 uShadowSplits;
|
||||||
|
uniform vec4 uShadowSplitBias;
|
||||||
uniform vec3 uLightDirection;
|
uniform vec3 uLightDirection;
|
||||||
uniform float uShadowBias;
|
uniform float uShadowBias;
|
||||||
|
|
||||||
|
@ -29,9 +30,9 @@ in vec2 ioFragTexCoords;
|
||||||
out vec3 outColor;
|
out vec3 outColor;
|
||||||
|
|
||||||
#ifdef USE_SAMPLER2D_SHADOW
|
#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
|
#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
|
#endif
|
||||||
vec3 projected_coordinates = frag_pos_light_space.xyz / frag_pos_light_space.w;
|
vec3 projected_coordinates = frag_pos_light_space.xyz / frag_pos_light_space.w;
|
||||||
projected_coordinates = projected_coordinates * 0.5 + 0.5;
|
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 current_depth = projected_coordinates.z;
|
||||||
|
|
||||||
float bias = 0.00;
|
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;
|
float shadow = 0.0;
|
||||||
vec2 texel_size = 1.0 / textureSize(shadow_map, 0);
|
vec2 texel_size = 1.0 / textureSize(shadow_map, 0);
|
||||||
|
@ -101,19 +102,23 @@ void main() {
|
||||||
float shadow = 0;
|
float shadow = 0;
|
||||||
float normalized_depth = (depth - uNear) / (uFar - uNear);
|
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)
|
// shadow (need to transform position and normal to light space)
|
||||||
vec4 position_light_space = uViewToLightMatrix[0] * vec4(position, 1.0);
|
vec4 position_light_space = uViewToLightMatrix[0] * vec4(position, 1.0);
|
||||||
vec3 normal_light_space = (transpose(inverse(uViewToLightMatrix[0])) * vec4(normal, 1.0)).xyz;
|
vec3 normal_light_space = (transpose(inverse(uViewToLightMatrix[0])) * vec4(normal, 1.0)).xyz;
|
||||||
shadow = ShadowCalculationPCF(uShadowMap[0], position_light_space, normal);
|
shadow = ShadowCalculationPCF(uShadowMap[0], position_light_space, normal, uShadowSplitBias[0]);
|
||||||
} else if (-position.z< uShadowSplits[2]) {
|
} else if (-position.z< uShadowSplits[1]) {
|
||||||
vec4 position_light_space = uViewToLightMatrix[1] * vec4(position, 1.0);
|
vec4 position_light_space = uViewToLightMatrix[1] * vec4(position, 1.0);
|
||||||
vec3 normal_light_space = (transpose(inverse(uViewToLightMatrix[1])) * vec4(normal, 1.0)).xyz;
|
vec3 normal_light_space = (transpose(inverse(uViewToLightMatrix[1])) * vec4(normal, 1.0)).xyz;
|
||||||
shadow = ShadowCalculationPCF(uShadowMap[1], position_light_space, normal);
|
shadow = ShadowCalculationPCF(uShadowMap[1], position_light_space, normal, uShadowSplitBias[1]);
|
||||||
} else {
|
} else if (-position.z< uShadowSplits[2]) {
|
||||||
vec4 position_light_space = uViewToLightMatrix[2] * vec4(position, 1.0);
|
vec4 position_light_space = uViewToLightMatrix[2] * vec4(position, 1.0);
|
||||||
vec3 normal_light_space = (transpose(inverse(uViewToLightMatrix[2])) * vec4(normal, 1.0)).xyz;
|
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);
|
// 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) {
|
bool SerializeVec3 (Serializer &serializer, const std::string &key, SimpleMath::Vector3f& value) {
|
||||||
return serializer.SerializeData(key, reinterpret_cast<char*>(&value), sizeof(SimpleMath::Vector3f));
|
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;
|
struct Renderer;
|
||||||
|
|
||||||
float moving_factor = 1.0f;
|
float moving_factor = 1.0f;
|
||||||
const int cNumSplits = 3;
|
const int cNumSplits = 4;
|
||||||
|
|
||||||
struct RendererSettings {
|
struct RendererSettings {
|
||||||
bool DrawLightDepth = false;
|
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.mDebugDrawSplitViewBounds", gRenderer->mLight.mDebugDrawSplitViewBounds);
|
||||||
SerializeBool(*serializer, "protot.RenderModule.mLight.mDebugDrawSplitWorldBounds", gRenderer->mLight.mDebugDrawSplitWorldBounds);
|
SerializeBool(*serializer, "protot.RenderModule.mLight.mDebugDrawSplitWorldBounds", gRenderer->mLight.mDebugDrawSplitWorldBounds);
|
||||||
SerializeBool(*serializer, "protot.RenderModule.mLight.mDebugDrawSplitLightBounds", gRenderer->mLight.mDebugDrawSplitLightBounds);
|
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) {
|
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("Near", &mNear, -10.0f, 50.0f);
|
||||||
ImGui::SliderFloat("Far", &mFar, -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::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::SliderFloat4("Shadow Splits", mShadowSplits.data(), 0.01f, 1.0f);
|
||||||
|
|
||||||
ImGui::Checkbox("Draw Split View Bounds", &mDebugDrawSplitViewBounds);
|
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 0", &sRendererSettings.ActiveShadowMapSplit, 0); ImGui::SameLine();
|
||||||
ImGui::RadioButton("Split 1", &sRendererSettings.ActiveShadowMapSplit, 1); ImGui::SameLine();
|
ImGui::RadioButton("Split 1", &sRendererSettings.ActiveShadowMapSplit, 1); ImGui::SameLine();
|
||||||
ImGui::RadioButton("Split 2", &sRendererSettings.ActiveShadowMapSplit, 2); 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;
|
RenderTarget* shadow_split_target = nullptr;
|
||||||
|
|
||||||
if (sRendererSettings.ActiveShadowMapSplit == 3) {
|
if (sRendererSettings.ActiveShadowMapSplit == 4) {
|
||||||
shadow_split_target = &mShadowMapTarget;
|
shadow_split_target = &mShadowMapTarget;
|
||||||
} else {
|
} else {
|
||||||
shadow_split_target = &mSplitTarget[sRendererSettings.ActiveShadowMapSplit];
|
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 = LookAt (mPosition, mPosition + mDirection, Vector3f (0.f, 1.0f, 0.0f));
|
||||||
Matrix44f light_matrix_inv = light_matrix.inverse();
|
Matrix44f light_matrix_inv = light_matrix.inverse();
|
||||||
|
|
||||||
mShadowSplits[0] = near;
|
mShadowSplits[0] = near + length * 0.02;
|
||||||
mShadowSplits[1] = near + length * 0.02;
|
mShadowSplits[1] = near + length * 0.1;
|
||||||
mShadowSplits[2] = near + length * 0.2;
|
mShadowSplits[2] = near + length * 0.3;
|
||||||
mShadowSplits[3] = far;
|
mShadowSplits[3] = far;
|
||||||
|
|
||||||
|
float prev_split_far = near;
|
||||||
|
|
||||||
for (int i = 0; i < cNumSplits; ++i) {
|
for (int i = 0; i < cNumSplits; ++i) {
|
||||||
split_near = mShadowSplits[i];
|
split_near = prev_split_far;
|
||||||
float split_far = mShadowSplits[i + 1];
|
float split_far = mShadowSplits[i];
|
||||||
|
|
||||||
mSplitViewFrustum[i] = look_at * Perspective (camera.mFov, aspect, split_near, split_far);
|
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
|
mSplitLightFrustum[i] = mSplitCamera[i].mViewMatrix
|
||||||
* mSplitCamera[i].mProjectionMatrix;
|
* mSplitCamera[i].mProjectionMatrix;
|
||||||
|
|
||||||
|
prev_split_far = split_far;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -929,12 +938,15 @@ void Renderer::RenderGl() {
|
||||||
glBindTexture(GL_TEXTURE_2D, mLight.mSplitTarget[1].mDepthTexture);
|
glBindTexture(GL_TEXTURE_2D, mLight.mSplitTarget[1].mDepthTexture);
|
||||||
glActiveTexture(GL_TEXTURE7);
|
glActiveTexture(GL_TEXTURE7);
|
||||||
glBindTexture(GL_TEXTURE_2D, mLight.mSplitTarget[2].mDepthTexture);
|
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[0] = 5;
|
||||||
shadow_maps[1] = 6;
|
shadow_maps[1] = 6;
|
||||||
shadow_maps[2] = 7;
|
shadow_maps[2] = 7;
|
||||||
mDeferredLighting.SetIntArray("uShadowMap", 3, shadow_maps);
|
shadow_maps[3] = 8;
|
||||||
|
mDeferredLighting.SetIntArray("uShadowMap", cNumSplits, shadow_maps);
|
||||||
|
|
||||||
Matrix44f light_matrices[3];
|
Matrix44f light_matrices[3];
|
||||||
|
|
||||||
|
@ -943,11 +955,12 @@ void Renderer::RenderGl() {
|
||||||
* mLight.mSplitLightFrustum[i];
|
* mLight.mSplitLightFrustum[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
mDeferredLighting.SetMat44Array("uViewToLightMatrix", 3, light_matrices);
|
mDeferredLighting.SetMat44Array("uViewToLightMatrix", cNumSplits, light_matrices);
|
||||||
|
|
||||||
mDeferredLighting.SetFloat("uNear", mCamera.mNear);
|
mDeferredLighting.SetFloat("uNear", mCamera.mNear);
|
||||||
mDeferredLighting.SetFloat("uFar", mCamera.mFar);
|
mDeferredLighting.SetFloat("uFar", mCamera.mFar);
|
||||||
mDeferredLighting.SetVec4("uShadowSplits", mLight.mShadowSplits);
|
mDeferredLighting.SetVec4("uShadowSplits", mLight.mShadowSplits);
|
||||||
|
mDeferredLighting.SetVec4("uShadowSplitBias", mLight.mSplitBias);
|
||||||
|
|
||||||
mDeferredLighting.SetMat44("uViewMatrix", mCamera.mViewMatrix);
|
mDeferredLighting.SetMat44("uViewMatrix", mCamera.mViewMatrix);
|
||||||
Matrix33f view_mat_rot = mCamera.mViewMatrix.block<3,3>(0,0);
|
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);
|
Vector4f mShadowSplits = Vector4f (0.0, 0.1, 0.4, 1.0);
|
||||||
|
|
||||||
Matrix44f mSplitViewFrustum[3];
|
Matrix44f mSplitViewFrustum[4];
|
||||||
Matrix44f mSplitLightFrustum[3];
|
Matrix44f mSplitLightFrustum[4];
|
||||||
RenderTarget mSplitTarget[3];
|
Vector4f mSplitBias = Vector4f (0.001f, 0.001f, 0.001f, 0.001f);
|
||||||
BBox mSplitBoundsLightSpace[3];
|
RenderTarget mSplitTarget[4];
|
||||||
BBox mSplitBoundsWorldSpace[3];
|
BBox mSplitBoundsLightSpace[4];
|
||||||
Camera mSplitCamera[3];
|
BBox mSplitBoundsWorldSpace[4];
|
||||||
|
Camera mSplitCamera[4];
|
||||||
|
|
||||||
Light() :
|
Light() :
|
||||||
mPosition (Vector3f(0.f, 3, 0.0f)),
|
mPosition (Vector3f(0.f, 3, 0.0f)),
|
||||||
|
|
Loading…
Reference in New Issue