74 lines
3.0 KiB
HLSL
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;
|
|
} |