#pragma kernel CSMain #pragma multi_compile_local _ _PRODUCTION #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" float _ScatterRadius; float _Intensity; int _SampleCount; int _ApplyTonemap; uint _TextureSize; RWTexture2D _SSSLut; static const float VARIANCE[6] = { 0.0064, 0.0484, 0.1870, 0.5670, 1.9900, 7.4100 }; static const float3 WEIGHTS[6] = { float3(0.233, 0.455, 0.649), float3(0.100, 0.336, 0.344), float3(0.118, 0.198, 0.000), float3(0.113, 0.007, 0.007), float3(0.358, 0.004, 0.000), float3(0.078, 0.000, 0.000) }; float Gaussian(float v, float r) { return rcp(2.0 * PI * v) * exp((-r * r) / (2.0 * v)); } float3 RadianceScatter(float r) { float3 result = 0.0; for (int i = 0; i < 6; i++) { result += WEIGHTS[i] * Gaussian(VARIANCE[i], r); } return result; } float3 IntegrateDiffuseScattering_Ring(float theta, float r) { float x = -HALF_PI; float increment = PI / _SampleCount; float3 totalScatter = 0; float3 totalWeight = 0; while (x < HALF_PI) { float diffuse = saturate(cos(theta + x)); float distance = abs(2.0 * r * sin(x / 2.0)); float3 radiance = RadianceScatter(distance); totalScatter += radiance * diffuse; totalWeight += radiance; x += increment; } return totalScatter / totalWeight; } float3 FilmicTonemap(float3 color) { return (color * (6.2 * color + 0.5)) / (color * (6.2 * color + 1.7) + 0.06); } [numthreads(8,8,1)] void CSMain (uint3 id : SV_DispatchThreadID) { if (id.x > _TextureSize || id.y > _TextureSize) { return; } float2 uv = id.xy / float2(_TextureSize, _TextureSize); #if UNITY_UV_STARTS_AT_TOP && _PRODUCTION uv.y = 1.0 - uv.y; #endif float theta = acos(uv.x * 2.0 - 1.0); float r = rcp(max(uv.y, 0.001) * _ScatterRadius); float3 scatter = IntegrateDiffuseScattering_Ring(theta, r) * _Intensity; if (_ApplyTonemap == 1) { scatter = FilmicTonemap(scatter); } _SSSLut[id.xy] = float4(scatter, 1.0); }