Clustering.hlsl 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. #ifndef UNIVERSAL_CLUSTERING_INCLUDED
  2. #define UNIVERSAL_CLUSTERING_INCLUDED
  3. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Input.hlsl"
  4. #if USE_CLUSTERED_LIGHTING
  5. // TODO: Remove after PR #4039 is merged
  6. // Select uint4 component by index.
  7. // Helper to improve codegen for 2d indexing (data[x][y])
  8. // Replace:
  9. // data[i / 4][i % 4];
  10. // with:
  11. // select4(data[i / 4], i % 4);
  12. uint ClusteringSelect4(uint4 v, uint i)
  13. {
  14. // x = 0 = 00
  15. // y = 1 = 01
  16. // z = 2 = 10
  17. // w = 3 = 11
  18. uint mask0 = uint(int(i << 31) >> 31);
  19. uint mask1 = uint(int(i << 30) >> 31);
  20. return
  21. (((v.w & mask0) | (v.z & ~mask0)) & mask1) |
  22. (((v.y & mask0) | (v.x & ~mask0)) & ~mask1);
  23. }
  24. struct ClusteredLightLoop
  25. {
  26. uint baseIndex;
  27. uint tileMask;
  28. uint wordIndex;
  29. uint bitIndex;
  30. uint zBinMinMask;
  31. uint zBinMaxMask;
  32. #if LIGHTS_PER_TILE > 32
  33. uint wordMin;
  34. uint wordMax;
  35. #endif
  36. };
  37. ClusteredLightLoop ClusteredLightLoopInit(float2 normalizedScreenSpaceUV, float3 positionWS)
  38. {
  39. ClusteredLightLoop state = (ClusteredLightLoop)0;
  40. uint2 tileId = uint2(normalizedScreenSpaceUV * _AdditionalLightsTileScale);
  41. state.baseIndex = (tileId.y * _AdditionalLightsTileCountX + tileId.x) * (LIGHTS_PER_TILE / 32);
  42. float viewZ = dot(GetViewForwardDir(), positionWS - GetCameraPositionWS());
  43. uint zBinIndex = min(4*MAX_ZBIN_VEC4S - 1, (uint)(sqrt(viewZ) * _AdditionalLightsZBinScale) - _AdditionalLightsZBinOffset);
  44. uint zBinData = ClusteringSelect4(asuint(_AdditionalLightsZBins[zBinIndex / 4]), zBinIndex % 4);
  45. uint2 zBin = min(uint2(zBinData & 0xFFFF, (zBinData >> 16) & 0xFFFF), MAX_VISIBLE_LIGHTS - 1);
  46. uint2 zBinWords = zBin / 32;
  47. state.zBinMinMask = 0xFFFFFFFF << (zBin.x & 0x1F);
  48. state.zBinMaxMask = 0xFFFFFFFF >> (31 - (zBin.y & 0x1F));
  49. #if LIGHTS_PER_TILE > 32
  50. state.wordMin = zBinWords.x;
  51. state.wordMax = zBinWords.y;
  52. state.wordIndex = zBinWords.x;
  53. #endif
  54. #if SHADER_TARGET < 45
  55. state.bitIndex = zBin.x & 0x1F;
  56. #endif
  57. return state;
  58. }
  59. bool ClusteredLightLoopNextWord(inout ClusteredLightLoop state)
  60. {
  61. #if LIGHTS_PER_TILE > 32
  62. uint wordMin = state.wordMin;
  63. uint wordMax = state.wordMax;
  64. #else
  65. uint wordMin = 0;
  66. uint wordMax = 0;
  67. #endif
  68. if (state.wordIndex > wordMax) return false;
  69. uint index = state.baseIndex + state.wordIndex;
  70. state.tileMask = ClusteringSelect4(asuint(_AdditionalLightsTiles[index / 4]), index % 4);
  71. if (state.wordIndex == wordMin) state.tileMask &= state.zBinMinMask;
  72. if (state.wordIndex == wordMax) state.tileMask &= state.zBinMaxMask;
  73. state.wordIndex++;
  74. #if SHADER_TARGET < 45
  75. state.bitIndex = 0;
  76. #endif
  77. return true;
  78. }
  79. bool ClusteredLightLoopNextLight(inout ClusteredLightLoop state)
  80. {
  81. if (state.tileMask == 0) return false;
  82. #if SHADER_TARGET < 45
  83. while ((state.tileMask & (1 << state.bitIndex)) == 0) state.bitIndex++;
  84. #else
  85. state.bitIndex = firstbitlow(state.tileMask);
  86. #endif
  87. state.tileMask ^= (1 << state.bitIndex);
  88. return true;
  89. }
  90. uint ClusteredLightLoopGetLightIndex(ClusteredLightLoop state)
  91. {
  92. return _AdditionalLightsDirectionalCount + (state.wordIndex - 1) * 32 + state.bitIndex;
  93. }
  94. #endif
  95. #endif