Streamingle_URP/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_LilToonShadowMode.hlsl

208 lines
9.0 KiB
HLSL

// SPDX-License-Identifier: (Not available for this version, you are only allowed to use this software if you have express permission from the copyright holder and agreed to the latest NiloToonURP EULA)
// Copyright (c) 2021 Kuroneko ShaderLab Limited
#pragma once
#if _SHADOW_MODE_LILTOON
struct NiloToonLilToonShadowModeResult
{
half3 lightColorIndependentLitColor;
half finalShadowAreaForNiloEffects;
};
float NiloToonLilToonTooningNoSaturateScale(float aaStrength, float value, float border, float blur)
{
float borderMin = saturate(border - blur * 0.5);
float borderMax = saturate(border + blur * 0.5);
return (value - borderMin) / saturate(borderMax - borderMin + fwidth(value) * aaStrength);
}
float NiloToonLilToonTooningNoSaturateScale(float aaStrength, float value, float border, float blur, float borderRange)
{
float borderMin = saturate(border - blur * 0.5 - borderRange);
float borderMax = saturate(border + blur * 0.5);
return (value - borderMin) / saturate(borderMax - borderMin + fwidth(value) * aaStrength);
}
float NiloToonLilToonTooningScale(float aaStrength, float value, float border, float blur)
{
return saturate(NiloToonLilToonTooningNoSaturateScale(aaStrength, value, border, blur));
}
float NiloToonLilToonTooningScale(float aaStrength, float value, float border, float blur, float borderRange)
{
return saturate(NiloToonLilToonTooningNoSaturateScale(aaStrength, value, border, blur, borderRange));
}
float3 NiloToonLilToonLinearToSRGB(float3 col)
{
float3 low = col * 12.92;
float3 high = 1.055 * pow(max(col, 0.0), 1.0 / 2.4) - 0.055;
return lerp(low, high, step(0.0031308, col));
}
void NiloToonLilToonCalcLUTUV(float3 col, float resX, float resY, out float4 uv, out float factor)
{
#if !UNITY_COLORSPACE_GAMMA
col = NiloToonLilToonLinearToSRGB(col);
#endif
float3 res = float3(resX, resY, resX * resY);
float3 resInv = float3(1.0, -1.0, 1.0) / res;
float3 col2 = (col - col * resInv.z) + 0.5 * resInv.z;
float4 b2 = saturate(col2.b + resInv.z * float2(-0.5, 0.5)).xxyy * res.zyzy;
float4 b3 = floor(b2);
uv = float4(0, 1, 0, 1) + (col2.rgrg + b3) * resInv.xyxy;
factor = abs(b2.x - b3.x);
}
// Match lilToon's shared sampler behavior for shadow masks.
#define NILO_LIL_SAMPLE_SHADOW_MASK_WITH_LOD(textureName, uv, lod) \
((lod) > 0 ? SAMPLE_TEXTURE2D_GRAD(textureName, sampler_linear_repeat, uv, max(abs(ddx(uv)), lod), max(abs(ddy(uv)), lod)) : SAMPLE_TEXTURE2D(textureName, sampler_linear_repeat, uv))
#define NILO_LIL_SAMPLE_SHADOW_COLOR_TEX(textureName, uv, lutUv, lutFactor) \
(_lilShadowColorType == 1 ? lerp(SAMPLE_TEXTURE2D_LOD(textureName, sampler_linear_clamp, (lutUv).xy, 0), SAMPLE_TEXTURE2D_LOD(textureName, sampler_linear_clamp, (lutUv).zw, 0), lutFactor) : SAMPLE_TEXTURE2D(textureName, sampler_BaseMap, uv))
half NiloToonLilToonRemapAO(half value, half minValue, half maxValue)
{
return invLerpClamp(minValue, maxValue, value);
}
NiloToonLilToonShadowModeResult CalculateNiloToonLilToonShadowMode(
ToonSurfaceData surfaceData,
ToonLightingData lightingData,
Light light,
half selfShadowMapShadow,
half depthDiffShadow,
half finalNiloShadowArea)
{
NiloToonLilToonShadowModeResult result;
if (!_EnableShadowColor)
{
result.lightColorIndependentLitColor = surfaceData.albedo;
result.finalShadowAreaForNiloEffects = finalNiloShadowArea;
return result;
}
const float2 uv = lightingData.uv;
const half3 rawAlbedo = surfaceData.albedo;
const half3 L = light.direction;
// lilToon also adds distance(fd.L, fd.origL) for _LightDirectionOverride; intentionally skipped here.
half receivedShadow = saturate(light.shadowAttenuation);
#if _NILOTOON_RECEIVE_SELF_SHADOW
receivedShadow *= selfShadowMapShadow;
#endif
receivedShadow *= depthDiffShadow;
receivedShadow = saturate(receivedShadow);
half3 N1 = lerp(lightingData.normalWS_NoNormalMap, lightingData.normalWS, _lilShadowNormalStrength);
half3 N2 = lerp(lightingData.normalWS_NoNormalMap, lightingData.normalWS, _lilShadow2ndNormalStrength);
half3 N3 = lerp(lightingData.normalWS_NoNormalMap, lightingData.normalWS, _lilShadow3rdNormalStrength);
half4 shadowStrengthMask = NILO_LIL_SAMPLE_SHADOW_MASK_WITH_LOD(_lilShadowStrengthMask, uv, _lilShadowStrengthMaskLOD);
half4 lns = 1.0;
lns.x = saturate(dot(L, N1) * 0.5 + 0.5);
lns.y = saturate(dot(L, N2) * 0.5 + 0.5);
lns.z = saturate(dot(L, N3) * 0.5 + 0.5);
lns.w = lns.x;
half aaStrength = _lilAAStrength;
if (_lilShadowMaskType == 2)
{
float3 faceR = mul((float3x3)UNITY_MATRIX_M, float3(-1.0, 0.0, 0.0));
float LdotR = dot(L.xz, faceR.xz);
half sdf = LdotR < 0 ? shadowStrengthMask.g : shadowStrengthMask.r;
float3 faceF = mul((float3x3)UNITY_MATRIX_M, float3(0.0, 0.0, 1.0));
faceF.y *= _lilShadowFlatBlur;
faceF = SafeNormalize(faceF);
float3 faceL = L;
faceL.y *= _lilShadowFlatBlur;
faceL = SafeNormalize(faceL);
half lnSDF = dot(faceL, faceF);
lns = lerp(saturate(lnSDF * 0.5 + sdf * 0.5 + 0.25), lns, shadowStrengthMask.b);
aaStrength = 0;
shadowStrengthMask.r = shadowStrengthMask.a;
}
lns.x *= lerp(1.0, receivedShadow, _lilShadowReceive);
lns.y *= lerp(1.0, receivedShadow, _lilShadow2ndReceive);
lns.z *= lerp(1.0, receivedShadow, _lilShadow3rdReceive);
half shadowBlur = _lilShadowBlur;
half shadow2ndBlur = _lilShadow2ndBlur;
half shadow3rdBlur = _lilShadow3rdBlur;
half4 shadowBlurMask = NILO_LIL_SAMPLE_SHADOW_MASK_WITH_LOD(_lilShadowBlurMask, uv, _lilShadowBlurMaskLOD);
shadowBlur *= shadowBlurMask.r;
shadow2ndBlur *= shadowBlurMask.g;
shadow3rdBlur *= shadowBlurMask.b;
half4 shadowBorderMask = NILO_LIL_SAMPLE_SHADOW_MASK_WITH_LOD(_lilShadowBorderMask, uv, _lilShadowBorderMaskLOD);
shadowBorderMask.r = NiloToonLilToonRemapAO(shadowBorderMask.r, _lilShadowAO1Min, _lilShadowAO1Max);
shadowBorderMask.g = NiloToonLilToonRemapAO(shadowBorderMask.g, _lilShadowAO2Min, _lilShadowAO2Max);
shadowBorderMask.b = NiloToonLilToonRemapAO(shadowBorderMask.b, _lilShadowAO3Min, _lilShadowAO3Max);
lns.xyz = _lilShadowPostAO ? lns.xyz : lns.xyz * shadowBorderMask.rgb;
lns.w = lns.x;
lns.x = NiloToonLilToonTooningNoSaturateScale(aaStrength, lns.x, _lilShadowBorder, shadowBlur);
lns.y = NiloToonLilToonTooningNoSaturateScale(aaStrength, lns.y, _lilShadow2ndBorder, shadow2ndBlur);
lns.w = NiloToonLilToonTooningNoSaturateScale(aaStrength, lns.w, _lilShadowBorder, shadowBlur, _lilShadowBorderRange);
lns.z = NiloToonLilToonTooningNoSaturateScale(aaStrength, lns.z, _lilShadow3rdBorder, shadow3rdBlur);
lns = _lilShadowPostAO ? lns * shadowBorderMask.rgbr : lns;
lns = saturate(lns);
half backfaceShadow = lightingData.facing < 0.0 ? 1.0 - _BackFaceForceShadow : 1.0;
lns.x *= backfaceShadow;
lns.y *= backfaceShadow;
lns.z *= backfaceShadow;
lns.w *= backfaceShadow;
half shadowStrength = _lilShadowStrength;
if (_lilShadowMaskType == 1)
{
half3 flatN = normalize(mul((float3x3)UNITY_MATRIX_M, float3(0.0, 0.25, 1.0)));
half lnFlat = saturate((dot(flatN, L) + _lilShadowFlatBorder) / _lilShadowFlatBlur);
lnFlat *= lerp(1.0, receivedShadow, _lilShadowReceive);
lns = lerp(lnFlat, lns, shadowStrengthMask.r);
}
else
{
shadowStrength *= shadowStrengthMask.r;
}
lns.x = lerp(1.0, lns.x, shadowStrength);
float4 shadowLutUv;
float shadowLutFactor;
NiloToonLilToonCalcLUTUV(rawAlbedo, 16, 1, shadowLutUv, shadowLutFactor);
half4 shadowColorTex = NILO_LIL_SAMPLE_SHADOW_COLOR_TEX(_lilShadowColorTex, uv, shadowLutUv, shadowLutFactor);
half4 shadow2ndColorTex = NILO_LIL_SAMPLE_SHADOW_COLOR_TEX(_lilShadow2ndColorTex, uv, shadowLutUv, shadowLutFactor);
half4 shadow3rdColorTex = NILO_LIL_SAMPLE_SHADOW_COLOR_TEX(_lilShadow3rdColorTex, uv, shadowLutUv, shadowLutFactor);
half3 indirectColor = lerp(rawAlbedo, shadowColorTex.rgb, shadowColorTex.a) * _lilShadowColor.rgb;
half3 shadow2ndColor = lerp(rawAlbedo, shadow2ndColorTex.rgb, shadow2ndColorTex.a) * _lilShadow2ndColor.rgb;
lns.y = _lilShadow2ndColor.a - lns.y * _lilShadow2ndColor.a;
indirectColor = lerp(indirectColor, shadow2ndColor, lns.y);
half3 shadow3rdColor = lerp(rawAlbedo, shadow3rdColorTex.rgb, shadow3rdColorTex.a) * _lilShadow3rdColor.rgb;
lns.z = _lilShadow3rdColor.a - lns.z * _lilShadow3rdColor.a;
indirectColor = lerp(indirectColor, shadow3rdColor, lns.z);
indirectColor = lerp(indirectColor, indirectColor * rawAlbedo, _lilShadowMainStrength);
indirectColor = lerp(indirectColor, rawAlbedo, saturate(Luminance(lightingData.SH) * _lilShadowEnvStrength));
indirectColor = min(indirectColor, rawAlbedo);
indirectColor = lerp(indirectColor, rawAlbedo, lns.w * _lilShadowBorderColor.rgb);
result.lightColorIndependentLitColor = lerp(indirectColor, rawAlbedo, lns.x);
result.finalShadowAreaForNiloEffects = saturate(lns.x);
return result;
}
#endif