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

515 lines
21 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
/*=============================================================================
DBufferDecalShared.ush: Common definitions for DBuffer decals
=============================================================================*/
#pragma once
#ifndef DBUFFER_BASEPASS_RESOURCE
#define DBUFFER_BASEPASS_RESOURCE 1
#endif
#if DBUFFER_BASEPASS_RESOURCE
#if SHADING_PATH_MOBILE
#define DBufferBasePass MobileBasePass
#else
#define DBufferBasePass OpaqueBasePass
#endif
#define OpaqueBasePassDBufferATexture DBufferBasePass.DBufferATexture
#define OpaqueBasePassDBufferBTexture DBufferBasePass.DBufferBTexture
#define OpaqueBasePassDBufferCTexture DBufferBasePass.DBufferCTexture
#define OpaqueBasePassDBufferRenderMask DBufferBasePass.DBufferRenderMask
#if MOBILE_MULTI_VIEW && SHADING_PATH_MOBILE
#define OpaqueBasePassDBufferATextureArray DBufferBasePass.DBufferATextureArray
#define OpaqueBasePassDBufferBTextureArray DBufferBasePass.DBufferBTextureArray
#define OpaqueBasePassDBufferCTextureArray DBufferBasePass.DBufferCTextureArray
#endif
#if SUPPORTS_INDEPENDENT_SAMPLERS
#define OpaqueBasePassDBufferATextureSampler DBufferBasePass.DBufferATextureSampler
#define OpaqueBasePassDBufferBTextureSampler DBufferBasePass.DBufferATextureSampler
#define OpaqueBasePassDBufferCTextureSampler DBufferBasePass.DBufferATextureSampler
#else
#define OpaqueBasePassDBufferATextureSampler DBufferBasePass.DBufferATextureSampler
#define OpaqueBasePassDBufferBTextureSampler DBufferBasePass.DBufferBTextureSampler
#define OpaqueBasePassDBufferCTextureSampler DBufferBasePass.DBufferCTextureSampler
#endif
#endif // DBUFFER_BASEPASS_RESOURCE
#if USE_DBUFFER && RAYHITGROUPSHADER
// This must be set prior to running the generated material code.
static float4 CurrentPayloadDBufferA = float4(0.0, 0.0, 0.0, 1.0);
static float4 CurrentPayloadDBufferB = float4(0.0, 0.0, 0.0, 1.0);
static float4 CurrentPayloadDBufferC = float4(0.0, 0.0, 0.0, 1.0);
#endif
// Returns a bitmask of DBuffer targets that contain valid data for this pixel.
// @param BufferUV - UV space in the DBuffer textures
uint GetDBufferTargetMask(uint2 PixelPos)
{
#if USE_DBUFFER && ENABLE_DBUFFER_TEXTURES && !RAYHITGROUPSHADER && !LUMEN_CARD_CAPTURE
{
# if PLATFORM_SUPPORTS_RENDERTARGET_WRITE_MASK
return DecodeRTWriteMask(PixelPos, OpaqueBasePassDBufferRenderMask, 3);
# elif PLATFORM_SUPPORTS_PER_PIXEL_DBUFFER_MASK
uint Mask = OpaqueBasePassDBufferRenderMask.Load(uint3(PixelPos, 0));
return Mask > 0 ? 0x07 : 0x00;
# else
return 0x07;
# endif
}
#elif USE_DBUFFER && RAYHITGROUPSHADER
return 0x07;
#else
return 0;
#endif
}
// all values that are output by the forward rendering pass
#if SUBSTRATE_ENABLED
void ConvertFromMetalness(
in float3 BaseColor,
in float Specular,
in float Metallic,
inout float3 DiffuseAlbedo,
inout float3 F0)
{
DiffuseAlbedo = lerp(BaseColor, 0, Metallic);
F0 = lerp(DielectricSpecularToF0(Specular), BaseColor, Metallic);
}
void ConvertToMetalness(
in float3 DiffuseAlbedo,
in float3 F0,
inout float3 BaseColor,
inout float Specular,
inout float Metallic)
{
Metallic = F0RGBToMetallic(F0);
Specular = F0RGBToDielectricSpecular(F0);
BaseColor = lerp(DiffuseAlbedo, F0, Metallic);
}
// @param BufferUV - UV space in the DBuffer textures
FSubstrateDBuffer SubstrateGetDBufferData(float2 BufferUV, uint RTMaskBit, uint EyeIndex)
{
// SUBSTRATE_TODO: Add support MOBILE_MULTI_VIEW and INSTANCED_STEREO on mobile (using EyeIndex)
// Setup default values, which mean that no decals are present in DBuffer
float4 DBufferA = float4(0.0, 0.0, 0.0, 1.0);
float4 DBufferB = float4(128.0f / 255.0f, 128.f / 255.5f, 128.f / 255.5f, 1.0);
float4 DBufferC = float4(0.0, 0.0, 0.0, 1.0);
#if USE_DBUFFER && ENABLE_DBUFFER_TEXTURES && !RAYHITGROUPSHADER && !LUMEN_CARD_CAPTURE
BRANCH
if (RTMaskBit & 0x1) { DBufferA = Texture2DSampleLevel(OpaqueBasePassDBufferATexture, OpaqueBasePassDBufferATextureSampler, BufferUV, 0); }
BRANCH
if (RTMaskBit & 0x2) { DBufferB = Texture2DSampleLevel(OpaqueBasePassDBufferBTexture, OpaqueBasePassDBufferBTextureSampler, BufferUV, 0); }
BRANCH
if (RTMaskBit & 0x4) { DBufferC = Texture2DSampleLevel(OpaqueBasePassDBufferCTexture, OpaqueBasePassDBufferCTextureSampler, BufferUV, 0); }
#elif USE_DBUFFER && RAYHITGROUPSHADER
BRANCH
if (RTMaskBit & 0x1) { DBufferA = CurrentPayloadDBufferA; }
BRANCH // SubstrateUnpackDBuffer expects DBufferB to have a specific scale and bias
if (RTMaskBit & 0x2) { DBufferB = float4(CurrentPayloadDBufferB.rgb * 0.5f + 128.0f / 255.0f, CurrentPayloadDBufferB.a); }
BRANCH
if (RTMaskBit & 0x4) { DBufferC = CurrentPayloadDBufferC; }
#endif
return SubstrateUnpackDBuffer(DBufferA, DBufferB, DBufferC);
}
FSubstrateDBuffer SubstrateGetDBufferData(float2 BufferUV, uint RTMaskBit)
{
return SubstrateGetDBufferData(BufferUV, RTMaskBit, 0 /*EyeIndex*/);
}
// Define how DBuffer is applied onto existing layers:
// * 0: Apply DBuffer as per-component parameter blending (legacy mode). Default.
// * 1: Apply DBuffer as a coating layer (using parameter blending for efficiency purpose). Not used for now
#define SUBSTRATE_DBUFFER_LEGACY 0
#define SUBSTRATE_DBUFFER_COATING 1
#define SUBSTRATE_DBUFFER_BLENDING_MODE SUBSTRATE_DBUFFER_LEGACY
// Define which DBuffers are valid to read from, for this material
#define SUBSTRATE_DBUFFER_RESPONSE_BASECOLOR_BIT_OFFSET 0
#define SUBSTRATE_DBUFFER_RESPONSE_NORMAL_BIT_OFFSET 1
#define SUBSTRATE_DBUFFER_RESPONSE_ROUGHNESS_BIT_OFFSET 2
#define SUBSTRATE_DBUFFER_RESPONSE_BASECOLOR (MATERIALDECALRESPONSEMASK & (1<<SUBSTRATE_DBUFFER_RESPONSE_BASECOLOR_BIT_OFFSET))
#define SUBSTRATE_DBUFFER_RESPONSE_NORMAL (MATERIALDECALRESPONSEMASK & (1<<SUBSTRATE_DBUFFER_RESPONSE_NORMAL_BIT_OFFSET))
#define SUBSTRATE_DBUFFER_RESPONSE_ROUGHNESS (MATERIALDECALRESPONSEMASK & (1<<SUBSTRATE_DBUFFER_RESPONSE_ROUGHNESS_BIT_OFFSET))
#if MATERIAL_IS_SUBSTRATE
void ApplyDBufferData(in FSubstrateDBuffer SubstrateDBufferData, inout FSubstratePixelHeader SubstratePixelHeader, inout FSubstrateData SubstrateData)
{
// We cannot early out due when coverage = 0 due to the possibility of using premultipled alpha.
// For normal, apply decal data onto all basis, without consideration of top layers
#if SUBSTRATE_DBUFFER_RESPONSE_NORMAL && SUBSTRATE_INLINE_SHADING
if(any(SubstrateDBufferData.WorldNormal != 0.0) || SubstrateDBufferData.OneMinusCoverage_WorldNormal < 1.0)
{
UNROLL
for (uint i = 0; i < SubstratePixelHeader.SharedLocalBases.Count; ++i)
{
// Note:
// * Assume Normal is already been normalized
// * After modification we normalize the normal to get smoother visual result (it helps to avoid having D_GGX explodes toward infinity)
//
// SUBSTRATE_TODO:
// * If the normal is shared by different layers on which decals would be applied differently (e.g., one affected, not the other), we
// would need to add a new normal entry and modify it.
// * If the basis has a tangent, the average operation should be changed into a basis sler/rotation
SubstratePixelHeader.SharedLocalBases.Normals[i] = normalize(SubstratePixelHeader.SharedLocalBases.Normals[i] * SubstrateDBufferData.OneMinusCoverage_WorldNormal + SubstrateDBufferData.WorldNormal);
//if (SubstrateGetSharedLocalBasisType(SubstratePixelHeader.SharedLocalBases.Types, i) == SUBSTRATE_BASIS_TYPE_TANGENT)
//{
// SubstratePixelHeader.SharedLocalBases.Tangents[i] = normalize(SubstratePixelHeader.SharedLocalBases.Tangents[i]);
//}
}
}
#endif
const bool bAffectDiffuse = any(SubstrateDBufferData.BaseColor > 0) || SubstrateDBufferData.OneMinusCoverage_BaseColor < 1.0;
const bool bAffectF0Rough = any(SubstrateDBufferData.Metallic > 0) || any(SubstrateDBufferData.Specular > 0) || any(SubstrateDBufferData.Roughness > 0) || SubstrateDBufferData.OneMinusCoverage_Roughness < 1.0;
if (!bAffectDiffuse && !bAffectF0Rough)
{
return;
}
// For now apply decal data onto all layers, without consideration of top layers
SUBSTRATE_UNROLL_N(SUBSTRATE_CLAMPED_CLOSURE_COUNT)
for (int BSDFIdx = 0; BSDFIdx < SubstratePixelHeader.SubstrateTree.BSDFCount; ++BSDFIdx)
{
#define BSDF SubstratePixelHeader.SubstrateTree.BSDFs[BSDFIdx]
switch (BSDF_GETTYPE(BSDF))
{
case SUBSTRATE_BSDF_TYPE_SLAB:
{
// Note:
// * For Slab, since the DBuffer is stored with a Metalness parameterization for storage-space reason,
// we were convert back&forth the Slab data between DiffuseAlbedo/F0 and Metalness.
// * However, this is a non identy operation even when non decal so material look could be changed.
// Furthermore this resulted in some transition edges being visible where the decal was being applied
//=> We now do computation in Diffuse/F0 space. It is still not perfectly matching legacy
// but at least the null operation is identity and no more transition edges are visible.
// Apply DBuffer as per-component parameter blending (legacy mode)
#if SUBSTRATE_DBUFFER_BLENDING_MODE == SUBSTRATE_DBUFFER_LEGACY
{
// The original metallic, before the decal touched the slab.
// We use MIN on F0 to nor remove too much energy when metallic is lowered and have smoother metallic gradient with low F0.
float SlabMetallic = F0ToMetallic(min(SLAB_F0(BSDF).r, min(SLAB_F0(BSDF).g, SLAB_F0(BSDF).b)));
#if SUBSTRATE_DBUFFER_RESPONSE_BASECOLOR || SUBSTRATE_DBUFFER_RESPONSE_ROUGHNESS
float3 DecalDiffuse;
float3 DecalF0;
ConvertFromMetalness(SubstrateDBufferData.BaseColor, SubstrateDBufferData.Specular, SubstrateDBufferData.Metallic, DecalDiffuse, DecalF0);
if (bAffectDiffuse || bAffectF0Rough)
{
// Affect F0 if basecolor or metallic are changed.
SLAB_F0(BSDF) = SLAB_F0(BSDF) * SubstrateDBufferData.OneMinusCoverage_BaseColor + DecalF0;
}
#endif
#if SUBSTRATE_DBUFFER_RESPONSE_BASECOLOR
if (bAffectDiffuse)
{
// Diffuse albedo is affected by throughpu and decal diffuse contribution
SLAB_DIFFUSEALBEDO(BSDF) = SLAB_DIFFUSEALBEDO(BSDF) * SubstrateDBufferData.OneMinusCoverage_BaseColor + DecalDiffuse;
// Fade out fuzz to avoid overbright decal.
SLAB_FUZZ_AMOUNT(BSDF) *= SubstrateDBufferData.OneMinusCoverage_BaseColor;
// Disable SSS when the coverage reach one to preserve the decal color.
// That operation also progressively makes non top layer disapear.
// Since this is ran before the Substrate tree is processed, we must use TmpMFP and not SLAB_SSSMFP.
BSDF.TmpMFP = BSDF.TmpMFP * SubstrateDBufferData.OneMinusCoverage_BaseColor;
if (SubstrateDBufferData.OneMinusCoverage_BaseColor == 0.0f)
{
BSDF_SETSSSTYPE(BSDF, SSS_TYPE_NONE);
}
}
#endif
#if SUBSTRATE_DBUFFER_RESPONSE_ROUGHNESS
if (bAffectF0Rough)
{
// Now also operate a change to reflect the change of metallic
float NewMetallic = SlabMetallic * SubstrateDBufferData.OneMinusCoverage_Roughness + SubstrateDBufferData.Metallic;
if (NewMetallic >= SlabMetallic)
{
float TransferDelta = (NewMetallic - SlabMetallic); // Positive or zero
SLAB_F0(BSDF) += TransferDelta * SLAB_DIFFUSEALBEDO(BSDF);
SLAB_DIFFUSEALBEDO(BSDF)-= TransferDelta * SLAB_DIFFUSEALBEDO(BSDF);
}
else
{
float TransferDelta =-(NewMetallic - SlabMetallic); // Positive
float CurrentSpecular = F0ToDielectricSpecular(min(SLAB_F0(BSDF).r, min(SLAB_F0(BSDF).g, SLAB_F0(BSDF).b)));
float F0ThatCannotTransfer = DielectricSpecularToF0(CurrentSpecular);
float3 F0ThatCanTransfer = saturate(SLAB_F0(BSDF) - F0ThatCannotTransfer);
SLAB_DIFFUSEALBEDO(BSDF)+= TransferDelta * F0ThatCanTransfer;
SLAB_F0(BSDF) -= TransferDelta * F0ThatCanTransfer;
}
SLAB_ROUGHNESS(BSDF) = SLAB_ROUGHNESS(BSDF) * SubstrateDBufferData.OneMinusCoverage_Roughness + SubstrateDBufferData.Roughness;
// Also fade out other specular features since we consider decal to have not specular features.
if (BSDF_GETHASHAZINESS(BSDF))
{
FHaziness Haziness = UnpackHaziness(SLAB_HAZINESS(BSDF));
Haziness.Weight *= SubstrateDBufferData.OneMinusCoverage_Roughness;
SLAB_HAZINESS(BSDF) = PackHaziness(Haziness);
}
SLAB_ANISOTROPY(BSDF) *= SubstrateDBufferData.OneMinusCoverage_Roughness;
}
#endif
}
// Apply DBuffer as a coating layer (using parameter blending for efficiency purpose)
#elif SUBSTRATE_DBUFFER_BLENDING_MODE == SUBSTRATE_DBUFFER_COATING
{
// Since all DBuffer parameters are not necessary initialized, take default value from the existing BDSF
FSubstrateDBuffer LocalSubstrateDBufferData = SubstrateDBufferData;
{
float3 SlabBaseColor = 0;
float SlabMetallic = 0;
float SlabSpecular = 0;
ConvertToMetalness(SLAB_DIFFUSEALBEDO(BSDF), SLAB_F0(BSDF), SlabBaseColor, SlabSpecular, SlabMetallic);
#if !SUBSTRATE_DBUFFER_RESPONSE_BASECOLOR
LocalSubstrateDBufferData.BaseColor = LocalSubstrateDBufferData.Coverage * SlabBaseColor;
LocalSubstrateDBufferData.OneMinusCoverage_BaseColor = LocalSubstrateDBufferData.OneMinusCoverage;
#endif
#if !SUBSTRATE_DBUFFER_RESPONSE_ROUGHNESS
LocalSubstrateDBufferData.Metallic = LocalSubstrateDBufferData.Coverage * SlabMetallic;
LocalSubstrateDBufferData.Specular = LocalSubstrateDBufferData.Coverage * SlabSpecular;
LocalSubstrateDBufferData.Roughness = LocalSubstrateDBufferData.Coverage * SLAB_ROUGHNESS(BSDF);
LocalSubstrateDBufferData.OneMinusCoverage_Roughness = LocalSubstrateDBufferData.OneMinusCoverage;
#endif
}
FSubstratePixelHeader SubstrateDecalHeader;
FSubstrateData SubstrateDecalData;
SubstrateDecalHeader.SubstrateConvertFromDBuffer(LocalSubstrateDBufferData, SubstrateDecalData);
// Parameters blend attributes
// SUBSTRATE_TODO BasisIndex is not defined... This is an experimental mode that will need revisiting when the time is right.
FSubstrateData SubstrateDataForBSDF;
SubstrateDataForBSDF.InlinedBSDF = BSDF;
const float DummyNoV = 1.0f;
BSDF = SubstrateVerticalLayeringParameterBlendingForDecal(SubstrateDecalData.Layers[l].BSDFs[i], SubstrateDataForBSDF, BasisIndex, DummyNoV, DummyNoV).InlinedBSDF;
}
#endif // SUBSTRATE_DBUFFER_BLENDING_MODE
break;
}
case SUBSTRATE_BSDF_TYPE_HAIR:
{
#if SUBSTRATE_DBUFFER_RESPONSE_BASECOLOR
HAIR_BASECOLOR(BSDF) = HAIR_BASECOLOR(BSDF) * SubstrateDBufferData.OneMinusCoverage_BaseColor + SubstrateDBufferData.BaseColor;
#endif
#if SUBSTRATE_DBUFFER_RESPONSE_ROUGHNESS
HAIR_ROUGHNESS(BSDF) = HAIR_ROUGHNESS(BSDF) * SubstrateDBufferData.OneMinusCoverage_Roughness + SubstrateDBufferData.Roughness;
HAIR_SPECULAR(BSDF) = HAIR_SPECULAR(BSDF) * SubstrateDBufferData.OneMinusCoverage_Roughness + SubstrateDBufferData.Specular;
#endif
break;
}
case SUBSTRATE_BSDF_TYPE_EYE:
{
#if SUBSTRATE_DBUFFER_RESPONSE_BASECOLOR
EYE_DIFFUSEALBEDO(BSDF) = EYE_DIFFUSEALBEDO(BSDF) * SubstrateDBufferData.OneMinusCoverage_BaseColor + SubstrateDBufferData.BaseColor;
#endif
#if SUBSTRATE_DBUFFER_RESPONSE_ROUGHNESS
EYE_ROUGHNESS(BSDF) = EYE_ROUGHNESS(BSDF) * SubstrateDBufferData.OneMinusCoverage_Roughness + SubstrateDBufferData.Roughness;
#endif
break;
}
case SUBSTRATE_BSDF_TYPE_SINGLELAYERWATER:
{
#if SUBSTRATE_DBUFFER_RESPONSE_BASECOLOR
SLW_BASECOLOR(BSDF) = SLW_BASECOLOR(BSDF) * SubstrateDBufferData.OneMinusCoverage_BaseColor + SubstrateDBufferData.BaseColor;
#endif
#if SUBSTRATE_DBUFFER_RESPONSE_ROUGHNESS
SLW_ROUGHNESS(BSDF) = SLW_ROUGHNESS(BSDF) * SubstrateDBufferData.OneMinusCoverage_Roughness + SubstrateDBufferData.Roughness;
SLW_SPECULAR(BSDF) = SLW_SPECULAR(BSDF) * SubstrateDBufferData.OneMinusCoverage_Roughness + SubstrateDBufferData.Specular;
SLW_METALLIC(BSDF) = SLW_METALLIC(BSDF) * SubstrateDBufferData.OneMinusCoverage_Roughness + SubstrateDBufferData.Metallic;
#endif
break;
}
} // switch
#undef BSDF
}
}
#endif // MATERIAL_IS_SUBSTRATE
#endif // SUBSTRATE_ENABLED
struct FDBufferData
{
// 0..1, premultiplied with ColorOpacity
float3 PreMulColor;
// 0:opaque ..1:see through
float ColorOpacity;
// -1..1, premultiplied with NormalOpacity
float3 PreMulWorldNormal;
// 0:opaque ..1:see through
float NormalOpacity;
// 0..1, premultiplied with RoughnessOpacity
float PreMulRoughness;
// 0..1, premultiplied with RoughnessOpacity
float PreMulMetallic;
// 0..1, premultiplied with RoughnessOpacity
float PreMulSpecular;
// 0:opaque ..1:see through
float RoughnessOpacity;
};
/** Populates DBufferA, DBufferB, DBufferC as float4 and puts opacity in alpha for frame buffer blending */
// @param MultiOpacity .x: Color, .y:Normal, .z:Roughness/Metallic/Specular
void EncodeDBufferData(FGBufferData GBufferData, float3 MultiOpacity,
out float4 DBufferA,
out float4 DBufferB,
out float4 DBufferC)
{
// UNORM 4 channel
DBufferA = float4(GBufferData.BaseColor, MultiOpacity.x);
// UNORM 4 channel, 128/255 represents 0
DBufferB = float4(GBufferData.WorldNormal * 0.5f + 128.0f/255.0f, MultiOpacity.y);
// UNORM 4 channel
DBufferC = float4(GBufferData.Metallic, GBufferData.Specular, GBufferData.Roughness, MultiOpacity.z);
}
/** Populates FDBufferData */
FDBufferData DecodeDBufferData(
float4 DBufferA,
float4 DBufferB,
float4 DBufferC)
{
FDBufferData ret;
// UNORM 4 channel
ret.PreMulColor = DBufferA.rgb;
ret.ColorOpacity = DBufferA.a;
// UNORM 4 channel, 128/255 represents 0
ret.PreMulWorldNormal = DBufferB.rgb * 2 - (256.0 / 255.0);
ret.NormalOpacity = DBufferB.a;
// UNORM 4 channel
ret.PreMulMetallic = DBufferC.r;
ret.PreMulSpecular = DBufferC.g;
ret.PreMulRoughness = DBufferC.b;
ret.RoughnessOpacity = DBufferC.a;
return ret;
}
// @param BufferUV - UV space in the DBuffer textures
FDBufferData GetDBufferData(float2 BufferUV, uint RTMaskBit, uint EyeIndex)
{
// Setup default values, which mean that no decals are present in DBuffer
float4 DBufferA = float4(0.0, 0.0, 0.0, 1.0);
float4 DBufferB = float4(128.0f / 255.0f, 128.f / 255.5f, 128.f / 255.5f, 1.0);
float4 DBufferC = float4(0.0, 0.0, 0.0, 1.0);
#if USE_DBUFFER && ENABLE_DBUFFER_TEXTURES && !RAYHITGROUPSHADER && !LUMEN_CARD_CAPTURE
BRANCH
if (RTMaskBit & 0x1)
{
#if MOBILE_MULTI_VIEW && SHADING_PATH_MOBILE
DBufferA = Texture2DArraySampleLevel(OpaqueBasePassDBufferATextureArray, OpaqueBasePassDBufferATextureSampler, float3(BufferUV.xy, EyeIndex), 0);
#else
DBufferA = Texture2DSampleLevel(OpaqueBasePassDBufferATexture, OpaqueBasePassDBufferATextureSampler, BufferUV, 0);
#endif
}
BRANCH
if (RTMaskBit & 0x2)
{
#if MOBILE_MULTI_VIEW && SHADING_PATH_MOBILE
DBufferB = Texture2DArraySampleLevel(OpaqueBasePassDBufferBTextureArray, OpaqueBasePassDBufferBTextureSampler, float3(BufferUV.xy, EyeIndex), 0);
#else
DBufferB = Texture2DSampleLevel(OpaqueBasePassDBufferBTexture, OpaqueBasePassDBufferBTextureSampler, BufferUV, 0);
#endif
}
BRANCH
if (RTMaskBit & 0x4)
{
#if MOBILE_MULTI_VIEW && SHADING_PATH_MOBILE
DBufferC = Texture2DArraySampleLevel(OpaqueBasePassDBufferCTextureArray, OpaqueBasePassDBufferCTextureSampler, float3(BufferUV.xy, EyeIndex), 0);
#else
DBufferC = Texture2DSampleLevel(OpaqueBasePassDBufferCTexture, OpaqueBasePassDBufferCTextureSampler, BufferUV, 0);
#endif
}
#elif USE_DBUFFER && RAYHITGROUPSHADER
BRANCH
if (RTMaskBit & 0x1)
{
DBufferA = CurrentPayloadDBufferA;
}
BRANCH
if (RTMaskBit & 0x2)
{
// DecodeDBufferData expects DBufferB to have a specific scale and bias
DBufferB = float4(CurrentPayloadDBufferB.rgb * 0.5f + 128.0f / 255.0f, CurrentPayloadDBufferB.a);
}
BRANCH
if (RTMaskBit & 0x4)
{
DBufferC = CurrentPayloadDBufferC;
}
#endif
return DecodeDBufferData(DBufferA, DBufferB, DBufferC);
}
FDBufferData GetDBufferData(float2 BufferUV, uint RTMaskBit)
{
return GetDBufferData(BufferUV, RTMaskBit, 0);
}
/** Populates DBufferA, DBufferB, DBufferC as float4 and puts opacity in alpha for frame buffer blending */
void ApplyDBufferData(
FDBufferData DBufferData, inout float3 WorldNormal, inout float3 SubsurfaceColor, inout float Roughness,
inout float3 BaseColor, inout float Metallic, inout float Specular )
{
#if (MATERIALDECALRESPONSEMASK & 0x1)
BaseColor = BaseColor * DBufferData.ColorOpacity + DBufferData.PreMulColor;
SubsurfaceColor *= DBufferData.ColorOpacity;
#endif
#if (MATERIALDECALRESPONSEMASK & 0x2)
// We normalise the normal to get smoother visual result (it helps to avoid having D_GGX explodes toward infinity, and matches DecodeGBufferData)
WorldNormal = normalize(WorldNormal * DBufferData.NormalOpacity + DBufferData.PreMulWorldNormal);
#endif
#if (MATERIALDECALRESPONSEMASK & 0x4)
Roughness = Roughness * DBufferData.RoughnessOpacity + DBufferData.PreMulRoughness;
Metallic = Metallic * DBufferData.RoughnessOpacity + DBufferData.PreMulMetallic;
Specular = Specular * DBufferData.RoughnessOpacity + DBufferData.PreMulSpecular;
#endif
}