ReflectionProbeBlendWeight.azsl 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. // Specular IBL reflection pipeline:
  9. // Stencil -> BlendWeight -> GlobalFullscreen -> RenderOuter -> RenderInner -> Composite
  10. // -----------
  11. //
  12. // This shader writes the blend weight of a particular probe to this location in the blend
  13. // weight texture. This is an additive operation since other overlapping probes will write
  14. // their blend weights here as well. Note that this shader only considers pixels stenciled
  15. // to the outer volumes. Inner volumes always blend at 100% so there is no need to write them
  16. // to the blend weight texture.
  17. #include <scenesrg_all.srgi>
  18. #include <viewsrg_all.srgi>
  19. #include "ReflectionProbeRenderObjectSrg.azsli"
  20. ShaderResourceGroup PassSrg : SRG_PerPass
  21. {
  22. Texture2DMS<float> m_depth;
  23. }
  24. #include "ReflectionCommon.azsli"
  25. // Vertex Shader
  26. struct VSInput
  27. {
  28. float3 m_position : POSITION;
  29. };
  30. struct VSOutput
  31. {
  32. float4 m_position : SV_Position;
  33. };
  34. VSOutput MainVS(VSInput vsInput)
  35. {
  36. VSOutput OUT;
  37. float3 positionWS = mul(ObjectSrg::GetWorldMatrix(), float4(vsInput.m_position, 1.0)).xyz;
  38. OUT.m_position = mul(ViewSrg::m_viewProjectionMatrix, float4(positionWS, 1.0));
  39. return OUT;
  40. }
  41. // Pixel Shader
  42. struct PSOutput
  43. {
  44. float m_blendWeight : SV_Target0;
  45. };
  46. PSOutput MainPS(VSOutput IN, in uint sampleIndex : SV_SampleIndex)
  47. {
  48. // reconstruct world position from depth
  49. // Note: this is the world position of the rendered object covered by the volume, not the volume itself
  50. uint2 dimensions;
  51. uint samples;
  52. PassSrg::m_depth.GetDimensions(dimensions.x, dimensions.y, samples);
  53. float depth = PassSrg::m_depth.Load(IN.m_position.xy, sampleIndex).r;
  54. float3 positionWS = ReconstructWorldPositionFromDepth(IN.m_position.xy, depth, dimensions, sampleIndex).xyz;
  55. // make sure the pixel belongs to this probe volume
  56. // this is necessary since it could have the correct stencil value but actually reside
  57. // in another volume that's in between the camera and the volume we're rendering
  58. if (!ObbContainsPoint(ObjectSrg::GetWorldMatrixInverse(), ObjectSrg::m_outerObbHalfLengths, positionWS))
  59. {
  60. discard;
  61. }
  62. // determine blend based on position with respect to the inner and outer AABBs
  63. // if it's inside the inner AABB it blends at 100%, otherwise it's the percentage of the distance between the inner/outer AABB
  64. float blendWeight = 1.0f;
  65. if (!ObbContainsPoint(ObjectSrg::GetWorldMatrixInverse(), ObjectSrg::m_innerObbHalfLengths, positionWS))
  66. {
  67. // not inside the inner AABB, so it's in between the inner and outer AABBs
  68. // compute blend amount based on the distance to the outer AABB
  69. blendWeight = ComputeLerpBetweenInnerOuterOBBs(
  70. (float3x4)ObjectSrg::GetWorldMatrixInverse(),
  71. ObjectSrg::m_innerObbHalfLengths,
  72. ObjectSrg::m_outerObbHalfLengths,
  73. positionWS);
  74. }
  75. // write the blend weight (additive) at this position for the probe volume
  76. PSOutput OUT;
  77. OUT.m_blendWeight = blendWeight;
  78. return OUT;
  79. }