#pragma kernel LightVolumeGradient #pragma kernel LightVolumeColors #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" // Tile size of this compute #define DEBUG_LIGHT_VOLUME_TILE_SIZE 8 // Input Runtime textures TEXTURE2D_X_FLOAT(_DebugLightCountBuffer); TEXTURE2D_X(_DebugColorAccumulationBuffer); // Data used for the computation Texture2D _ColorGradientTexture; int _MaxDebugLightCount; // The pixel radius to switch on the edge color float _BorderRadius; // output texture RW_TEXTURE2D_X(float4, _DebugLightVolumesTexture); [numthreads(DEBUG_LIGHT_VOLUME_TILE_SIZE, DEBUG_LIGHT_VOLUME_TILE_SIZE, 1)] void LightVolumeGradient(uint3 dispatchThreadId : SV_DispatchThreadID, uint2 groupThreadId : SV_GroupThreadID, uint2 groupId : SV_GroupID) { UNITY_XR_ASSIGN_VIEW_INDEX(dispatchThreadId.z); // Fetch the current pixel coordinate uint2 currentPixelCoordinate = groupId * DEBUG_LIGHT_VOLUME_TILE_SIZE + groupThreadId; // Lightcount at this pixel float lightCount = _DebugLightCountBuffer[COORD_TEXTURE2D_X(currentPixelCoordinate)].r; // Tonemap this pixel value bool noLights = lightCount == 0.0f; bool lightOverCount = lightCount > (float)(_MaxDebugLightCount + 0.1f); float lightSampleValue = saturate((lightCount - 1.0f) / (float)(_MaxDebugLightCount - 1.0f)); // Read the gradient color float4 gradientColor = _ColorGradientTexture.SampleLevel(s_linear_clamp_sampler, float2(lightSampleValue, 0.5f), 0); // Return the right color _DebugLightVolumesTexture[COORD_TEXTURE2D_X(currentPixelCoordinate)] = noLights ? 0.0f : (lightOverCount ? float4(1.0, 0.0, 0.0, 1.0) : gradientColor); } [numthreads(DEBUG_LIGHT_VOLUME_TILE_SIZE, DEBUG_LIGHT_VOLUME_TILE_SIZE, 1)] void LightVolumeColors(uint3 dispatchThreadId : SV_DispatchThreadID, uint2 groupThreadId : SV_GroupThreadID, uint2 groupId : SV_GroupID) { UNITY_XR_ASSIGN_VIEW_INDEX(dispatchThreadId.z); // Fetch the current pixel coordinate uint2 currentPixelCoordinate = groupId * DEBUG_LIGHT_VOLUME_TILE_SIZE + groupThreadId; // Lightcount at this pixel float lightCount = _DebugLightCountBuffer[COORD_TEXTURE2D_X(currentPixelCoordinate)].r; // Look around this pixel to check if this should be displayed as a border float maxLightCount = lightCount; bool isBorder = false; for (float radiusX = -_BorderRadius; radiusX <= _BorderRadius; ++radiusX) { for (float radiusY = -_BorderRadius; radiusY <= _BorderRadius; ++radiusY) { // Compute the target pixel int2 targetpixel = int2((uint)currentPixelCoordinate.x + radiusX, (uint)currentPixelCoordinate.y + radiusY); float neighborLightCount = _DebugLightCountBuffer[COORD_TEXTURE2D_X(targetpixel)].r; maxLightCount = max(maxLightCount, neighborLightCount); if(neighborLightCount != lightCount) { isBorder = true; break; } } } // Tonemap the light count float tonemappedLightCount = maxLightCount / (1.0f + maxLightCount); // Tonemap this pixel color float4 lightColor = _DebugColorAccumulationBuffer[COORD_TEXTURE2D_X(currentPixelCoordinate)]; float3 toneMappedLightColor = lightColor.xyz / (1.0f + lightColor.xyz); // Compose base if we are on the border or not _DebugLightVolumesTexture[COORD_TEXTURE2D_X(currentPixelCoordinate)] = isBorder ? float4(tonemappedLightCount * tonemappedLightCount, 0.0f, 0.0f, 1.0f) : float4(toneMappedLightColor, 1.0f); }