Files
2025-01-07 18:54:46 +02:00

151 lines
6.1 KiB
HLSL

float _Distortion;
float _Scale;
float _Power;
float _Fresnel;
float _FresnelDamp;
float4 TranslucentBRDF(float3 diffColor, float3 specColor, float oneMinusReflectivity, float smoothness, float3 normal, float3x3 worldVectors,
float anisotropy, float metallic, float3 viewDir, UnityLight light, UnityIndirect gi)
{
//Unpack world vectors
float3 tangent = worldVectors[0];
float3 bitangent = worldVectors[1];
//Normal shift
float shiftAmount = dot(normal, viewDir);
normal = shiftAmount < 0.0f ? normal + viewDir * (-shiftAmount + 1e-5f) : normal;
//Regular vectors
float NdotL = saturate(dot(normal, light.dir));
float NdotV = abs(dot(normal, viewDir));
float LdotV = dot(light.dir, viewDir);
float3 H = Unity_SafeNormalize(light.dir + viewDir);
float invLenLV = rsqrt(abs(2 + 2 * normalize(LdotV)));
float NdotH = saturate(dot(normal, H));
float LdotH = saturate(dot(light.dir, H));
//Tangent vectors
float TdotH = dot(tangent, H);
float TdotL = dot(tangent, light.dir);
float BdotH = dot(bitangent, H);
float BdotL = dot(bitangent, light.dir);
float TdotV = dot(viewDir, tangent);
float BdotV = dot(viewDir, bitangent);
//Fresnels
half grazingTerm = saturate(smoothness + (1 - oneMinusReflectivity));
float3 F = FresnelLerp(specColor, grazingTerm, NdotV); //Original Schlick - Replace from SRP?
//float3 fresnel0 = lerp(specColor, diffColor, metallic);
//float3 F = FresnelSchlick(fresnel0, 1.0, LdotH);
//Calculate roughness
float roughnessT;
float roughnessB;
float perceptualRoughness = SmoothnessToPerceptualRoughness(smoothness);
float roughness = PerceptualRoughnessToRoughness(perceptualRoughness);
ConvertAnisotropyToRoughness(roughness, anisotropy, roughnessT, roughnessB);
//Clamp roughness
roughnessT = ClampRoughnessForAnalyticalLights(roughnessT);
roughnessB = ClampRoughnessForAnalyticalLights(roughnessB);
//Visibility & Distribution terms
float V = SmithJointGGXAnisotropic(TdotV, BdotV, NdotV, TdotL, BdotL, NdotL, roughnessT, roughnessB);
float D = D_GGXAnisotropic(TdotH, BdotH, NdotH, roughnessT, roughnessB);
//Specular term
float3 specularTerm = V * D;
# ifdef UNITY_COLORSPACE_GAMMA
specularTerm = sqrt(max(1e-4h, specularTerm));
# endif
// specularTerm * nl can be NaN on Metal in some cases, use max() to make sure it's a sane value
specularTerm = max(0, specularTerm * NdotL);
#if defined(_SPECULARHIGHLIGHTS_OFF)
specularTerm = 0.0;
#endif
//Diffuse term
float diffuseTerm = DisneyDiffuse(NdotV, NdotL, LdotH, perceptualRoughness) * NdotL;// - Need this NdotL multiply?
//Reduction
half surfaceReduction;
# ifdef UNITY_COLORSPACE_GAMMA
surfaceReduction = 1.0 - 0.28*roughness*perceptualRoughness; // 1-0.28*x^3 as approximation for (1/(x^4+1))^(1/2.2) on the domain [0;1]
# else
surfaceReduction = 1.0 / (roughness*roughness + 1.0); // fade \in [0.5;1]
# endif
//Final
half3 color = (diffColor * (gi.diffuse + light.color * diffuseTerm))
+ specularTerm * light.color * (FresnelTerm(specColor, LdotH))
+ (surfaceReduction * gi.specular * FresnelLerp(specColor, grazingTerm, NdotV) * _Fresnel * lerp(float3(1,1,1),specColor,_FresnelDamp));
return half4(color, 1);
}
inline half4 LightFunctionStandardAnisotropic(SurfaceOutputStandardAnisotropic s, half3 viewDir, UnityGI gi)
{
s.Normal = normalize(s.Normal);
half oneMinusReflectivity;
half3 specColor;
s.Albedo = DiffuseAndSpecularFromMetallic(s.Albedo, s.Metallic, /*out*/ specColor, /*out*/ oneMinusReflectivity);
// shader relies on pre-multiply alpha-blend (_SrcBlend = One, _DstBlend = OneMinusSrcAlpha)
// this is necessary to handle transparency in physically correct way - only diffuse component gets affected by alpha
half outputAlpha;
s.Albedo = PreMultiplyAlpha(s.Albedo, s.Alpha, oneMinusReflectivity, /*out*/ outputAlpha);
half4 c = TranslucentBRDF(s.Albedo, specColor, oneMinusReflectivity, s.Smoothness, s.Normal, s.WorldVectors, s.Anisotropy, s.Metallic, viewDir, gi.light, gi.indirect);
c.a = outputAlpha;
return c;
}
inline fixed4 LightingStandardTranslucent(SurfaceOutputStandardAnisotropic s, fixed3 viewDir, UnityGI gi)
{
// Original colour
fixed4 pbr = LightFunctionStandardAnisotropic(s, viewDir, gi);
// --- Translucency ---
float3 L = gi.light.dir;
float3 V = viewDir;
float3 N = s.Normal;
float3 H = normalize(L + N * _Distortion);
float I = (pow(saturate(dot(V, -H)), _Power) * _Scale);
// Final add
pbr.rgb = pbr.rgb + gi.light.color * (I*s.Albedo);
return pbr;
}
//This is pointless as always forward?
inline half4 LightingStandardTranslucent_Deferred(SurfaceOutputStandardAnisotropic s, half3 viewDir, UnityGI gi, out half4 outGBuffer0, out half4 outGBuffer1, out half4 outGBuffer2)
{
half oneMinusReflectivity;
half3 specColor;
s.Albedo = DiffuseAndSpecularFromMetallic(s.Albedo, s.Metallic, /*out*/ specColor, /*out*/ oneMinusReflectivity);
half4 c = TranslucentBRDF(s.Albedo, specColor, oneMinusReflectivity, s.Smoothness, s.Normal, s.WorldVectors, s.Anisotropy, s.Metallic, viewDir, gi.light, gi.indirect);
UnityStandardData data;
data.diffuseColor = s.Albedo;
data.occlusion = s.Occlusion;
data.specularColor = specColor;
data.smoothness = s.Smoothness;
data.normalWorld = s.Normal;
UnityStandardDataToGbuffer(data, outGBuffer0, outGBuffer1, outGBuffer2);
// --- Translucency ---
float3 L = gi.light.dir;
float3 V = viewDir;
float3 N = s.Normal;
float3 H = normalize(L + N * _Distortion);
float I = (pow(saturate(dot(V, -H)), _Power) * _Scale);
half4 emission = half4(s.Emission + c.rgb, 1);
return emission * (float4(1,1,1,1) + float4(I * c.rgb,0));
}
inline void LightingStandardTranslucent_GI(SurfaceOutputStandardAnisotropic s, UnityGIInput data, inout UnityGI gi)
{
#if defined(UNITY_PASS_DEFERRED) && UNITY_ENABLE_REFLECTION_BUFFERS
gi = UnityGlobalIllumination(data, s.Occlusion, s.Normal);
#else
Unity_GlossyEnvironmentData g = UnityGlossyEnvironmentSetup(s.Smoothness, data.worldViewDir, s.Normal, lerp(unity_ColorSpaceDielectricSpec.rgb, s.Albedo, s.Metallic));
gi = UnityAnisotropicGlobalIllumination(data, s.Occlusion, s.Normal, g, s.Anisotropy, s.WorldVectors);
#endif
}