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

284 lines
8.7 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "SSDDefinitions.ush"
#include "../Common.ush"
#include "../SceneTextureParameters.ush"
#include "/Engine/Public/WaveBroadcastIntrinsics.ush"
//------------------------------------------------------- SHARED CONSTANTS DEPENDING ON CONFIG OF SHADER
#define MAX_COMPRESSED_METADATA_VGPRS 6
//------------------------------------------------------- SHARED FUNCTION
void DecompressDevizeZAndN(uint Compressed, out float DevizeZ, out float3 N)
{
DevizeZ = f16tof32(Compressed & 0x3FFF);
uint FaceN = (Compressed >> 15) & 0x7;
N.x = float((Compressed >> 18) & 0x7F) * rcp(127);
N.y = float((Compressed >> 25) & 0x7F) * rcp(127);
N.z = 0.0;
DecodeNormal(/* inout */ N, FaceN);
}
uint CompressDevizeZAndN(float DevizeZ, float3 N)
{
uint FaceN;
EncodeNormal(/* inout */ N, /* out */ FaceN);
uint2 FaceCood = uint2(clamp(round(127.0 * N.xy), 0, 127.0));
uint Compressed = f32tof16(DevizeZ) | (FaceN << 15) | (FaceCood.x << 18) | (FaceCood.y << 25);
return Compressed;
}
/** Return whether this shading model id should be denoised or not. */
bool DenoiseShadingModelID(uint ShadingModelID)
{
return ShadingModelID != SHADINGMODELID_UNLIT;
}
//------------------------------------------------------- COMMON SCENE INFOS
/** olds commonly used information of the scene of a given sample. */
struct FSSDCompressedSceneInfos
{
/** Raw compressed buffer, kept fully compressed to have minimal VGPR footprint. */
uint VGPR[MAX_COMPRESSED_METADATA_VGPRS];
};
FSSDCompressedSceneInfos CreateCompressedSceneInfos()
{
FSSDCompressedSceneInfos CompressedInfos;
UNROLL_N(MAX_COMPRESSED_METADATA_VGPRS)
for (uint i = 0; i < MAX_COMPRESSED_METADATA_VGPRS; i++)
{
CompressedInfos.VGPR[i] = 0;
}
return CompressedInfos;
}
//------------------------------------------------------- UNCOMPRESSED SCENE INFOS
/** olds commonly used information of the scene of a given sample. */
struct FSSDSampleSceneInfos
{
/** Raw screen position of the sample. */
float2 ScreenPosition;
/** The raw device Z. */
float DeviceZ;
/** Raw pixel depth in world space. */
float WorldDepth;
/** Roughness of the pixel. */
float Roughness;
/** Normal of the pixel in world space. */
float3 WorldNormal;
/** Normal of the pixel in view space. */
float3 ViewNormal;
/** Position of the pixel in the translated world frame to save VALU. */
float3 TranslatedWorldPosition;
/** Shading model of the scene pixel. */
uint ShadingModelID;
};
FSSDSampleSceneInfos CreateSampleSceneInfos()
{
FSSDSampleSceneInfos Infos;
Infos.WorldDepth = 0;
Infos.ScreenPosition = 0;
Infos.Roughness = 0;
Infos.WorldNormal = 0;
Infos.ViewNormal = 0;
Infos.TranslatedWorldPosition = 0;
Infos.ShadingModelID = SHADINGMODELID_DEFAULT_LIT;
return Infos;
}
//------------------------------------------------------- UNCOMPRESSED SCENE INFOS
// SUBSTRATE_TODO
ISOLATE
FSSDSampleSceneInfos UncompressSampleSceneInfo(
const uint CompressedLayout, const bool bIsPrevFrame,
float2 ScreenPosition,
FSSDCompressedSceneInfos CompressedInfos)
{
FSSDSampleSceneInfos Infos = CreateSampleSceneInfos();
Infos.ScreenPosition = ScreenPosition;
if (CompressedLayout == METADATA_BUFFER_LAYOUT_DISABLED)
{
Infos.WorldDepth = asfloat(CompressedInfos.VGPR[0]);
Infos.WorldNormal.x = asfloat(CompressedInfos.VGPR[1]);
Infos.WorldNormal.y = asfloat(CompressedInfos.VGPR[2]);
Infos.WorldNormal.z = asfloat(CompressedInfos.VGPR[3]);
Infos.Roughness = asfloat(CompressedInfos.VGPR[4]);
Infos.ShadingModelID = CompressedInfos.VGPR[5];
Infos.DeviceZ = ConvertToDeviceZ(Infos.WorldDepth);
Infos.ViewNormal = mul(float4(Infos.WorldNormal, 0), View.TranslatedWorldToView).xyz;
}
else if (CompressedLayout == METADATA_BUFFER_LAYOUT_DEPTH_NORMAL)
{
DecompressDevizeZAndN(CompressedInfos.VGPR[0], /* out */ Infos.DeviceZ, /* out */ Infos.WorldNormal);
Infos.WorldDepth = ConvertFromDeviceZ(Infos.DeviceZ);
Infos.ViewNormal = mul(float4(Infos.WorldNormal, 0), View.TranslatedWorldToView).xyz;
}
else if (CompressedLayout == METADATA_BUFFER_LAYOUT_DEPTH_VIEWNORMAL)
{
float3 DecodedViewNormal;
DecompressDevizeZAndN(CompressedInfos.VGPR[0], /* out */ Infos.DeviceZ, /* out */ DecodedViewNormal);
Infos.WorldDepth = ConvertFromDeviceZ(Infos.DeviceZ);
if (bIsPrevFrame)
{
Infos.WorldNormal = mul(float4(DecodedViewNormal, 0), View.PrevViewToTranslatedWorld).xyz;
// TODO(Denoiser): PrevViewToView.
Infos.ViewNormal = mul(float4(Infos.WorldNormal, 0), View.TranslatedWorldToView).xyz;
}
else
{
Infos.ViewNormal = DecodedViewNormal;
Infos.WorldNormal = mul(float4(Infos.ViewNormal, 0), View.ViewToTranslatedWorld).xyz;
}
}
else if (CompressedLayout == METADATA_BUFFER_LAYOUT_FED_DEPTH_SHADINGMODEL)
{
Infos.DeviceZ = asfloat(CompressedInfos.VGPR[0]);
Infos.WorldDepth = ConvertFromDeviceZ(Infos.DeviceZ);
Infos.ShadingModelID = CompressedInfos.VGPR[1];
}
else if (CompressedLayout == METADATA_BUFFER_LAYOUT_WORLD_POS_SHADINGMODEL)
{
Infos.TranslatedWorldPosition.x = asfloat(CompressedInfos.VGPR[0]);
Infos.TranslatedWorldPosition.y = asfloat(CompressedInfos.VGPR[1]);
Infos.TranslatedWorldPosition.z = asfloat(CompressedInfos.VGPR[2]);
Infos.ShadingModelID = CompressedInfos.VGPR[3];
if (bIsPrevFrame)
{
Infos.WorldDepth = mul(float4(Infos.TranslatedWorldPosition, 1.0), View.TranslatedWorldToView).z;
}
else
{
Infos.WorldDepth = mul(float4(Infos.TranslatedWorldPosition, 1.0), View.PrevTranslatedWorldToView).z;
}
Infos.DeviceZ = ConvertToDeviceZ(Infos.WorldDepth);
return Infos;
}
else
{
// ERROR
}
// Compute translated world position.
{
float4 ClipPosition = float4(GetScreenPositionForProjectionType(ScreenPosition, Infos.WorldDepth), Infos.WorldDepth, 1);
if (bIsPrevFrame)
{
float3 PreViewTranslationOffset = DFFastLocalSubtractDemote(PrimaryView.PreViewTranslation, PrimaryView.PrevPreViewTranslation);
Infos.TranslatedWorldPosition = mul(ClipPosition, View.PrevScreenToTranslatedWorld).xyz + PreViewTranslationOffset;
}
else
{
Infos.TranslatedWorldPosition = mul(ClipPosition, View.ScreenToTranslatedWorld).xyz;
}
}
return Infos;
}
// SUBSTRATE_TODO
FSSDCompressedSceneInfos CompressSampleSceneInfo(
const uint CompressedLayout,
FSSDSampleSceneInfos Infos)
{
FSSDCompressedSceneInfos CompressedInfos = CreateCompressedSceneInfos();
if (CompressedLayout == METADATA_BUFFER_LAYOUT_DISABLED)
{
CompressedInfos.VGPR[0] = asuint(Infos.WorldDepth);
CompressedInfos.VGPR[1] = asuint(Infos.WorldNormal.x);
CompressedInfos.VGPR[2] = asuint(Infos.WorldNormal.y);
CompressedInfos.VGPR[3] = asuint(Infos.WorldNormal.z);
CompressedInfos.VGPR[4] = asuint(Infos.Roughness);
CompressedInfos.VGPR[5] = asuint(Infos.ShadingModelID);
}
else if (CompressedLayout == METADATA_BUFFER_LAYOUT_DEPTH_NORMAL)
{
CompressedInfos.VGPR[0] = CompressDevizeZAndN(Infos.DeviceZ, Infos.WorldNormal);
}
else if (CompressedLayout == METADATA_BUFFER_LAYOUT_DEPTH_VIEWNORMAL)
{
CompressedInfos.VGPR[0] = CompressDevizeZAndN(Infos.DeviceZ, Infos.ViewNormal);
}
else if (CompressedLayout == METADATA_BUFFER_LAYOUT_FED_DEPTH_SHADINGMODEL)
{
CompressedInfos.VGPR[0] = asuint(Infos.DeviceZ);
CompressedInfos.VGPR[1] = Infos.ShadingModelID;
}
else if (CompressedLayout == METADATA_BUFFER_LAYOUT_WORLD_POS_SHADINGMODEL)
{
CompressedInfos.VGPR[0] = asuint(Infos.TranslatedWorldPosition.x);
CompressedInfos.VGPR[1] = asuint(Infos.TranslatedWorldPosition.y);
CompressedInfos.VGPR[2] = asuint(Infos.TranslatedWorldPosition.z);
CompressedInfos.VGPR[3] = Infos.ShadingModelID;
}
else
{
// ERROR
}
return CompressedInfos;
}
float3 GetWorldNormal(FSSDSampleSceneInfos SceneMetadata)
{
return SceneMetadata.WorldNormal;
}
float GetWorldDepth(FSSDSampleSceneInfos SceneMetadata)
{
return SceneMetadata.WorldDepth;
}
float3 GetTranslatedWorldPosition(FSSDSampleSceneInfos SceneMetadata)
{
return SceneMetadata.TranslatedWorldPosition;
}
FSSDSampleSceneInfos WaveBroadcastSceneMetadata(const FWaveBroadcastSettings Settings, FSSDSampleSceneInfos SceneMetadata)
{
FSSDSampleSceneInfos NewSceneMetadata;
NewSceneMetadata.WorldDepth = WaveBroadcast(Settings, SceneMetadata.WorldDepth);
NewSceneMetadata.ScreenPosition = WaveBroadcast(Settings, SceneMetadata.ScreenPosition);
NewSceneMetadata.Roughness = WaveBroadcast(Settings, SceneMetadata.Roughness);
NewSceneMetadata.WorldNormal = WaveBroadcast(Settings, SceneMetadata.WorldNormal);
NewSceneMetadata.ViewNormal = WaveBroadcast(Settings, SceneMetadata.ViewNormal);
NewSceneMetadata.TranslatedWorldPosition = WaveBroadcast(Settings, SceneMetadata.TranslatedWorldPosition);
return NewSceneMetadata;
}