162 lines
3.7 KiB
Plaintext
162 lines
3.7 KiB
Plaintext
#pragma kernel SkinLut
|
|
#pragma kernel ShadowLut
|
|
|
|
#pragma multi_compile_local _ _PRODUCTION
|
|
|
|
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
|
|
|
|
#define _PROFILE_WIDTH 8.166
|
|
|
|
float _ScatterRadius;
|
|
float _PositionShift;
|
|
float _Intensity;
|
|
int _SampleCount;
|
|
int _ApplyTonemap;
|
|
|
|
uint _TextureSize;
|
|
|
|
RWTexture2D<float4> _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)
|
|
{
|
|
float3 totalScatter = 0;
|
|
float3 totalWeight = 0;
|
|
float increment = PI / _SampleCount;
|
|
|
|
float x = -HALF_PI;
|
|
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;
|
|
}
|
|
|
|
float newPenumbra(float pos, float penumbraWidth)
|
|
{
|
|
return saturate((pos * penumbraWidth - _PROFILE_WIDTH) / (penumbraWidth - _PROFILE_WIDTH));
|
|
}
|
|
|
|
float3 IntegrateShadowScattering(float penumbraLocation, float penumbraWidth)
|
|
{
|
|
float3 totalScatter = 0;
|
|
float3 totalWeights = 0;
|
|
float increment = (_PROFILE_WIDTH * 2) / _SampleCount;
|
|
|
|
penumbraWidth = max(penumbraWidth, _PROFILE_WIDTH + 1e-5);
|
|
|
|
float x = -_PROFILE_WIDTH;
|
|
while (x <= _PROFILE_WIDTH)
|
|
{
|
|
float light = newPenumbra(penumbraLocation + x / penumbraWidth, penumbraWidth);
|
|
float distance = abs(x);
|
|
float3 weights = RadianceScatter(distance);
|
|
|
|
totalWeights += weights;
|
|
totalScatter += light * weights;
|
|
|
|
x += increment;
|
|
}
|
|
|
|
return totalScatter / totalWeights;
|
|
}
|
|
|
|
float3 FilmicTonemap(float3 color)
|
|
{
|
|
return (color * (6.2 * color + 0.5)) / (color * (6.2 * color + 1.7) + 0.06);
|
|
}
|
|
|
|
[numthreads(8,8,1)]
|
|
void SkinLut (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)) + _PositionShift;
|
|
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);
|
|
//_SSSLut[id.xy] = theta;
|
|
}
|
|
|
|
[numthreads(8, 8, 1)]
|
|
void ShadowLut(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 penumbraLocation = uv.x + _PositionShift;
|
|
float penumbraWidth = rcp(max(uv.y, 0.001) * _ScatterRadius);
|
|
|
|
float3 scatter = IntegrateShadowScattering(penumbraLocation, penumbraWidth) * _Intensity;
|
|
if (_ApplyTonemap == 1)
|
|
{
|
|
scatter = FilmicTonemap(scatter);
|
|
}
|
|
|
|
_SSSLut[id.xy] = float4(scatter, 1.0);
|
|
} |