ShadowDepthBase.bslinc 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. #include "$ENGINE$\PerObjectData.bslinc"
  2. #include "$ENGINE$\VertexInput.bslinc"
  3. mixin ShadowDepthBase
  4. {
  5. mixin PerObjectData;
  6. mixin VertexInput;
  7. // Render back-faces to reduce shadow acne (assuming thick geometry everywhere)
  8. raster
  9. {
  10. cull = cw;
  11. };
  12. code
  13. {
  14. struct ShadowVStoFS
  15. {
  16. float4 position : SV_Position;
  17. #ifdef USES_GS
  18. float4 worldPos : TEXCOORD0;
  19. #else
  20. #ifdef USES_PS
  21. float shadowPos : TEXCOORD0;
  22. #endif
  23. #endif
  24. };
  25. cbuffer ShadowParams
  26. {
  27. float4x4 gMatViewProj;
  28. float2 gNDCZToDeviceZ;
  29. float gDepthBias;
  30. float gInvDepthRange;
  31. };
  32. /** Converts Z value from device range ([0, 1]) to NDC space. */
  33. float DeviceZToNDCZ(float deviceZ)
  34. {
  35. return deviceZ / gNDCZToDeviceZ.x - gNDCZToDeviceZ.y;
  36. }
  37. /** Converts Z value from NDC space to device Z value in range [0, 1]. */
  38. float NDCZToDeviceZ(float ndcZ)
  39. {
  40. return (ndcZ + gNDCZToDeviceZ.y) * gNDCZToDeviceZ.x;
  41. }
  42. ShadowVStoFS vsmain(VertexInput_PO input)
  43. {
  44. ShadowVStoFS output;
  45. float4 worldPosition = getVertexWorldPosition(input);
  46. // If using a geometry shader, just pass through the relevant information
  47. // as the GS does the necessary transform and applies the depth bias
  48. #ifdef USES_GS
  49. output.worldPos = worldPosition;
  50. output.position = worldPosition;
  51. #else // USES_GS
  52. // Not using a geometry shader, transform to clip space
  53. float4 clipPos = mul(gMatViewProj, worldPosition);
  54. // Clamp geometry behind the near plane
  55. #ifdef CLAMP_TO_NEAR_PLANE
  56. float ndcZ = clipPos.z / clipPos.w;
  57. float deviceZ = NDCZToDeviceZ(ndcZ);
  58. #ifdef USES_PS
  59. if (deviceZ < 0)
  60. #else
  61. if (deviceZ < -gDepthBias)
  62. #endif
  63. {
  64. clipPos.z = DeviceZToNDCZ(0);
  65. clipPos.w = 1.0f;
  66. }
  67. #endif // CLAMP_TO_NEAR_PLANE
  68. // If using a pixel shader, output shadow depth in clip space, as
  69. // we'll apply bias to it in PS (depth needs to be interpolated in
  70. // a perspective correct way)
  71. #ifdef USES_PS
  72. output.shadowPos = clipPos.z;
  73. #else // Otherwise apply bias immediately
  74. clipPos.z = max(DeviceZToNDCZ(0), clipPos.z + gDepthBias);
  75. #endif // USES_PS
  76. output.position = clipPos;
  77. #endif // USES_GS
  78. return output;
  79. }
  80. };
  81. };