Files
UnrealEngine/Engine/Shaders/Private/Nanite/NaniteVertexFetch.ush
Brandyn / Techy fcc1b09210 init
2026-04-04 15:40:51 -05:00

148 lines
4.6 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "../Common.ush"
#include "../ViewData.ush"
#include "NaniteSceneCommon.ush"
// Represents vertex data for a Nanite mesh in local space
struct FNaniteLocalVertex
{
// Index of the vertex in the cluster
uint VertIndex;
// Decoded vertex position (NOTE: On assembly parts, this is transformed into local, and is not "part"-local)
float3 Position;
// Prev vertex position (NOTE: This is currently only different than Position with skinned assembly parts)
float3 PrevPosition;
// Decoded vertex attribute data
FNaniteRawAttributeData RawAttributeData;
// Whether or not this vertex should be skinned
bool bEnableSkinning;
};
// Transforms a vertex that is part of an assembly into local space
void TransformNaniteAssemblyVertex(float4x4 AssemblyTransform, float4x4 PrevAssemblyTransform, inout FNaniteLocalVertex Vert)
{
const float3x3 NormalTransform = float3x3(
normalize(AssemblyTransform[0].xyz),
normalize(AssemblyTransform[1].xyz),
normalize(AssemblyTransform[2].xyz)
);
// NOTE: We assume non-negative scale. Otherwise, we'd have to flip the binormal sign and reverse the winding order
Vert.Position = mul(float4(Vert.Position, 1.0f), AssemblyTransform).xyz;
Vert.PrevPosition = mul(float4(Vert.PrevPosition, 1.0f), PrevAssemblyTransform).xyz;
Vert.RawAttributeData.TangentZ = mul(Vert.RawAttributeData.TangentZ, NormalTransform);
Vert.RawAttributeData.TangentXAndSign.xyz = mul(Vert.RawAttributeData.TangentXAndSign.xyz, NormalTransform);
}
template<uint N>
void FetchLocalNaniteVerts(
FPrimitiveSceneData PrimitiveData,
FInstanceSceneData InstanceData,
FInstanceViewData InstanceViewData,
FCluster Cluster,
FVisibleCluster VisibleCluster,
uint3 VertIndexes,
uint CompileTimeMaxTexCoords,
inout FNaniteLocalVertex OutVerts[N])
{
float3 Positions[N];
UNROLL
for (uint i = 0; i < N; i++)
{
Positions[i] = DecodePosition(VertIndexes[i], Cluster);
}
FNaniteRawAttributeData RawAttributeData[N];
GetRawAttributeData<N>(RawAttributeData, Cluster, Positions, VertIndexes, CompileTimeMaxTexCoords);
UNROLL
for (uint i = 0; i < N; ++i)
{
OutVerts[i].VertIndex = VertIndexes[i];
OutVerts[i].Position = Positions[i];
OutVerts[i].PrevPosition = Positions[i];
OutVerts[i].RawAttributeData = RawAttributeData[i];
// HACK: disable skinning on assembly parts until we get their own local skeleton/bones hooked up
// TODO: Nanite-Assemblies: Remove when part bones are accessible
OutVerts[i].bEnableSkinning = !IsAssemblyPartCluster(VisibleCluster);
}
if (IsAssemblyPartCluster(VisibleCluster))
{
#if NANITE_USE_RAYTRACING_UNIFORM_BUFFER
const float4x4 AssemblyTransform = LoadNaniteHierarchyAssemblyTransform(PrimitiveData.NaniteAssemblyTransformOffset, VisibleCluster.AssemblyTransformIndex);
float4x4 PrevAssemblyTransform = AssemblyTransform;
#else
const float4x4 AssemblyTransform = LoadNaniteAssemblyTransform(VisibleCluster.AssemblyTransformIndex);
float4x4 PrevAssemblyTransform = AssemblyTransform;
BRANCH
if (Cluster.bSkinning && InstanceViewData.bIsDeforming)
{
PrevAssemblyTransform = LoadNaniteAssemblyTransform(VisibleCluster.AssemblyTransformIndex + 1);
}
#endif
for (uint i = 0; i < N; ++i)
{
TransformNaniteAssemblyVertex(AssemblyTransform, PrevAssemblyTransform, OutVerts[i]);
}
}
}
FNaniteLocalVertex FetchLocalNaniteVertex(
FPrimitiveSceneData PrimitiveData,
FInstanceSceneData InstanceData,
FInstanceViewData InstanceViewData,
FCluster Cluster,
FVisibleCluster VisibleCluster,
uint VertIndex,
uint CompileTimeMaxTexCoords)
{
FNaniteLocalVertex Verts[1];
FetchLocalNaniteVerts(PrimitiveData, InstanceData, InstanceViewData, Cluster, VisibleCluster, VertIndex, CompileTimeMaxTexCoords, Verts);
return Verts[0];
}
template<uint N>
void FetchLocalNaniteVertexPositions(
FInstanceSceneData InstanceData,
FCluster Cluster,
FVisibleCluster VisibleCluster,
uint3 VertIndexes,
inout float3 OutPositions[N])
{
UNROLL
for (uint i = 0; i < N; i++)
{
OutPositions[i] = DecodePosition(VertIndexes[i], Cluster);
}
if (IsAssemblyPartCluster(VisibleCluster))
{
const float4x4 AssemblyTransform = LoadNaniteAssemblyTransform(VisibleCluster.AssemblyTransformIndex);
UNROLL
for (uint i = 0; i < N; ++i)
{
OutPositions[i] = mul(float4(OutPositions[i], 1), AssemblyTransform).xyz;
}
}
}
float3 FetchLocalNaniteVertexPosition(
FInstanceSceneData InstanceData,
FCluster Cluster,
FVisibleCluster VisibleCluster,
uint VertIndex)
{
float3 Positions[1];
FetchLocalNaniteVertexPositions(InstanceData, Cluster, VisibleCluster, VertIndex, Positions);
return Positions[0];
}