Files
UnrealEngine/Engine/Shaders/Private/HairStrands/HairStrandsGuideDeform.usf
2025-05-18 13:04:45 +08:00

115 lines
4.1 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
#include "../Common.ush"
#include "HairStrandsClusterCommon.ush"
#include "HairStrandsBindingCommon.ush"
#include "HairStrandsVertexFactoryCommon.ush"
#if SHADER_DEFORM_GUIDE
float3 SimRestOffset;
uint VertexCount;
uint InstanceRegisteredIndex;
StructuredBuffer<float4> SimDeformedOffsetBuffer;
ByteAddressBuffer SimRestPosePositionBuffer;
RWByteAddressBuffer OutSimDeformedPositionBuffer;
#define DEFORMATION_BYPASS 0
#define DEFORMATION_OFFSET_GUIDE 1
#define DEFORMATION_OFFSET_GUIDE_DYNAMIC 2
#define DEFORMATION_OFFSET_GUIDE_GLOBAL 3
#define DEFORMATION_OFFSET_GUIDE_BONES 4
#if PERMUTATION_DEFORMATION == DEFORMATION_OFFSET_GUIDE_DYNAMIC
Buffer<float4> SimRestPositionBuffer;
Buffer<float4> SimDeformedPositionBuffer;
Buffer<uint> SimRootBarycentricBuffer;
ByteAddressBuffer SimPointToCurveBuffer;
Buffer<uint> SimRootToUniqueTriangleIndexBuffer;
// Return world position of a guide vertex deformed by a skinned triangle
float3 DeformGuideByTriangle(
uint GuideIndex,
FHairMeshBasis RestBasis,
FHairMeshBasis DeformedBasis)
{
const float3 WorldRestGuidePoint = ReadHairControlPointPosition(SimRestPosePositionBuffer, GuideIndex, SimRestOffset);
const float3 LocalRestGuidePoint = ToTriangle(WorldRestGuidePoint, RestBasis);
const float3 WorldDeformedGuidePoint = ToWorld(LocalRestGuidePoint, DeformedBasis);
return WorldDeformedGuidePoint;
}
#endif
#if PERMUTATION_DEFORMATION == DEFORMATION_OFFSET_GUIDE_BONES
Buffer<float4> BoneDeformedPositionBuffer;
#endif
#if PERMUTATION_DEFORMATION == DEFORMATION_OFFSET_GUIDE_GLOBAL
uint SampleCount;
StructuredBuffer<float4> RestSamplePositionsBuffer;
StructuredBuffer<float4> MeshSampleWeightsBuffer;
#endif
float3 DisplacePosition(uint VertexIndex, float3 Pos)
{
const float3 OutSimHairPositionOffset = ReadSimPositionOffset(SimDeformedOffsetBuffer, InstanceRegisteredIndex);
// By pass
#if PERMUTATION_DEFORMATION == DEFORMATION_BYPASS
return Pos;
#endif
#if PERMUTATION_DEFORMATION == DEFORMATION_OFFSET_GUIDE
return Pos + (SimRestOffset - OutSimHairPositionOffset);
#endif
#if PERMUTATION_DEFORMATION == DEFORMATION_OFFSET_GUIDE_DYNAMIC
const uint RootIndex = ReadHairPointToCurveIndex(SimPointToCurveBuffer, VertexIndex);
const float3 RootBarycentric = UnpackBarycentrics(SimRootBarycentricBuffer[RootIndex]);
const uint TriangleIndex = SimRootToUniqueTriangleIndexBuffer[RootIndex];
const FHairMeshBasis RestBasis = GetHairMeshBasis(TriangleIndex, SimRestPositionBuffer, RootBarycentric);
const FHairMeshBasis DeformedBasis = GetHairMeshBasis(TriangleIndex, SimDeformedPositionBuffer, RootBarycentric);
return DeformGuideByTriangle(VertexIndex, RestBasis, DeformedBasis) - OutSimHairPositionOffset;
#endif
#if PERMUTATION_DEFORMATION == DEFORMATION_OFFSET_GUIDE_GLOBAL
const float3 RestControlPoint = Pos + SimRestOffset;
const float3 ControlPoint = ApplyRBF(RestControlPoint, SampleCount, RestSamplePositionsBuffer, MeshSampleWeightsBuffer);
return ControlPoint - OutSimHairPositionOffset;
#endif
#if PERMUTATION_DEFORMATION == DEFORMATION_OFFSET_GUIDE_BONES
const float4 RestControlPoint = float4(Pos + SimRestOffset,1);
const int BufferOffset = 3 * (VertexIndex+1);
const float3x4 BoneMatrix = float3x4(BoneDeformedPositionBuffer[BufferOffset], BoneDeformedPositionBuffer[BufferOffset+1], BoneDeformedPositionBuffer[BufferOffset+2]);
return mul(BoneMatrix,RestControlPoint) - OutSimHairPositionOffset;
#endif
}
[numthreads(GROUP_SIZE, 1, 1)]
void MainCS(uint DispatchThreadId : SV_DispatchThreadID)
{
const uint VertexIndex = DispatchThreadId;
if (VertexIndex < VertexCount)
{
const FPackedHairPosition PackedCP = ReadPackedHairPosition(SimRestPosePositionBuffer, VertexIndex);
const float3 CPPosition = UnpackHairControlPointPosition(PackedCP);
const float3 DisplacedPosition = DisplacePosition(VertexIndex, CPPosition);
WritePackedHairControlPointPosition(OutSimDeformedPositionBuffer, VertexIndex, PackedCP, DisplacedPosition);
// OutSimDeformedPositionBuffer[VertexIndex] = PackHairControlPointPosition(PackedCP, DisplacedPosition);
}
}
#endif // SHADER_DEFORM_GUIDE