Files
UnrealEngine/Engine/Shaders/Private/ClearCoatCommon.ush
2025-05-18 13:04:45 +08:00

74 lines
3.0 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
float3 GetClearCoatBottomNormal(FGBufferData GBuffer, float3 WorldNormal)
{
if (GBuffer.ShadingModelID == SHADINGMODELID_CLEAR_COAT && CLEAR_COAT_BOTTOM_NORMAL)
{
const float2 oct1 = ((float2(GBuffer.CustomData.a, GBuffer.CustomData.z) * 4) - (512.0 / 255.0)) + UnitVectorToOctahedron(WorldNormal);
WorldNormal = OctahedronToUnitVector(oct1);
}
return WorldNormal;
}
float GetClearCoatRoughness(FGBufferData GBuffer)
{
return GBuffer.ShadingModelID == SHADINGMODELID_CLEAR_COAT ? GBuffer.CustomData.y : GBuffer.Roughness;
}
void RemapClearCoatDiffuseAndSpecularColor(FGBufferData GBuffer, half NoV, inout half3 DiffuseColor, inout half3 SpecularColor)
{
if (GBuffer.ShadingModelID == SHADINGMODELID_CLEAR_COAT)
{
// Attenuate base color and recompute diffuse color
half RefractionScale = ((NoV * 0.5 + 0.5) * NoV - 1) * saturate(1.25 - 1.25 * GBuffer.Roughness) + 1;
half MetalSpec = 0.9;
half3 AbsorptionColor = GBuffer.BaseColor * (1 / MetalSpec);
half3 Absorption = AbsorptionColor * ((NoV - 1) * 0.85 * (1 - lerp(AbsorptionColor, Square(AbsorptionColor), -0.78)) + 1);
half F0 = 0.04;
half Fc = Pow5(1 - NoV);
half F = Fc + (1 - Fc) * F0;
half ClearCoat = GBuffer.CustomData.x;
half LayerAttenuation = lerp(1, (1 - F), ClearCoat);
half3 BaseColor = lerp(GBuffer.BaseColor * LayerAttenuation, MetalSpec * Absorption * RefractionScale, GBuffer.Metallic * ClearCoat);
//BaseColor += Dither / 255.f;
DiffuseColor = BaseColor - BaseColor * GBuffer.Metallic;
half Specular = lerp(GBuffer.Specular, RefractionScale, ClearCoat);
SpecularColor = ComputeF0(Specular, BaseColor, GBuffer.Metallic) * View.SpecularOverrideParameter.w + View.SpecularOverrideParameter.xyz;
}
}
void RemapClearCoatDiffuseAndSpecularColor(FGBufferData GBuffer, float2 ScreenPosition, inout half3 DiffuseColor, inout half3 SpecularColor)
{
if (GBuffer.ShadingModelID == SHADINGMODELID_CLEAR_COAT)
{
float3 TranslatedWorldPosition = mul(float4(GetScreenPositionForProjectionType(ScreenPosition, GBuffer.Depth), GBuffer.Depth, 1), View.ScreenToTranslatedWorld).xyz;
half3 V = -GetCameraVectorFromTranslatedWorldPosition(TranslatedWorldPosition);
half NoV = saturate(dot(GBuffer.WorldNormal, V));
RemapClearCoatDiffuseAndSpecularColor(GBuffer, NoV, DiffuseColor, SpecularColor);
}
}
float3 ClearCoatLayerCombine(FGBufferData GBuffer, float NoV, float3 TopLayerReflections, float3 BottomLayerReflections, float3 SpecularColor)
{
const float ClearCoat = GBuffer.CustomData.x;
const float ClearCoatRoughness = GBuffer.CustomData.y;
// TODO EnvBRDF should have a mask param
float2 AB = PreIntegratedGF.SampleLevel( PreIntegratedGFSampler, float2( NoV, GBuffer.Roughness ), 0 ).rg;
BottomLayerReflections *= SpecularColor * AB.x + AB.y * saturate( 50 * SpecularColor.g ) * (1 - ClearCoat);
// F_Schlick
float F = EnvBRDF( 0.04, ClearCoatRoughness, NoV ).x;
F *= ClearCoat;
return BottomLayerReflections * (1 - F) + TopLayerReflections * F;
}