Added new Shadow SSS Lut;

Fixed the issue that SSGI and SSAO weight not works properly;
This commit is contained in:
2025-03-17 00:02:46 +09:00
parent b2136e1ff4
commit ee0b720b6d
7 changed files with 126 additions and 58 deletions

View File

@@ -1,9 +1,14 @@
#pragma kernel CSMain
#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;
@@ -51,12 +56,11 @@ float3 RadianceScatter(float r)
float3 IntegrateDiffuseScattering_Ring(float theta, float r)
{
float x = -HALF_PI;
float increment = PI / _SampleCount;
float3 totalScatter = 0;
float3 totalWeight = 0;
float increment = PI / _SampleCount;
float x = -HALF_PI;
while (x < HALF_PI)
{
float diffuse = saturate(cos(theta + x));
@@ -72,13 +76,42 @@ float3 IntegrateDiffuseScattering_Ring(float theta, float r)
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 CSMain (uint3 id : SV_DispatchThreadID)
void SkinLut (uint3 id : SV_DispatchThreadID)
{
if (id.x > _TextureSize || id.y > _TextureSize)
{
@@ -90,7 +123,7 @@ void CSMain (uint3 id : SV_DispatchThreadID)
uv.y = 1.0 - uv.y;
#endif
float theta = acos(uv.x * 2.0 - 1.0);
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;
@@ -99,5 +132,31 @@ void CSMain (uint3 id : SV_DispatchThreadID)
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);
}

View File

@@ -37,7 +37,9 @@ namespace Misaki.HdrpToon.Editor
private RenderTexture _previewTexture;
private RenderTextureDescriptor _previewDescriptor;
public bool isShadowLut;
public float scatterRadius = 1.0f;
public float positionShift = 0.0f;
public float intensity = 1.0f;
public Quality sampleCount = Quality.Low;
public bool applyTonemap = true;
@@ -78,7 +80,10 @@ namespace Misaki.HdrpToon.Editor
return false;
}
var kernelIndex = isShadowLut ? 1 : 0;
_bakerShader.SetFloat("_ScatterRadius", scatterRadius);
_bakerShader.SetFloat("_PositionShift", positionShift);
_bakerShader.SetFloat("_Intensity", intensity);
_bakerShader.SetInt("_SampleCount", (int)sampleCount);
_bakerShader.SetInt("_ApplyTonemap", applyTonemap ? 1 : 0);
@@ -86,13 +91,13 @@ namespace Misaki.HdrpToon.Editor
_bakerShader.SetKeyword(new LocalKeyword(_bakerShader, "_PRODUCTION"), production);
_bakerShader.SetTexture(0, "_SSSLut", texture);
_bakerShader.SetTexture(kernelIndex, "_SSSLut", texture);
const int groupSizeX = 8;
const int groupSizeY = 8;
var threadGroupX = (textureSize + (groupSizeX - 1)) / groupSizeX;
var threadGroupY = (textureSize + (groupSizeY - 1)) / groupSizeY;
_bakerShader.Dispatch(0, threadGroupX, threadGroupY, 1);
_bakerShader.Dispatch(kernelIndex, threadGroupX, threadGroupY, 1);
return true;
}

View File

@@ -2,11 +2,21 @@
<engine:VisualElement data-source-type="Misaki.HdrpToon.Editor.SSSLutBakerView, Misaki.HdrpToon.Editor" style="flex-grow: 1; padding-top: 8px; padding-right: 8px; padding-bottom: 8px; padding-left: 8px;">
<engine:Label text="SSS Lut Baker" style="font-size: 18px; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; margin-top: 12px; margin-bottom: 8px; margin-left: 4px; margin-right: 6px; -unity-font-style: bold;" />
<engine:Label text="Parameters:" style="-unity-font-style: bold; margin-top: 12px; margin-bottom: 4px; margin-right: 2px; margin-left: 2px;" />
<engine:DropdownField label="Lut Type" choices="Skin,Shadow" index="0">
<Bindings>
<engine:DataBinding property="index" data-source-path="isShadowLut" binding-mode="TwoWay" />
</Bindings>
</engine:DropdownField>
<engine:FloatField label="Scatter Radius" value="1">
<Bindings>
<engine:DataBinding property="value" data-source-path="scatterRadius" binding-mode="TwoWay" />
</Bindings>
</engine:FloatField>
<engine:Slider label="Position Shift" value="0.0" low-value="-1" high-value="1" page-size="0.1" show-input-field="true">
<Bindings>
<engine:DataBinding property="value" data-source-path="positionShift" binding-mode="TwoWay" />
</Bindings>
</engine:Slider>
<engine:Slider label="Intensity" value="1" high-value="10" show-input-field="true" page-size="0.1">
<Bindings>
<engine:DataBinding property="value" data-source-path="intensity" binding-mode="TwoWay" />