EEVEE-Next: Add Shadows PCF #118220

Merged
Miguel Pozo merged 24 commits from pragma37/blender:pull-eevee-pcf-shadows into main 2024-02-29 15:47:26 +01:00
2 changed files with 43 additions and 17 deletions
Showing only changes of commit c2d9212d61 - Show all commits

View File

@ -71,19 +71,16 @@ struct ShadowEvalResult {
* \{ */
/* TODO(fclem): Remove. Only here to avoid include order hell with common_math_lib. */
mat4x4 shadow_projection_perspective(
float left, float right, float bottom, float top, float near_clip, float far_clip)
mat4x4 shadow_projection_perspective(float side, float near_clip, float far_clip)
pragma37 marked this conversation as resolved Outdated

You can remove the TODO on top as this is now a valid optimization

You can remove the `TODO` on top as this is now a valid optimization
{
float x_delta = right - left;
float y_delta = top - bottom;
float z_delta = far_clip - near_clip;
mat4x4 mat = mat4x4(1.0);
if (x_delta != 0.0 && y_delta != 0.0 && z_delta != 0.0) {
mat[0][0] = near_clip * 2.0 / x_delta;
mat[1][1] = near_clip * 2.0 / y_delta;
mat[2][0] = (right + left) / x_delta; /* NOTE: negate Z. */
mat[2][1] = (top + bottom) / y_delta;
if (side != 0.0 && z_delta != 0.0) {
mat[0][0] = near_clip / side;
mat[1][1] = near_clip / side;
mat[2][0] = 0.0;
mat[2][1] = 0.0;
mat[2][2] = -(far_clip + near_clip) / z_delta;
mat[2][3] = -1.0;
mat[3][2] = (-2.0 * near_clip * far_clip) / z_delta;
@ -92,6 +89,25 @@ mat4x4 shadow_projection_perspective(
return mat;
}
mat4x4 shadow_projection_perspective_inverse(float side, float near_clip, float far_clip)
{
float z_delta = far_clip - near_clip;
float d = 2.0 * near_clip * far_clip;
mat4x4 mat = mat4x4(1.0);
if (side != 0.0 && z_delta != 0.0) {
pragma37 marked this conversation as resolved Outdated

I'm wondering if we could remove this check as we ensure both are valid on CPU side.

I'm wondering if we could remove this check as we ensure both are valid on CPU side.
mat[0][0] = side / near_clip;
mat[1][1] = side / near_clip;
mat[2][0] = 0.0;
mat[2][1] = 0.0;
mat[2][2] = 0.0;
mat[2][3] = (near_clip - far_clip) / d;
mat[3][2] = -1.0;
mat[3][3] = (near_clip + far_clip) / d;
}
return mat;
}
/**
* Convert occluder distance in shadow space to world space distance.
* Assuming the occluder is above the shading point in direction to the shadow projection center.
@ -117,16 +133,25 @@ mat4 shadow_punctual_projection_perspective(LightData light)
float clip_far = intBitsToFloat(light.clip_far);
float clip_near = intBitsToFloat(light.clip_near);
float clip_side = light.clip_side;
/* TODO: Could be simplified since frustum is completely symmetrical. */
return shadow_projection_perspective(
-clip_side, clip_side, -clip_side, clip_side, clip_near, clip_far);
return shadow_projection_perspective(clip_side, clip_near, clip_far);
}
vec3 shadow_punctual_reconstruct_position(ShadowSampleParams params, LightData light, vec3 uvw)
mat4 shadow_punctual_projection_perspective_inverse(LightData light)
{
/* Face Local (View) Space > Clip Space. */
float clip_far = intBitsToFloat(light.clip_far);
float clip_near = intBitsToFloat(light.clip_near);
float clip_side = light.clip_side;
return shadow_projection_perspective_inverse(clip_side, clip_near, clip_far);
}
vec3 shadow_punctual_reconstruct_position(ShadowSampleParams params,
mat4 wininv,
LightData light,
vec3 uvw)
{
vec3 clip_P = uvw * 2.0 - 1.0;
mat4 winmat = shadow_punctual_projection_perspective(light);
vec3 lP = project_point(inverse(winmat), clip_P);
vec3 lP = project_point(wininv, clip_P);
int face_id = params.tilemap_index - light.tilemap_index;
lP = shadow_punctual_face_local_to_local_position(face_id, lP);
return mat3(light.object_mat) * lP + light._position;

View File

@ -444,10 +444,11 @@ vec3 shadow_pcf_offset(LightData light, const bool is_directional, vec3 P, vec3
BP = line_plane_intersect(BP, dot(L, BP) > 0.0 ? L : -L, P, Ng);
}
else {
mat4 wininv = shadow_punctual_projection_perspective_inverse(light);
TP = shadow_punctual_reconstruct_position(
params, light, params.uv + vec3(uv_offset, 0.0, 0.0));
params, wininv, light, params.uv + vec3(uv_offset, 0.0, 0.0));
BP = shadow_punctual_reconstruct_position(
params, light, params.uv + vec3(0.0, uv_offset, 0.0));
params, wininv, light, params.uv + vec3(0.0, uv_offset, 0.0));
/* Project the offset positions into the surface plane. */
TP = line_plane_intersect(light._position, normalize(TP - light._position), P, Ng);
BP = line_plane_intersect(light._position, normalize(BP - light._position), P, Ng);
pragma37 marked this conversation as resolved Outdated

You could do it with a mat2x3.

You could do it with a `mat2x3`.