151 lines
6.1 KiB
HLSL
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
|
|
} |