ShadowDepthBase.bslinc 2.5 KB

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