ShadowDepthBase.bslinc 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  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. void linearizeDepth(inout float4 clipPos)
  43. {
  44. #ifdef CLAMP_TO_NEAR_PLANE
  45. float ndcZ = clipPos.z / clipPos.w;
  46. float deviceZ = NDCZToDeviceZ(ndcZ);
  47. // Clamp to near plane if behind it
  48. if (deviceZ < 0)
  49. {
  50. clipPos.z = DeviceZToNDCZ(0);
  51. clipPos.w = 1.0f;
  52. }
  53. #endif
  54. // Output linear depth
  55. #ifdef LINEAR_DEPTH_RANGE
  56. float linearDepth = clipPos.z * gInvDepthRange + gDepthBias;
  57. clipPos.z = linearDepth * clipPos.w;
  58. #endif
  59. }
  60. ShadowVStoFS vsmain(VertexInput_PO input)
  61. {
  62. ShadowVStoFS output;
  63. float4 worldPosition = getVertexWorldPosition(input);
  64. // If using a geometry shader, just pass through the relevant information
  65. // as the GS does the necessary transform and applies the depth bias
  66. #ifdef USES_GS
  67. output.worldPos = worldPosition;
  68. output.position = worldPosition;
  69. #else // USES_GS
  70. // Not using a geometry shader, transform to clip space
  71. float4 clipPos = mul(gMatViewProj, worldPosition);
  72. // Clamp geometry behind the near plane
  73. #ifdef CLAMP_TO_NEAR_PLANE
  74. float ndcZ = clipPos.z / clipPos.w;
  75. float deviceZ = NDCZToDeviceZ(ndcZ);
  76. if (deviceZ < 0)
  77. {
  78. clipPos.z = DeviceZToNDCZ(0);
  79. clipPos.w = 1.0f;
  80. }
  81. #endif // CLAMP_TO_NEAR_PLANE
  82. // If using a pixel shader, output shadow depth in clip space, as
  83. // we'll apply bias to it in PS (depth needs to be interpolated in
  84. // a perspective correct way)
  85. #ifdef USES_PS
  86. output.shadowPos = clipPos.z;
  87. #else // Otherwise apply bias immediately
  88. clipPos.z += gDepthBias;
  89. #endif // USES_PS
  90. output.position = clipPos;
  91. #endif // USES_GS
  92. return output;
  93. }
  94. };
  95. };