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

197 lines
7.9 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 _GENERIC_REFLECTION
half3 BlendGenericReflectionColor(half3 dstCol, half3 srcCol, half3 srcA, uint blendMode)
{
half3 add = dstCol + srcCol;
half3 mul = dstCol * srcCol;
half3 outCol = dstCol;
if (blendMode == 0) outCol = srcCol;
else if (blendMode == 1) outCol = add;
else if (blendMode == 2) outCol = max(add - mul, dstCol);
else if (blendMode == 3) outCol = mul;
return lerp(dstCol, outCol, srcA);
}
half GenericReflectionTooningScale(half value, half border, half blur)
{
half borderMin = saturate(border - blur * 0.5h);
half borderMax = saturate(border + blur * 0.5h);
return saturate((value - borderMin) / saturate(borderMax - borderMin + fwidth(value) * _lilAAStrength));
}
void GenericReflectionGSAAForSmoothness(inout half smoothness, half3 normalWS, half strength)
{
float3 dx = abs(ddx(normalWS));
float3 dy = abs(ddy(normalWS));
float dxy = max(dot(dx, dx), dot(dy, dy));
float roughnessGSAA = dxy / (dxy * 5.0 + 0.002) * strength;
smoothness = min(smoothness, saturate(1.0h - roughnessGSAA));
}
half3 GenericReflectionFresnelTerm(half3 f0, half cosA)
{
half a = 1.0h - cosA;
half a5 = a * a * a * a * a;
return f0 + (1.0h - f0) * a5;
}
half3 GenericReflectionFresnelLerp(half3 f0, half3 f90, half cosA)
{
half a = 1.0h - cosA;
half a5 = a * a * a * a * a;
return lerp(f0, f90, a5);
}
half3 DecodeGenericReflectionCubemap(half4 data)
{
half alpha = _GenericReflectionCubemap_HDR.w * (data.a - 1.0h) + 1.0h;
#if defined(UNITY_COLORSPACE_GAMMA)
return (_GenericReflectionCubemap_HDR.x * alpha) * data.rgb;
#elif defined(UNITY_USE_NATIVE_HDR)
return _GenericReflectionCubemap_HDR.x * data.rgb;
#else
return (_GenericReflectionCubemap_HDR.x * pow(abs(alpha), _GenericReflectionCubemap_HDR.y)) * data.rgb;
#endif
}
half3 SampleGenericReflectionCubemap(half3 reflectVector, half perceptualRoughness)
{
half mip = perceptualRoughness * (10.2h - 4.2h * perceptualRoughness);
half4 encodedIrradiance = half4(SAMPLE_TEXTURECUBE_LOD(
_GenericReflectionCubemap,
sampler_linear_repeat,
reflectVector,
mip));
return DecodeGenericReflectionCubemap(encodedIrradiance);
}
half3 SampleGenericReflectionEnvironment(half3 reflectVector, half perceptualRoughness, ToonSurfaceData surfaceData, ToonLightingData lightingData)
{
if (_GenericReflectionCubeOverride > 0.5h)
{
half3 cubemapColor = SampleGenericReflectionCubemap(reflectVector, perceptualRoughness);
cubemapColor *= _GenericReflectionCubeColor.rgb;
cubemapColor *= lerp(1.0h.xxx, saturate(lightingData.mainLight.color), _GenericReflectionCubeEnableLighting);
return cubemapColor;
}
#if UNITY_VERSION > 202220
return GlossyEnvironmentReflection(reflectVector, lightingData.positionWS, perceptualRoughness, surfaceData.occlusion, lightingData.normalizedScreenSpaceUV);
#else
return GlossyEnvironmentReflection(reflectVector, lightingData.positionWS, perceptualRoughness, surfaceData.occlusion);
#endif
}
half3 ApplyGenericReflectionSpecular(half3 normalWS, half smoothnessRoughness, half3 specular, ToonLightingData lightingData)
{
half3 viewDirWS = normalize(lightingData.viewDirectionWS);
half3 lightDirWS = normalize(lightingData.mainLight.direction);
half3 halfDirWS = normalize(viewDirWS + lightDirWS);
half NdotH = saturate(dot(normalWS, halfDirWS));
if (_GenericReflectionSpecularToon > 0.5h)
{
half specularArea = pow(NdotH, rcp(max(smoothnessRoughness, 0.002h)));
return GenericReflectionTooningScale(specularArea, _GenericReflectionSpecularBorder, _GenericReflectionSpecularBlur).xxx;
}
half NdotV = saturate(dot(normalWS, viewDirWS));
half NdotL = saturate(dot(normalWS, lightDirWS));
half LdotH = saturate(dot(lightDirWS, halfDirWS));
half roughness = max(smoothnessRoughness, 0.002h);
half lambdaV = NdotL * (NdotV * (1.0h - roughness) + roughness);
half lambdaL = NdotV * (NdotL * (1.0h - roughness) + roughness);
half roughness2 = roughness * roughness;
half d = (NdotH * roughness2 - NdotH) * NdotH + 1.0h;
half ggx = roughness2 / (d * d + 1e-7h);
#if defined(SHADER_API_MOBILE) || defined(SHADER_API_SWITCH)
half smithJointGGX = 0.5h / (lambdaV + lambdaL + 1e-4h);
#else
half smithJointGGX = 0.5h / (lambdaV + lambdaL + 1e-5h);
#endif
half specularTerm = smithJointGGX * ggx;
#if defined(UNITY_COLORSPACE_GAMMA)
specularTerm = sqrt(max(1e-4h, specularTerm));
#endif
specularTerm *= NdotL;
return specularTerm * GenericReflectionFresnelTerm(specular, LdotH);
}
#endif
void ApplyGenericReflection(inout half3 color, ToonSurfaceData surfaceData, Varyings varyings, ToonLightingData lightingData)
{
#if _GENERIC_REFLECTION && NiloToonForwardLitPass
half3 baseNormalWS = normalize(lightingData.normalWS);
half smoothness = saturate(_GenericReflectionSmoothness * SAMPLE_TEXTURE2D(
_GenericReflectionSmoothnessMap,
sampler_linear_repeat,
CalcUV(GetUV(varyings), _GenericReflectionSmoothnessMap_ST)).r);
GenericReflectionGSAAForSmoothness(smoothness, baseNormalWS, _GenericReflectionGSAAStrength);
half perceptualRoughness = PerceptualSmoothnessToPerceptualRoughness(smoothness);
half roughness = perceptualRoughness * perceptualRoughness;
half4 colorMask = SAMPLE_TEXTURE2D(
_GenericReflectionColorMaskMap,
sampler_linear_repeat,
CalcUV(GetUV(varyings), _GenericReflectionColorMaskMap_ST));
half4 reflectionColor = _GenericReflectionColor * colorMask;
half reflectionAlpha = _GenericReflectionBlend * reflectionColor.a;
if (_GenericReflectionApplyTransparency > 0.5h)
{
reflectionAlpha *= surfaceData.alpha;
}
half metallicMask = SAMPLE_TEXTURE2D(
_GenericReflectionMetallicMap,
sampler_linear_repeat,
CalcUV(GetUV(varyings), _GenericReflectionMetallicMap_ST)).r;
half metallic = saturate(_GenericReflectionMetallic * metallicMask);
color -= metallic * color;
half3 specular = lerp(_GenericReflectionReflectance.xxx, surfaceData.albedo, metallic);
if (_GenericReflectionApplySpecular > 0.5h)
{
half3 specularNormalWS = normalize(lerp(lightingData.normalWS_NoNormalMap, lightingData.normalWS, _GenericReflectionSpecularNormalStrength));
half3 specularReflection = ApplyGenericReflectionSpecular(specularNormalWS, roughness, specular, lightingData);
color = BlendGenericReflectionColor(
color,
reflectionColor.rgb * saturate(lightingData.mainLight.color),
specularReflection * reflectionAlpha,
_GenericReflectionBlendMode);
}
if (_GenericReflectionApplyReflection <= 0.5h)
{
return;
}
half3 normalWS = normalize(lerp(lightingData.normalWS_NoNormalMap, lightingData.normalWS, _GenericReflectionNormalStrength));
half3 reflectionVectorWS = reflect(-lightingData.viewDirectionWS, normalWS);
half3 envReflectionColor = SampleGenericReflectionEnvironment(reflectionVectorWS, perceptualRoughness, surfaceData, lightingData);
half oneMinusReflectivity = 0.96h * (1.0h - metallic);
half grazingTerm = saturate(smoothness + (1.0h - oneMinusReflectivity));
half surfaceReduction = 1.0h / (roughness * roughness + 1.0h);
half normalNdotV = saturate(dot(normalWS, lightingData.viewDirectionWS));
half3 reflectCol = surfaceReduction * envReflectionColor * GenericReflectionFresnelLerp(specular, grazingTerm.xxx, normalNdotV);
color = BlendGenericReflectionColor(
color,
reflectionColor.rgb,
reflectCol * reflectionAlpha,
_GenericReflectionBlendMode);
#endif
}