Skip to content

Commit

Permalink
feat(rendering): Add Shadow Normal Offset Bias in the deferred shading
Browse files Browse the repository at this point in the history
  • Loading branch information
GalaxyCrush committed Nov 22, 2024
1 parent e32490e commit 0a8fd95
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 8 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Audio asset (#230, **@Dageus**, **@diogomsmiranda**).
- Compatibility with CMake find_package (#1326, **@RiscadoA**).
- A proper Nix package which can be used to install Cubos and Tesseratos (#1327, **RiscadoA**).
- Added the option to use Shadow Normal Offset Bias algorithm (#1308, **@GalaxyCrush**)

### Changed

Expand Down
24 changes: 21 additions & 3 deletions engine/assets/render/deferred_shading.fs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ struct DirectionalLight
vec4 shadowFarSplitDistances[3]; // intended to be a float array, but std140 layout aligns array elements
// to vec4 size; number of vec4s = ceiling(MaxCascades / 4 components)
int numCascades;
float normalOffsetScale;
};

struct PointLight
Expand All @@ -49,6 +50,7 @@ struct SpotLight
vec2 shadowMapSize;
float shadowBias;
float shadowBlurRadius;
float normalOffsetScale;
};

layout(std140) uniform PerScene
Expand Down Expand Up @@ -80,13 +82,27 @@ float remap(float value, float min1, float max1, float min2, float max2)
return max2 + (value - min1) * (max2 - min2) / (max1 - min1);
}

vec3 applyNormalOffset(vec3 normal, vec3 lightDir, vec3 position, float normalOffsetScale) {

float prod = dot(normal, lightDir);
prod = max(0.0, prod);

float slopeScale = 0.02;
float offset = slopeScale * prod + normalOffsetScale;

vec3 offsetPosition = position + normal * offset;
return offsetPosition;
}

vec3 spotLightCalc(vec3 fragPos, vec3 fragNormal, uint lightI)
{
// Shadows
float shadow = 0.0;
if (spotLights[lightI].shadowMapSize.x > 0.0)
{
vec4 positionLightSpace = spotLights[lightI].matrix * vec4(fragPos, 1.0);
float normalOffsetScale = spotLights[lightI].normalOffsetScale;
vec3 offsetFragPos = normalOffsetScale > 0.0 ? applyNormalOffset(fragNormal, spotLights[lightI].direction.xyz, fragPos, normalOffsetScale) : fragPos;
vec4 positionLightSpace = spotLights[lightI].matrix * vec4(offsetFragPos, 1.0);
vec3 projCoords = positionLightSpace.xyz / positionLightSpace.w;
projCoords = projCoords * 0.5 + 0.5;
vec2 uv = projCoords.xy * spotLights[lightI].shadowMapSize + spotLights[lightI].shadowMapOffset;
Expand Down Expand Up @@ -136,12 +152,14 @@ vec3 spotLightCalc(vec3 fragPos, vec3 fragNormal, uint lightI)

vec3 directionalLightCalc(vec3 fragPos, vec3 fragNormal, uint lightI, bool drawShadows)
{
float normalOffsetScale = directionalLights[lightI].normalOffsetScale;
vec3 offsetFragPos = normalOffsetScale > 0.0 ? applyNormalOffset(fragNormal, directionalLights[lightI].direction.xyz, fragPos, normalOffsetScale) : fragPos;
// Shadows
float shadow = 0.0;
if (drawShadows)
{
// Select split
vec4 positionCameraSpace = inverse(inverseView) * vec4(fragPos, 1.0);
vec4 positionCameraSpace = inverse(inverseView) * vec4(offsetFragPos, 1.0);
float depthCameraSpace = abs(positionCameraSpace.z);
int split = directionalLights[lightI].numCascades - 1;
for (int i = 0; i < directionalLights[lightI].numCascades; i++)
Expand All @@ -155,7 +173,7 @@ vec3 directionalLightCalc(vec3 fragPos, vec3 fragNormal, uint lightI, bool drawS
}

// Sample shadow map
vec4 positionLightSpace = directionalLights[lightI].matrices[split] * vec4(fragPos, 1.0);
vec4 positionLightSpace = directionalLights[lightI].matrices[split] * vec4(offsetFragPos, 1.0);
vec3 projCoords = positionLightSpace.xyz / positionLightSpace.w;
projCoords = projCoords * 0.5 + 0.5;
if (projCoords.z < 1.0)
Expand Down
7 changes: 4 additions & 3 deletions engine/include/cubos/engine/render/shadows/caster.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ namespace cubos::engine
{
CUBOS_REFLECT;

float bias = 0.002F; ///< Shadow bias.
float blurRadius = 1.0F; ///< Shadow blur radius.
int id = -1; ///< Caster id for the shadow atlas.
float bias = 0.001F; ///< Shadow bias.
float blurRadius = 0.005F; ///< Shadow blur radius.
int id = -1; ///< Caster id for the shadow atlas.
float normalOffsetScale = 0.007F; ///< Scale of the normal offset.
};
} // namespace cubos::engine
8 changes: 6 additions & 2 deletions engine/src/render/deferred_shading/plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ namespace
4]; // intended to be a float array, but std140 layout aligns array elements
// to vec4 size; number of vec4s = ceiling(MaxCascades / 4 components)
int numCascades;
int padding2[3];
float normalOffsetScale;
int padding2[2];
};

struct PerPointLight
Expand All @@ -86,7 +87,8 @@ namespace
glm::vec2 shadowMapSize;
float shadowBias;
float shadowBlurRadius;
float padding[2];
float normalOffsetScale;
float padding[1];
};

struct PerScene
Expand Down Expand Up @@ -332,6 +334,7 @@ void cubos::engine::deferredShadingPlugin(Cubos& cubos)
perLight.shadowBlurRadius = caster.value().baseSettings.blurRadius;
perLight.numCascades = numCascades;
perScene.directionalLightWithShadowsId = directionalLightIndex;
perLight.normalOffsetScale = caster.value().baseSettings.normalOffsetScale;
directionalShadowMap = caster.value().shadowMaps.at(cameraEntity)->cascades;
}
directionalLightIndex++;
Expand Down Expand Up @@ -375,6 +378,7 @@ void cubos::engine::deferredShadingPlugin(Cubos& cubos)
perLight.shadowMapSize = slot->size;
perLight.shadowBias = caster.value().baseSettings.bias;
perLight.shadowBlurRadius = caster.value().baseSettings.blurRadius;
perLight.normalOffsetScale = caster.value().baseSettings.normalOffsetScale;
}
else
{
Expand Down
1 change: 1 addition & 0 deletions engine/src/render/shadows/caster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ CUBOS_REFLECT_IMPL(cubos::engine::ShadowCaster)
return core::ecs::TypeBuilder<ShadowCaster>("cubos::engine::ShadowCaster")
.withField("bias", &ShadowCaster::bias)
.withField("blurRadius", &ShadowCaster::blurRadius)
.withField("normalOffsetScale", &ShadowCaster::normalOffsetScale)
.build();
}

0 comments on commit 0a8fd95

Please sign in to comment.