Skip to content

Commit

Permalink
Lichdom: Accurate fix for CryEngine directional shadows!!!
Browse files Browse the repository at this point in the history
Achievement unlocked: World first fix for CryEngine shadows ;-)

These were tricky to solve, but at the end of the day the pattern is
actually not that hard.

The far clipping plane and screen resolution needs to be copied from the
vertex shader, as the variable in the PS that suggests it might have the
far clipping plane is not the right one - seems to be for the shadow
map?

The SV_Position v0 is adjusted in the pixel shader based on the
information from the depth buffer. This is scaled back to world Z by
multiplying by the far clipping plane, then the stereo correction
formula (with perspective divide) is applied and finally multiplied by
the screen resolution.
  • Loading branch information
DarkStarSword committed Jul 5, 2015
1 parent 436a5df commit 0680548
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 16 deletions.
29 changes: 21 additions & 8 deletions Lichdom Battlemage/ShaderFixes/83cd6b8f4158edba-ps_replace.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// shadow pixel shader
// directional lighting / shadow pixel shader

cbuffer PER_BATCH : register(b0)
{
Expand Down Expand Up @@ -28,15 +28,32 @@ Texture1D<float4> IniParams : register(t120);

void main(
float4 v0 : SV_POSITION0,
float4 v1 : TEXCOORD0,
float4 v2 : TEXCOORD1,
out float4 o0 : SV_Target0)
float4 v1 : TEXCOORD0, // xy = rotated view pos, zw = relative to something
float4 v2 : TEXCOORD1, // xy = screen, zw = scaled by resolution
out float4 o0 : SV_Target0,

float4 g_VS_NearFarClipDist : TEXCOORD2,
float4 g_VS_ScreenSize : TEXCOORD3

)
{
float4 r0,r1,r2,r3;
uint4 bitmask, uiDest;
float4 fDest;

float4 stereo = StereoParams.Load(0);
float4 params = IniParams.Load(0);

r0.x = sceneDepthSampler.Sample(sceneDepthSampler_s, v2.xy).x;

// Align shadows with ground. Scale the z buffer to get the depth and subtract
// the stereo correction formula. We have to take the perspective divide into
// account and multiply by the horizontal resolution since v0 is in pixels.
float depth = r0.x * g_VS_NearFarClipDist.y;
v0.x -= stereo.x * (depth - stereo.y) / depth * g_VS_ScreenSize.x / 2;

// *Basis* is already the start of the transformation from screen space into
// shadow map space, so we have to fix the coordinate before this point:
r0.yzw = vBasisMagnitudes.xyz * r0.xxx;
r1.xy = v1.zw * r0.xx + v1.xy;
r0.xy = v0.xy * r0.yz;
Expand Down Expand Up @@ -110,10 +127,6 @@ void main(
r0.y = r0.w + r0.y;
r0.y = -r0.y * r0.y + 1.000000000e+000;
o0.xyzw = r0.yyyy * r0.xxxx;

// Disable shadows:
o0 = 0;

return;
}

Expand Down
28 changes: 20 additions & 8 deletions Lichdom Battlemage/ShaderFixes/89472c0d62104dc8-vs_replace.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
cbuffer cb3 : register(b3)
{
float4 cb3[8];
}


cbuffer PER_BATCH : register(b0)
{
row_major float4x4 TexGen0 : packoffset(c0);
Expand All @@ -19,9 +13,16 @@ cbuffer PER_INSTANCE : register(b1)
row_major float4x4 CompMatrix : packoffset(c0);
}

// Filled in some missing declarations from other shaders:
cbuffer PER_FRAME : register(b3)
{
row_major float4x4 g_VS_ViewProjMatr : packoffset(c0);
float4 g_VS_SunLightDir : packoffset(c4);
float4 g_VS_WorldViewPos : packoffset(c6);
float4 g_VS_ScreenSize : packoffset(c7);
float4 g_VS_AnimGenParams : packoffset(c8);
float4 g_VS_NearFarClipDist : packoffset(c9);
row_major float4x4 g_VS_ViewProjZeroMatr : packoffset(c10);
}

Texture2D<float4> StereoParams : register(t125);
Expand All @@ -33,7 +34,12 @@ void main(
float3 v2 : TEXCOORD1,
out float4 o0 : SV_Position0,
out float4 o1 : TEXCOORD0,
out float4 o2 : TEXCOORD1)
out float4 o2 : TEXCOORD1,

out float4 nearfar : TEXCOORD2,
out float4 res : TEXCOORD3

)
{
float4 r0;
uint4 bitmask, uiDest;
Expand All @@ -52,9 +58,15 @@ void main(
r0.zw = g_vViewPos.zz * RotMatrix._m20_m21 + r0.zw;
o1.zw = r0.xy + -r0.zw;
o1.xy = r0.zw;
r0.xy = cb3[7].xy * v1.xy;
// For whatever reason the decompiler used cb3[7].xy here:
r0.xy = g_VS_ScreenSize.xy * v1.xy;
o2.zw = float2(2.500000e-001,2.500000e-001) * r0.xy;
o2.xy = v1.xy;

// Pass far clipping plane and screen resolution through to pixel shader:
nearfar = g_VS_NearFarClipDist;
res = g_VS_ScreenSize;

return;
}

Expand Down

0 comments on commit 0680548

Please sign in to comment.