123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- #ifndef UNIVERSAL_CLUSTERING_INCLUDED
- #define UNIVERSAL_CLUSTERING_INCLUDED
- #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Input.hlsl"
- #if USE_CLUSTERED_LIGHTING
- // TODO: Remove after PR #4039 is merged
- // Select uint4 component by index.
- // Helper to improve codegen for 2d indexing (data[x][y])
- // Replace:
- // data[i / 4][i % 4];
- // with:
- // select4(data[i / 4], i % 4);
- uint ClusteringSelect4(uint4 v, uint i)
- {
- // x = 0 = 00
- // y = 1 = 01
- // z = 2 = 10
- // w = 3 = 11
- uint mask0 = uint(int(i << 31) >> 31);
- uint mask1 = uint(int(i << 30) >> 31);
- return
- (((v.w & mask0) | (v.z & ~mask0)) & mask1) |
- (((v.y & mask0) | (v.x & ~mask0)) & ~mask1);
- }
- struct ClusteredLightLoop
- {
- uint baseIndex;
- uint tileMask;
- uint wordIndex;
- uint bitIndex;
- uint zBinMinMask;
- uint zBinMaxMask;
- #if LIGHTS_PER_TILE > 32
- uint wordMin;
- uint wordMax;
- #endif
- };
- ClusteredLightLoop ClusteredLightLoopInit(float2 normalizedScreenSpaceUV, float3 positionWS)
- {
- ClusteredLightLoop state = (ClusteredLightLoop)0;
- uint2 tileId = uint2(normalizedScreenSpaceUV * _AdditionalLightsTileScale);
- state.baseIndex = (tileId.y * _AdditionalLightsTileCountX + tileId.x) * (LIGHTS_PER_TILE / 32);
- float viewZ = dot(GetViewForwardDir(), positionWS - GetCameraPositionWS());
- uint zBinIndex = min(4*MAX_ZBIN_VEC4S - 1, (uint)(sqrt(viewZ) * _AdditionalLightsZBinScale) - _AdditionalLightsZBinOffset);
- uint zBinData = ClusteringSelect4(asuint(_AdditionalLightsZBins[zBinIndex / 4]), zBinIndex % 4);
- uint2 zBin = min(uint2(zBinData & 0xFFFF, (zBinData >> 16) & 0xFFFF), MAX_VISIBLE_LIGHTS - 1);
- uint2 zBinWords = zBin / 32;
- state.zBinMinMask = 0xFFFFFFFF << (zBin.x & 0x1F);
- state.zBinMaxMask = 0xFFFFFFFF >> (31 - (zBin.y & 0x1F));
- #if LIGHTS_PER_TILE > 32
- state.wordMin = zBinWords.x;
- state.wordMax = zBinWords.y;
- state.wordIndex = zBinWords.x;
- #endif
- #if SHADER_TARGET < 45
- state.bitIndex = zBin.x & 0x1F;
- #endif
- return state;
- }
- bool ClusteredLightLoopNextWord(inout ClusteredLightLoop state)
- {
- #if LIGHTS_PER_TILE > 32
- uint wordMin = state.wordMin;
- uint wordMax = state.wordMax;
- #else
- uint wordMin = 0;
- uint wordMax = 0;
- #endif
- if (state.wordIndex > wordMax) return false;
- uint index = state.baseIndex + state.wordIndex;
- state.tileMask = ClusteringSelect4(asuint(_AdditionalLightsTiles[index / 4]), index % 4);
- if (state.wordIndex == wordMin) state.tileMask &= state.zBinMinMask;
- if (state.wordIndex == wordMax) state.tileMask &= state.zBinMaxMask;
- state.wordIndex++;
- #if SHADER_TARGET < 45
- state.bitIndex = 0;
- #endif
- return true;
- }
- bool ClusteredLightLoopNextLight(inout ClusteredLightLoop state)
- {
- if (state.tileMask == 0) return false;
- #if SHADER_TARGET < 45
- while ((state.tileMask & (1 << state.bitIndex)) == 0) state.bitIndex++;
- #else
- state.bitIndex = firstbitlow(state.tileMask);
- #endif
- state.tileMask ^= (1 << state.bitIndex);
- return true;
- }
- uint ClusteredLightLoopGetLightIndex(ClusteredLightLoop state)
- {
- return _AdditionalLightsDirectionalCount + (state.wordIndex - 1) * 32 + state.bitIndex;
- }
- #endif
- #endif
|