Files
UnrealEngineUWP/Engine/Shaders/Private/RayTracing/RayTracingDecalMaterialShader.usf
chris kulla cacbf35802 Path Tracer: Implement support for virtual texture feedback
This allows skipping the basepass when the path tracer is active, reducing overhead.

VT feedback logic is identical to the rasterizer for now, and will not restart the path tracer accumulation. This is not noticeable in the editor as the right VT pages are loaded fairly quickly. In the offline case, this could potentially lead to some textures being blurrier for some samples, but with proper warmup this should not be noticeable either.

Note that the VT feedback logic is only executed for camera rays for now.

#rb Jeremy.Moore

[CL 27872518 by chris kulla in ue5-main branch]
2023-09-14 05:19:55 -04:00

276 lines
10 KiB
Plaintext

// Copyright Epic Games, Inc. All Rights Reserved.
#define PATH_TRACING 1
#define SCENE_TEXTURES_DISABLED 1 // Ray tracing shaders cannot access scene textures
// This should be good enough for ray tracing and avoids having to bind an extra buffer
#define EYE_ADAPTATION_PREV_FRAME_EXPOSURE 1
#define SUBSTRATE_INLINE_SHADING 1
#include "/Engine/Private/Common.ush"
#include "/Engine/Private/RayTracing/RayTracingCommon.ush"
#include "/Engine/Private/PathTracing/PathTracingShaderUtils.ush"
#define DecalTilePosition RayTracingDecalParameters.DecalTilePosition
#define WorldToDecal RayTracingDecalParameters.WorldToDecal
#define SvPositionToDecal WorldToDecal
#define DecalToWorld RayTracingDecalParameters.DecalToWorld
#define DecalToWorldInvScale RayTracingDecalParameters.DecalToWorldInvScale
#define DecalOrientation RayTracingDecalParameters.DecalOrientation
#define DecalParams RayTracingDecalParameters.DecalParams
#define DecalColorParam RayTracingDecalParameters.DecalColorParam
#define DecalWriteFlags RayTracingDecalParameters.DecalWriteFlags
#include "/Engine/Generated/Material.ush"
struct FDecalData
{
float Opacity;
float3 BaseColor;
float3 WorldNormal;
float3 MetallicSpecularRoughness;
float3 Emissive;
void WriteToPayload(inout FDecalShaderPayload Payload, uint WriteFlags, float OpacityMult)
{
Opacity *= OpacityMult;
if (WriteFlags & DECAL_WRITE_BASE_COLOR_FLAG)
{
Payload.SetBaseColor(BaseColor * Opacity);
}
if (WriteFlags & DECAL_WRITE_NORMAL_FLAG)
{
Payload.SetWorldNormal(WorldNormal * Opacity);
}
if (WriteFlags & DECAL_WRITE_ROUGHNESS_SPECULAR_METALLIC_FLAG)
{
Payload.SetMetallicSpecularRoughness(MetallicSpecularRoughness * Opacity);
}
if (WriteFlags & DECAL_WRITE_EMISSIVE_FLAG)
{
Payload.SetEmissive(Emissive * Opacity);
}
Payload.SetTransparency(1.0f - Opacity);
Payload.SetFlags(WriteFlags);
}
};
FDecalData GetDecalData(FPixelMaterialInputs PixelMaterialInputs, FMaterialPixelParameters MaterialParameters)
{
FDecalData Result = (FDecalData)0;
#if SUBSTRATE_ENABLED
FSubstratePixelHeader SubstrateHeader = MaterialParameters.GetFrontSubstrateHeader();
if (SubstrateHeader.SubstrateTree.BSDFCount > 0)
{
const float3 V = MaterialParameters.CameraVector;
// Update tree (coverage/transmittance/luminace weights)
const FSubstrateIntegrationSettings Settings = InitSubstrateIntegrationSettings(false /*bForceFullyRough*/, false /*bRoughDiffuseEnabled*/, 0, false/*bRoughnessTracking*/);
SubstrateHeader.SubstrateUpdateTree(V, Settings);
// Since the Convert-To-Decal node forces parameter blending for the entire Substrate tree, the BSDF we are interested in will be in 0.
FSubstrateDBuffer DBuffer = SubstrateHeader.SubstrateConvertToDBuffer(SubstrateHeader.SubstrateTree.BSDFs[0]);
Result.Opacity = DBuffer.Coverage;
Result.BaseColor = DBuffer.BaseColor;
Result.WorldNormal = DBuffer.WorldNormal;
Result.MetallicSpecularRoughness = float3(DBuffer.Metallic, DBuffer.Specular, DBuffer.Roughness);
Result.Emissive = DBuffer.Emissive;
}
#else // SUBSTRATE_ENABLED
Result.Opacity = GetMaterialOpacity(PixelMaterialInputs);
Result.BaseColor = GetMaterialBaseColor(PixelMaterialInputs);
Result.WorldNormal = MaterialParameters.WorldNormal;
Result.MetallicSpecularRoughness = float3(GetMaterialMetallic(PixelMaterialInputs), GetMaterialSpecular(PixelMaterialInputs), GetMaterialRoughness(PixelMaterialInputs));
Result.Emissive = GetMaterialEmissive(PixelMaterialInputs);
#endif // SUBSTRATE_ENABLED
return Result;
}
#if RAYCALLABLESHADER
RAY_TRACING_ENTRY_CALLABLE(RayTracingDecalMaterialShader, FDecalShaderPayload, Payload)
{
ResolvedView = ResolveView();
const float3 TranslatedWorldPosition = Payload.GetInputTranslatedWorldPosition();
float4 DecalPos = mul(float4(TranslatedWorldPosition.xyz, 1), WorldToDecal);
if (any(abs(DecalPos.xyz) > 1))
{
// clip content outside the decal
Payload.SetTransparency(1.0f);
return;
}
float3 CameraVector = normalize(PrimaryView.TranslatedWorldCameraOrigin - TranslatedWorldPosition.xyz);
// can be optimized
float3 DecalVector = DecalPos.xyz * 0.5f + 0.5f;
// Swizzle so that DecalVector.xy are perpendicular to the projection direction and DecalVector.z is distance along the projection direction
float3 SwizzlePos = DecalVector.zyx;
// By default, map textures using the vectors perpendicular to the projection direction
float2 DecalUVs = SwizzlePos.xy;
FMaterialPixelParameters MaterialParameters = MakeInitializedMaterialPixelParameters();
#if NUM_MATERIAL_TEXCOORDS
for (int CoordinateIndex = 0; CoordinateIndex < NUM_MATERIAL_TEXCOORDS; CoordinateIndex++)
{
MaterialParameters.TexCoords[CoordinateIndex] = DecalUVs;
}
#endif
MaterialParameters.TwoSidedSign = 1;
MaterialParameters.VertexColor = 1;
MaterialParameters.CameraVector = CameraVector;
MaterialParameters.SvPosition = mul(float4(TranslatedWorldPosition, 1.0f), ResolvedView.TranslatedWorldToClip);
MaterialParameters.ScreenPosition = SvPositionToResolvedScreenPosition(MaterialParameters.SvPosition);
MaterialParameters.LightVector = SwizzlePos;
MaterialParameters.AbsoluteWorldPosition = MaterialParameters.WorldPosition_NoOffsets = LWCSubtract(TranslatedWorldPosition.xyz, PrimaryView.PreViewTranslation);
MaterialParameters.WorldPosition_CamRelative = MaterialParameters.WorldPosition_NoOffsets_CamRelative = TranslatedWorldPosition.xyz;
FPixelMaterialInputs PixelMaterialInputs;
CalcPixelMaterialInputs(MaterialParameters, PixelMaterialInputs);
const float DecalFading = saturate(4 - 4 * abs(SwizzlePos.z * 2 - 1)) * DecalParams.x;
FDecalData Data = GetDecalData(PixelMaterialInputs, MaterialParameters);
#if MATERIAL_VIRTUALTEXTURE_FEEDBACK
{
// Virtual texturing feedback logic
// NOTE: decals are only evaluated for camera rays (and sharp reflections)
FinalizeVirtualTextureFeedback(
MaterialParameters.VirtualTextureFeedback,
MaterialParameters.SvPosition,
Data.Opacity * DecalFading,
View.FrameNumber,
View.VTFeedbackBuffer
);
}
#endif
Data.WriteToPayload(Payload, DecalWriteFlags, DecalFading);
}
#endif // RAYCALLABLESHADER
#if RAYHITGROUPSHADER
#ifdef NEEDS_VERTEX_FACTORY_INTERPOLATION
#undef NEEDS_VERTEX_FACTORY_INTERPOLATION
#endif
// Needed for VertexFactoryInterpolate to interpolate attributes from vertices to hit point
#define NEEDS_VERTEX_FACTORY_INTERPOLATION 1
#include "/Engine/Private/RayTracing/RayTracingHitGroupCommon.ush"
#include "/Engine/Generated/VertexFactory.ush"
#include "/Engine/Private/RayTracing/RayTracingCalcInterpolants.ush"
RAY_TRACING_ENTRY_CLOSEST_HIT(RayTracingDecalMaterialCHS,
FDecalShaderPayload, Payload,
FRayTracingIntersectionAttributes, Attributes)
{
Payload.HitT = RayTCurrent();
ResolvedView = ResolveView();
const float3 TranslatedWorldPosition = TranslatedWorldRayOrigin() + WorldRayDirection() * RayTCurrent();
const float4 SvPosition = mul(float4(TranslatedWorldPosition, 1.0f), ResolvedView.TranslatedWorldToClip);
#if VF_SUPPORTS_RAYTRACING_PREPARE_MATERIAL_PIXEL_PARAMETERS
// this is a newer codepath that is both more flexible and allows for more direct calculation compared to the other codepath
// TODO: implement such a method for all vertex factories
float3 GeoNormal = 0;
FMaterialPixelParameters MaterialParameters = GetMaterialPixelParameters(TranslatedWorldRayOrigin(), WorldRayDirection(), RayTCurrent(), PrimitiveIndex(), Attributes, HitKind(), GeoNormal);
#else
FVertexFactoryInterpolantsVSToPS Interpolants;
float3 GeoNormal = 0;
CalcInterpolants((FRayCone)0, Attributes, Interpolants, GeoNormal);
FMaterialPixelParameters MaterialParameters = GetMaterialPixelParameters(Interpolants, SvPosition);
#endif
FPixelMaterialInputs PixelMaterialInputs;
{
const float4 ScreenPosition = SvPositionToResolvedScreenPosition(SvPosition);
const bool bIsFrontFace = HitKind() == HIT_KIND_TRIANGLE_FRONT_FACE;
MaterialParameters.CameraVector = -WorldRayDirection();
// #dxr_todo: UE-72130 support world position offset
// #if USE_WORLD_POSITION_EXCLUDING_SHADER_OFFSETS
// CalcMaterialParametersEx(MaterialParameters, PixelMaterialInputs, SvPosition, ScreenPosition, bIsFrontFace, TranslatedWorldPosition, BasePassInterpolants.PixelPositionExcludingWPO);
// #else
CalcMaterialParametersEx(MaterialParameters, PixelMaterialInputs, SvPosition, ScreenPosition, bIsFrontFace, TranslatedWorldPosition, TranslatedWorldPosition);
// #endif
}
FDecalData Data = GetDecalData(PixelMaterialInputs, MaterialParameters);
#if MATERIAL_VIRTUALTEXTURE_FEEDBACK
{
// Virtual texturing feedback logic
// NOTE: decals are only evaluated for camera rays (and sharp reflections)
FinalizeVirtualTextureFeedback(
MaterialParameters.VirtualTextureFeedback,
MaterialParameters.SvPosition,
Data.Opacity,
View.FrameNumber,
View.VTFeedbackBuffer
);
}
#endif
Data.WriteToPayload(Payload, DECAL_PAYLOAD_FLAGS, 1.0);
}
#if USE_MATERIAL_ANY_HIT_SHADER
RAY_TRACING_ENTRY_ANY_HIT(RayTracingDecalMaterialAHS,
FDecalShaderPayload, Payload,
FRayTracingIntersectionAttributes, Attributes)
{
ResolvedView = ResolveView();
const float3 TranslatedWorldPosition = TranslatedWorldRayOrigin() + WorldRayDirection() * RayTCurrent();
const float4 SvPosition = mul(float4(TranslatedWorldPosition, 1.0f), ResolvedView.TranslatedWorldToClip);
FVertexFactoryInterpolantsVSToPS Interpolants;
CalcInterpolants((FRayCone)0, Attributes, Interpolants);
FMaterialPixelParameters MaterialParameters = GetMaterialPixelParameters(Interpolants, SvPosition);
FPixelMaterialInputs PixelMaterialInputs;
const bool bIsFrontFace = HitKind() == HIT_KIND_TRIANGLE_FRONT_FACE;
{
const float4 ScreenPosition = SvPositionToResolvedScreenPosition(SvPosition);
MaterialParameters.CameraVector = -WorldRayDirection();
CalcMaterialParametersEx(MaterialParameters, PixelMaterialInputs, SvPosition, ScreenPosition, bIsFrontFace, TranslatedWorldPosition, TranslatedWorldPosition);
}
const float Opacity = GetDecalData(PixelMaterialInputs, MaterialParameters).Opacity;
if (Opacity <= 0.00001f)
{
IgnoreHit();
return;
}
}
#endif // USE_MATERIAL_ANY_HIT_SHADER
#endif // RAYHITGROUPSHADER