설명 없음
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Clustering.hlsl 5.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. #ifndef UNIVERSAL_CLUSTERING_INCLUDED
  2. #define UNIVERSAL_CLUSTERING_INCLUDED
  3. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Input.hlsl"
  4. #if USE_FORWARD_PLUS
  5. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRendering.hlsl"
  6. // Debug switches for disabling parts of the algorithm. Not implemented for mobile.
  7. #define URP_FP_DISABLE_ZBINNING 0
  8. #define URP_FP_DISABLE_TILING 0
  9. // internal
  10. struct ClusterIterator
  11. {
  12. uint tileOffset;
  13. uint zBinOffset;
  14. uint tileMask;
  15. // Stores the next light index in first 16 bits, and the max light index in the last 16 bits.
  16. uint entityIndexNextMax;
  17. };
  18. // internal
  19. ClusterIterator ClusterInit(float2 normalizedScreenSpaceUV, float3 positionWS, int headerIndex)
  20. {
  21. ClusterIterator state = (ClusterIterator)0;
  22. #if defined(SUPPORTS_FOVEATED_RENDERING_NON_UNIFORM_RASTER)
  23. UNITY_BRANCH if (_FOVEATED_RENDERING_NON_UNIFORM_RASTER)
  24. {
  25. #if UNITY_UV_STARTS_AT_TOP
  26. // RemapFoveatedRenderingNonUniformToLinear expects the UV coordinate to be non-flipped, so we un-flip it before
  27. // the call, and then flip it back afterwards.
  28. normalizedScreenSpaceUV.y = 1.0 - normalizedScreenSpaceUV.y;
  29. #endif
  30. normalizedScreenSpaceUV = RemapFoveatedRenderingNonUniformToLinear(normalizedScreenSpaceUV);
  31. #if UNITY_UV_STARTS_AT_TOP
  32. normalizedScreenSpaceUV.y = 1.0 - normalizedScreenSpaceUV.y;
  33. #endif
  34. }
  35. #endif // SUPPORTS_FOVEATED_RENDERING_NON_UNIFORM_RASTER
  36. uint2 tileId = uint2(normalizedScreenSpaceUV * URP_FP_TILE_SCALE);
  37. state.tileOffset = tileId.y * URP_FP_TILE_COUNT_X + tileId.x;
  38. #if defined(USING_STEREO_MATRICES)
  39. state.tileOffset += URP_FP_TILE_COUNT * unity_StereoEyeIndex;
  40. #endif
  41. state.tileOffset *= URP_FP_WORDS_PER_TILE;
  42. float viewZ = dot(GetViewForwardDir(), positionWS - GetCameraPositionWS());
  43. uint zBinBaseIndex = (uint)((IsPerspectiveProjection() ? log2(viewZ) : viewZ) * URP_FP_ZBIN_SCALE + URP_FP_ZBIN_OFFSET);
  44. #if defined(USING_STEREO_MATRICES)
  45. zBinBaseIndex += URP_FP_ZBIN_COUNT * unity_StereoEyeIndex;
  46. #endif
  47. // The Zbin buffer is laid out in the following manner:
  48. // ZBin 0 ZBin 1
  49. // .-------------------------^------------------------. .----------------^-------
  50. // | header0 | header1 | word 1 | word 2 | ... | word N | header0 | header 1 | ...
  51. // `----------------v--------------'
  52. // URP_FP_WORDS_PER_TILE
  53. //
  54. // The total length of this buffer is `4*MAX_ZBIN_VEC4S`. `zBinBaseIndex` should
  55. // always point to the `header 0` of a ZBin, so we clamp it accordingly, to
  56. // avoid out-of-bounds indexing of the ZBin buffer.
  57. zBinBaseIndex = zBinBaseIndex * (2 + URP_FP_WORDS_PER_TILE);
  58. zBinBaseIndex = min(zBinBaseIndex, 4*MAX_ZBIN_VEC4S - (2 + URP_FP_WORDS_PER_TILE));
  59. uint zBinHeaderIndex = zBinBaseIndex + headerIndex;
  60. state.zBinOffset = zBinBaseIndex + 2;
  61. #if !URP_FP_DISABLE_ZBINNING
  62. uint header = Select4(asuint(urp_ZBins[zBinHeaderIndex / 4]), zBinHeaderIndex % 4);
  63. #else
  64. uint header = headerIndex == 0 ? ((URP_FP_PROBES_BEGIN - 1) << 16) : (((URP_FP_WORDS_PER_TILE * 32 - 1) << 16) | URP_FP_PROBES_BEGIN);
  65. #endif
  66. #if MAX_LIGHTS_PER_TILE > 32 || !defined(_ENVIRONMENTREFLECTIONS_OFF)
  67. state.entityIndexNextMax = header;
  68. #else
  69. uint tileIndex = state.tileOffset;
  70. uint zBinIndex = state.zBinOffset;
  71. if (URP_FP_WORDS_PER_TILE > 0)
  72. {
  73. state.tileMask =
  74. Select4(asuint(urp_Tiles[tileIndex / 4]), tileIndex % 4) &
  75. Select4(asuint(urp_ZBins[zBinIndex / 4]), zBinIndex % 4) &
  76. (0xFFFFFFFFu << (header & 0x1F)) & (0xFFFFFFFFu >> (31 - (header >> 16)));
  77. }
  78. #endif
  79. return state;
  80. }
  81. // internal
  82. bool ClusterNext(inout ClusterIterator it, out uint entityIndex)
  83. {
  84. #if MAX_LIGHTS_PER_TILE > 32 || !defined(_ENVIRONMENTREFLECTIONS_OFF)
  85. uint maxIndex = it.entityIndexNextMax >> 16;
  86. [loop] while (it.tileMask == 0 && (it.entityIndexNextMax & 0xFFFF) <= maxIndex)
  87. {
  88. // Extract the lower 16 bits and shift by 5 to divide by 32.
  89. uint wordIndex = ((it.entityIndexNextMax & 0xFFFF) >> 5);
  90. uint tileIndex = it.tileOffset + wordIndex;
  91. uint zBinIndex = it.zBinOffset + wordIndex;
  92. it.tileMask =
  93. #if !URP_FP_DISABLE_TILING
  94. Select4(asuint(urp_Tiles[tileIndex / 4]), tileIndex % 4) &
  95. #endif
  96. #if !URP_FP_DISABLE_ZBINNING
  97. Select4(asuint(urp_ZBins[zBinIndex / 4]), zBinIndex % 4) &
  98. #endif
  99. // Mask out the beginning and end of the word.
  100. (0xFFFFFFFFu << (it.entityIndexNextMax & 0x1F)) & (0xFFFFFFFFu >> (31 - min(31, maxIndex - wordIndex * 32)));
  101. // The light index can start at a non-multiple of 32, but the following iterations should always be multiples of 32.
  102. // So we add 32 and mask out the lower bits.
  103. it.entityIndexNextMax = (it.entityIndexNextMax + 32) & ~31;
  104. }
  105. #endif
  106. bool hasNext = it.tileMask != 0;
  107. uint bitIndex = FIRST_BIT_LOW(it.tileMask);
  108. it.tileMask ^= (1 << bitIndex);
  109. #if MAX_LIGHTS_PER_TILE > 32 || !defined(_ENVIRONMENTREFLECTIONS_OFF)
  110. // Subtract 32 because it stores the index of the _next_ word to fetch, but we want the current.
  111. // The upper 16 bits and bits representing values < 32 are masked out. The latter is due to the fact that it will be
  112. // included in what FIRST_BIT_LOW returns.
  113. entityIndex = (((it.entityIndexNextMax - 32) & (0xFFFF & ~31))) + bitIndex;
  114. #else
  115. entityIndex = bitIndex;
  116. #endif
  117. return hasNext;
  118. }
  119. #endif
  120. #endif