Files
UnrealEngineUWP/Engine/Shaders/Private/RayTracing/RayTracingDynamicMesh.usf
tiago costa 1722da7465 Raytracing in translated world space
- Raytracing shadows/reflections/AO/GI/etc and path tracer now work in large worlds.
- Updated parts of Lumen using raytracing to work in large worlds.
- This change doesn't not address (all) GPU Lightmass issues in large worlds.

Changes:
- Build TLAS with instances in translated world space.
- Move ray origin to translated world space.
- Updated raytracing shaders to use translated world space (most LWCHackToFloat in these shaders are now gone).
- Store gather points positions in translated world space.
- Removed unused RayTracingDynamicMeshVS(...)

#rb Yuriy.ODonnell, Patrick.Kelly, chris.kulla, rob.krajcarski
#jira UE-140558
#preflight 620bb3ff4353dc61c7f51e64

[CL 18995354 by tiago costa in ue5-main branch]
2022-02-15 09:20:03 -05:00

112 lines
4.3 KiB
Plaintext

// Copyright Epic Games, Inc. All Rights Reserved.
/*=============================================================================
RayTracingDynamicMesh.usf
=============================================================================*/
#define RAY_TRACING_DYNAMIC_MESH_SHADER_VERSION 0xFA5CE282 // Change to force shader compilation of this shader
#include "/Engine/Private/Common.ush"
#include "/Engine/Generated/Material.ush"
#include "/Engine/Generated/VertexFactory.ush"
struct FRayTracingDynamicMeshVSToGS
{
float4 WorldPosition : SV_POSITION;
};
// Must match GetUniformMeshStreamOutLayout and TRIANGLE_VERTEX_DATA_STRIDE
struct FRayTracingDynamicMeshVertex
{
float4 WorldPosition : SV_POSITION;
};
[maxvertexcount(3)]
void RayTracingDynamicMeshGS(triangle FRayTracingDynamicMeshVSToGS Inputs[3], inout TriangleStream<FRayTracingDynamicMeshVertex> OutStream)
{
for (int i = 0; i < 3; i++)
{
FRayTracingDynamicMeshVSToGS Input = Inputs[i];
FRayTracingDynamicMeshVertex Vertex;
Vertex.WorldPosition = Input.WorldPosition;
OutStream.Append(Vertex);
}
}
#if COMPUTESHADER
uint UsingIndirectDraw;
uint NumVertices;
uint MinVertexIndex;
uint PrimitiveId;
uint OutputVertexBaseIndex;
int InstanceId;
float4x4 WorldToInstance;
RWBuffer<float> RWVertexPositions;
int bApplyWorldPositionOffset;
[numthreads(64, 1, 1)]
void RayTracingDynamicGeometryConverterCS(uint3 DispatchThreadId : SV_DispatchThreadID)
{
if (DispatchThreadId.x >= NumVertices) return;
ResolvedView = ResolveView();
bool bUsingIndirectDraw = UsingIndirectDraw != 0;
uint NumActualVertices = bUsingIndirectDraw ? GetNumRayTracingDynamicMeshVerticesIndirect() : NumVertices;
uint VertexIndex = MinVertexIndex + DispatchThreadId.x;
if (DispatchThreadId.x < NumActualVertices)
{
FVertexFactoryInput Input = LoadVertexFactoryInputForDynamicUpdate(VertexIndex / 3, VertexIndex % 3, PrimitiveId);
#if USE_INSTANCING
Input.InstanceId = InstanceId;
#elif USE_INSTANCE_CULLING
Input.DrawInstanceId = InstanceId;
#endif
FVertexFactoryIntermediates VFIntermediates = GetVertexFactoryIntermediates(Input);
float4 WorldPosition = VertexFactoryGetWorldPosition(Input, VFIntermediates);
float3x3 TangentToLocal = VertexFactoryGetTangentToLocal(Input, VFIntermediates);
FMaterialVertexParameters VertexParameters = GetMaterialVertexParameters(Input, VFIntermediates, WorldPosition.xyz, TangentToLocal);
WorldPosition.xyz -= LWCHackToFloat(ResolvedView.PreViewTranslation);
if (bApplyWorldPositionOffset)
{
// We must guarantee that no NaNs are produced by WPO to avoid a possibility of producing invalid BLAS.
// DXR specification allows NaN positions to mark "inactive" primitives, but only when X component each vertex is NaN.
// This is impossible to guarantee here, since WPO is evaluated per vertex and not per triangle.
WorldPosition.xyz += MakeFinite(GetMaterialWorldPositionOffset(VertexParameters));
}
#if USE_INSTANCING || USE_INSTANCE_CULLING
//Reverse transform to neutral space
WorldPosition = mul(WorldPosition, WorldToInstance);
#elif RAY_TRACING_DYNAMIC_MESH_IN_LOCAL_SPACE
// Move the point back into local space because the RT instance will be placed there
// This the recommended default behavior so that the transform applied by the VertexFactory and the RT transform are always the same
WorldPosition.xyz = LWCMultiply(LWCPromote(WorldPosition), VertexFactoryGetWorldToLocal(VFIntermediates));
#elif RAY_TRACING_DYNAMIC_MESH_IN_WORLD_SPACE
// There are a few geometry types which natively generate positions in world space and therefore not need any extra processing here.
// This behavior must be explicitly opted-in to so as to make the code more self-documenting and avoid un-intended mismatched transforms.
#else
#error "Are you sure you want mesh vertices to be in world space? Please update the VertexFactory to report its requirement!"
#endif
RWVertexPositions[OutputVertexBaseIndex + VertexIndex * 3 + 0] = WorldPosition.x;
RWVertexPositions[OutputVertexBaseIndex + VertexIndex * 3 + 1] = WorldPosition.y;
RWVertexPositions[OutputVertexBaseIndex + VertexIndex * 3 + 2] = WorldPosition.z;
}
else
{
RWVertexPositions[OutputVertexBaseIndex + VertexIndex * 3 + 0] = asfloat(0xFFFFFFFF);
RWVertexPositions[OutputVertexBaseIndex + VertexIndex * 3 + 1] = 0;
RWVertexPositions[OutputVertexBaseIndex + VertexIndex * 3 + 2] = 0;
}
}
#endif