2021-09-09 20:42:29 -04:00

86 lines
3.6 KiB
Plaintext

#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<float4> _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);
}