Skip to content

Commit

Permalink
feat(rendering): change deferred shading to render directional shadows
Browse files Browse the repository at this point in the history
  • Loading branch information
tomas7770 committed Sep 30, 2024
1 parent 6db84e8 commit ab27b1d
Show file tree
Hide file tree
Showing 2 changed files with 266 additions and 13 deletions.
81 changes: 78 additions & 3 deletions engine/assets/render/deferred_shading.fs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,22 @@ uniform sampler2D albedoTexture;
uniform sampler2D ssaoTexture;
uniform sampler2D shadowAtlasTexture;

uniform sampler2DArray directionalShadowMap; // only one directional light with shadows is supported, for now

uniform vec2 viewportOffset;
uniform vec2 viewportSize;

struct DirectionalLight
{
vec4 direction;
vec4 color;
mat4 matrices[10]; // hardcoded max splits
float intensity;
float shadowBias;
float shadowBlurRadius;
float shadowMaxDistance;
vec4 shadowFarSplitDistances[3]; // hardcoded max splits
int numSplits;
};

struct PointLight
Expand Down Expand Up @@ -60,6 +68,8 @@ layout(std140) uniform PerScene
uint numDirectionalLights;
uint numPointLights;
uint numSpotLights;

int directionalLightWithShadowsId; // index of directional light that casts shadows, or -1 if none
};

layout(location = 0) out vec3 color;
Expand Down Expand Up @@ -120,9 +130,73 @@ vec3 spotLightCalc(vec3 fragPos, vec3 fragNormal, SpotLight light)
return vec3(0);
}

vec3 directionalLightCalc(vec3 fragNormal, DirectionalLight light)
vec3 directionalLightCalc(vec3 fragPos, vec3 fragNormal, DirectionalLight light, bool drawShadows)
{
return max(dot(fragNormal, -light.direction.xyz), 0) * light.intensity * vec3(light.color);
// Shadows
float shadow = 0.0;
if (drawShadows)
{
// Select split
vec4 positionCameraSpace = inverse(inverseView) * vec4(fragPos, 1.0);
float depthCameraSpace = abs(positionCameraSpace.z);
int split = light.numSplits - 1;
for (int i = 0; i < light.numSplits; i++)
{
float far;
switch (i % 4)
{
case 0:
far = light.shadowFarSplitDistances[i / 4].x;
break;
case 1:
far = light.shadowFarSplitDistances[i / 4].y;
break;
case 2:
far = light.shadowFarSplitDistances[i / 4].z;
break;
case 3:
far = light.shadowFarSplitDistances[i / 4].w;
break;
}
if (depthCameraSpace < far)
{
split = i;
break;
}
}

// Sample shadow map
vec4 positionLightSpace = light.matrices[split] * vec4(fragPos, 1.0);
vec3 projCoords = positionLightSpace.xyz / positionLightSpace.w;
projCoords = projCoords * 0.5 + 0.5;
if (projCoords.z < 1.0)
{
vec2 uv = projCoords.xy;
float currentDepth = projCoords.z;
float bias = light.shadowBias / positionLightSpace.w; // make the bias not depend on near/far planes
// PCF
if (light.shadowBlurRadius <= 0.001f)
{
float pcfDepth = texture(directionalShadowMap, vec3(uv.xy, split)).r;
shadow += currentDepth - bias > pcfDepth ? 1.0 : 0.0;
}
else
{
vec2 texelSize = vec2(1.0 / 1024.0); // largely arbitrary value, affects blur size
for(float x = -light.shadowBlurRadius; x <= light.shadowBlurRadius; x += light.shadowBlurRadius)
{
for(float y = -light.shadowBlurRadius; y <= light.shadowBlurRadius; y += light.shadowBlurRadius)
{
vec2 newUv = uv + vec2(x, y) * texelSize;
float pcfDepth = texture(directionalShadowMap, vec3(newUv.xy, split)).r;
shadow += currentDepth - bias > pcfDepth ? 1.0 : 0.0;
}
}
shadow /= 9.0;
}
}
}
return max(dot(fragNormal, -light.direction.xyz), 0) * (1.0 - shadow) * light.intensity * vec3(light.color);
}

vec3 pointLightCalc(vec3 fragPos, vec3 fragNormal, PointLight light)
Expand Down Expand Up @@ -174,7 +248,8 @@ void main()
}
for (uint i = 0u; i < numDirectionalLights; i++)
{
lighting += directionalLightCalc(normal, directionalLights[i]);
lighting += directionalLightCalc(position, normal, directionalLights[i],
int(i) == directionalLightWithShadowsId);
}
for (uint i = 0u; i < numPointLights; i++)
{
Expand Down
Loading

0 comments on commit ab27b1d

Please sign in to comment.