Files
UnrealEngineUWP/Engine/Shaders/Shared/SplineMeshShaderParams.h
jamie hayes 4a2eaa711f Spline mesh updates:
- Add system for spline meshes to cache their slice transforms into look-up textures to optimize spline evaluations in shaders.
- Optimize the Nanite cluster culling shader with spline mesh deformation enabled to limit the cost of this shader added to all Nanite culling.
- More tightly pack the spline mesh parameters into 7 float4s from 8 and rearrange them to optimize shader access.
- Add "Nanite Cluster Bounds Scale" to spline mesh parameters as a means of fixing rare artifacts caused by inaccurate cluster culling bounds.
- A few other various tweaks and fixes to Nanite spline meshes.
- With these improvements, r.Nanite.AllowSplineMeshes is now on by default

NOTE: This is a re-submission of a change that had been previously rolled back. It is now being resubmitted with fixes to the following issues:
- Gaps in spline meshes due to calculating endpoint tangents using finite differencing of the texture.
- Fixed an issue where spline mesh deformation was broken in RVT rendering.
- Fix to an assert that would trip in some commandlets that were using the scene uniform buffer without having first initialized FSystemTextures
- Handle extrapolation of spline sampling from manually specifying mesh extents that are smaller than the actual mesh boundaries.

#rb brian.karis
#jira UE-181795

[CL 27697936 by jamie hayes in ue5-main branch]
2023-09-07 20:32:42 -04:00

103 lines
3.8 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
// The packed size of the spline mesh data in float4s
#define SPLINE_MESH_PARAMS_FLOAT4_SIZE 7
// Definitions for sizing the scene spline mesh texture and encoding spline addresses
#define SPLINE_MESH_TEXEL_WIDTH_BITS (6u)
#define SPLINE_MESH_TEXEL_WIDTH (1u << SPLINE_MESH_TEXEL_WIDTH_BITS)
#define SPLINE_MESH_TEXEL_WIDTH_MASK (SPLINE_MESH_TEXEL_WIDTH - 1u)
#define SPLINE_MESH_TEXTURE_MAX_DIMENSION (16 * 1024)
#ifdef __cplusplus
#include "HLSLTypeAliases.h"
namespace SplineMeshInternal::ShaderParams::HLSL
{
// The struct below doesn't need to be binary compatible between C++ and HLSL because of custom packing/unpacking methods.
// So we'll let "half" just mean float on the C++ side in this particular context.
// (NOTE: placed in separate namespace so as not to pollute UE::HLSL)
using namespace UE::HLSL;
using half = float;
using half2 = float2;
using half3 = float3;
#endif // __cplusplus
struct FSplineMeshShaderParams
{
float3 StartPos;
float3 EndPos;
float3 StartTangent;
float3 EndTangent;
float2 StartOffset;
float2 EndOffset;
half StartRoll;
half EndRoll;
half2 StartScale;
half2 EndScale;
float MeshZScale;
float MeshZOffset;
float2 MeshDeformScaleMinMax;
bool bSmoothInterpRollScale;
half3 SplineUpDir;
half3 MeshDir;
half3 MeshX;
half3 MeshY;
uint2 TextureCoord;
half SplineDistToTexelScale;
half SplineDistToTexelOffset;
half NaniteClusterBoundsScale;
};
#ifdef __cplusplus
} // namespace SplineMeshInternal::ShaderParams::HLSL
using FSplineMeshShaderParams = SplineMeshInternal::ShaderParams::HLSL::FSplineMeshShaderParams;
#endif // __cplusplus
#ifndef __cplusplus
#include "/Engine/Private/Quaternion.ush"
// HLSL unpack method
FSplineMeshShaderParams UnpackSplineMeshParams(float4 PackedParams[SPLINE_MESH_PARAMS_FLOAT4_SIZE])
{
FSplineMeshShaderParams Output;
Output.StartPos = PackedParams[0].xyz;
Output.EndPos = PackedParams[1].xyz;
Output.StartTangent = PackedParams[2].xyz;
Output.EndTangent = float3(PackedParams[0].w, PackedParams[1].w, PackedParams[2].w);
Output.StartOffset = PackedParams[3].xy;
Output.EndOffset = PackedParams[3].zw;
Output.StartRoll = f16tof32(asuint(PackedParams[4].x));
Output.EndRoll = f16tof32(asuint(PackedParams[4].x) >> 16u);
Output.StartScale = half2(f16tof32(asuint(PackedParams[4].y)),
f16tof32(asuint(PackedParams[4].y) >> 16u));
Output.EndScale = half2(f16tof32(asuint(PackedParams[4].z)),
f16tof32(asuint(PackedParams[4].z) >> 16u));
Output.TextureCoord = uint2(asuint(PackedParams[4].w) & 0xFFFFu,
asuint(PackedParams[4].w) >> 16u);
Output.MeshZScale = PackedParams[5].x;
Output.MeshZOffset = PackedParams[5].y;
Output.MeshDeformScaleMinMax = half2(f16tof32(asuint(PackedParams[5].z)),
f16tof32(asuint(PackedParams[5].z) >> 16u));
Output.SplineDistToTexelScale = f16tof32(asuint(PackedParams[5].w));
Output.SplineDistToTexelOffset = f16tof32(asuint(PackedParams[5].w) >> 16u);
Output.SplineUpDir = half3(SNorm16ToF32(asuint(PackedParams[6].x)),
SNorm16ToF32(asuint(PackedParams[6].x) >> 16u),
SNorm16ToF32(asuint(PackedParams[6].y)));
Output.NaniteClusterBoundsScale = f16tof32((asuint(PackedParams[6].y) >> 16u) & 0x7FFFu);
Output.bSmoothInterpRollScale = (asuint(PackedParams[6].y) >> 31u) != 0;
FQuat MeshQuat = FQuat(SNorm16ToF32(asuint(PackedParams[6].z)),
SNorm16ToF32(asuint(PackedParams[6].z) >> 16u),
SNorm16ToF32(asuint(PackedParams[6].w)),
SNorm16ToF32(asuint(PackedParams[6].w) >> 16u));
half3x3 MeshRot = QuatToMatrix(MeshQuat);
Output.MeshDir = MeshRot[0];
Output.MeshX = MeshRot[1];
Output.MeshY = MeshRot[2];
return Output;
}
#endif // !__cplusplus