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

140 lines
5.8 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "../Barycentrics.ush"
struct FRaytracingDerivatives
{
TDual< float3 > WorldPosition;
TDual< float3 > WorldGeoNormals;
TDual< float4 > ScreenPosition;
#if NUM_TEX_COORD_INTERPOLATORS
TDual< float2 > TexCoords[NUM_TEX_COORD_INTERPOLATORS];
#endif
};
void CalcInterpolants(
in float4 SvPosition,
in FRayCone RayCone,
in FRayTracingIntersectionAttributes Attributes,
inout FVertexFactoryInterpolantsVSToPS OutInterpolants,
inout FRaytracingDerivatives OutDerivateData,
inout float3 OutFaceNormal)
{
FVertexFactoryRayTracingInterpolants Interpolated = (FVertexFactoryRayTracingInterpolants)0;
float4 ClipPositions[3];
float3 WorldPositions[3];
float3 WorldGeoNormals[3];
float2 TexCoords[3];
#if NUM_TEX_COORD_INTERPOLATORS
float2 TexCoords_Custom[NUM_TEX_COORD_INTERPOLATORS][3];
#endif
const float2 VW = Attributes.GetBarycentrics();
const float3 UVW = float3(1 - VW.x - VW.y, VW.x, VW.y);
for (int i = 0; i < 3; i++)
{
FVertexFactoryInput Input = LoadVertexFactoryInputForHGS(PrimitiveIndex(), i);
FVertexFactoryIntermediates VFIntermediates = GetVertexFactoryIntermediates(Input);
float3x3 TangentToLocal = VertexFactoryGetTangentToLocal(Input, VFIntermediates);
float4 WorldPositionExcludingWPO = VertexFactoryGetWorldPosition(Input, VFIntermediates);
FMaterialVertexParameters VertexParameters = GetMaterialVertexParameters(Input, VFIntermediates, WorldPositionExcludingWPO.xyz, TangentToLocal);
FVertexFactoryRayTracingInterpolants PerVertexInterpolants = VertexFactoryGetRayTracingInterpolants(Input, VFIntermediates, VertexParameters);
Interpolated = VertexFactoryInterpolate(PerVertexInterpolants, UVW[i], Interpolated, 1.0);
WorldPositions[i] = WorldPositionExcludingWPO.xyz;
WorldGeoNormals[i] = VertexFactoryGetWorldNormal(Input, VFIntermediates);
TexCoords[i] = VertexFactoryGetRayTracingTextureCoordinate(PerVertexInterpolants);
#if (NUM_TEX_COORD_INTERPOLATORS)
UNROLL
for (uint TexCoordIndex=0;TexCoordIndex<NUM_TEX_COORD_INTERPOLATORS; ++TexCoordIndex)
{
#if !VERTEX_FACTORY_MODIFIES_INTERPOLATION && !VF_SUPPORTS_RAYTRACING_PREPARE_MATERIAL_PIXEL_PARAMETERS
TexCoords_Custom[TexCoordIndex][i] = GetUV(PerVertexInterpolants.InterpolantsVSToPS, TexCoordIndex);
#else
TexCoords_Custom[TexCoordIndex][i] = TexCoords[i];
#endif
}
#endif
ClipPositions[i] = mul(float4(WorldPositions[i], 1), View.TranslatedWorldToClip);
}
OutInterpolants = VertexFactoryAssignInterpolants(Interpolated);
float3 PA = WorldPositions[1] - WorldPositions[0];
float3 PB = WorldPositions[2] - WorldPositions[0];
float3 Unnormalized = cross(PB, PA);
float InvWorldArea = rsqrt(dot(Unnormalized, Unnormalized));
OutFaceNormal = Unnormalized * InvWorldArea;
#if USE_RAYTRACED_TEXTURE_RAYCONE_LOD && (NUM_TEX_COORD_INTERPOLATORS || USE_PARTICLE_SUBUVS) && !VERTEX_FACTORY_MODIFIES_INTERPOLATION
float2 TA = TexCoords[1] - TexCoords[0];
float2 TB = TexCoords[2] - TexCoords[0];
float UvArea = abs((TA.x * TB.y) - (TA.y * TB.x));
float RayConeCapArea = RayCone.Width * RayCone.Width * (1.0f / (2.0f * PI));
float3 RayDir = WorldRayDirection();
float RaySlope = dot(RayDir, OutFaceNormal);
const float SmallValue = 1.0 / 16777216.0;
GlobalRayCone_TexArea = (UvArea * InvWorldArea * RayConeCapArea) / max(RaySlope * RaySlope, SmallValue);
GlobalRayCone_TexArea = max(GlobalRayCone_TexArea, SmallValue);
#endif
// Compute derivatives
const float2 PixelClip = (SvPosition.xy - View.ViewRectMin.xy) * View.ViewSizeAndInvSize.zw * float2(2, -2) + float2(-1, 1);
FBarycentrics Barycentrics = CalculateTriangleBarycentrics(PixelClip, ClipPositions[0], ClipPositions[1], ClipPositions[2], View.ViewSizeAndInvSize.zw);
OutDerivateData.WorldPosition = Lerp( WorldPositions[0], WorldPositions[1], WorldPositions[2], Barycentrics );
OutDerivateData.WorldGeoNormals = Lerp( WorldGeoNormals[0], WorldGeoNormals[1], WorldGeoNormals[2], Barycentrics );
OutDerivateData.ScreenPosition = Lerp( ClipPositions[0] * rcp(ClipPositions[0].w), ClipPositions[1] * rcp(ClipPositions[1].w), ClipPositions[2] * rcp(ClipPositions[2].w), Barycentrics );
#if NUM_TEX_COORD_INTERPOLATORS > 0
UNROLL
for (uint TexCoordIndex = 0; TexCoordIndex < NUM_TEX_COORD_INTERPOLATORS; TexCoordIndex++)
{
OutDerivateData.TexCoords[TexCoordIndex] = Lerp( TexCoords_Custom[TexCoordIndex][0], TexCoords_Custom[TexCoordIndex][1], TexCoords_Custom[TexCoordIndex][2], Barycentrics );
}
#endif
}
void CalcInterpolants(in FRayCone RayCone, in FRayTracingIntersectionAttributes Attributes, inout FVertexFactoryInterpolantsVSToPS OutInterpolants, inout float3 OutFaceNormal)
{
FRaytracingDerivatives OutDerivatives; // unused
CalcInterpolants(0, RayCone, Attributes, OutInterpolants, OutDerivatives, OutFaceNormal);
}
// simplified call when Geometric Normal is not needed
void CalcInterpolants(in FRayCone RayCone, in FRayTracingIntersectionAttributes Attributes, inout FVertexFactoryInterpolantsVSToPS OutInterpolants)
{
float3 OutGeoNormal = 0; // unused
FRaytracingDerivatives OutDerivatives; // unused
CalcInterpolants(0, RayCone, Attributes, OutInterpolants, OutDerivatives, OutGeoNormal);
}
void ApplyRaytracingDerivatives(inout FMaterialPixelParameters Out, in FRaytracingDerivatives In)
{
Out.WorldPosition_DDX = In.WorldPosition.Value_dx;
Out.WorldPosition_DDY = In.WorldPosition.Value_dy;
Out.ScreenPosition_DDX = In.ScreenPosition.Value_dx;
Out.ScreenPosition_DDY = In.ScreenPosition.Value_dy;
Out.WorldGeoNormal_DDX = In.WorldGeoNormals.Value_dx;
Out.WorldGeoNormal_DDY = In.WorldGeoNormals.Value_dy;
#if NUM_TEX_COORD_INTERPOLATORS
UNROLL
for (uint TexCoordIndex = 0; TexCoordIndex < NUM_TEX_COORD_INTERPOLATORS; TexCoordIndex++)
{
Out.TexCoords_DDX[TexCoordIndex] = In.TexCoords[TexCoordIndex].Value_dx;
Out.TexCoords_DDY[TexCoordIndex] = In.TexCoords[TexCoordIndex].Value_dy;
}
#endif
}