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

101 lines
3.6 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "/Engine/Public/Platform.ush"
#include "../GpuSkinCommon.ush"
#if SHADER_SKIN_UPDATE
//----------------------------------------------------------------------------------
uint bWriteTangent;
uint WeightIndexSize; // bone index size: 1 - 8bit or 2 - 16bit
uint SectionVertexBaseIndex;
uint NumTotalVertices;
uint NumVertexToProcess;
uint WeightStride;
uint TangentFormat;
Buffer<uint> WeightLookup;
Buffer<uint> VertexWeights;
Buffer<float> RestPositions;
Buffer<SNORM float4> RestTangents;
// Current Position
Buffer<float4> BoneMatrices;
RWBuffer<float> DeformedPositions;
RWBuffer<TANGENT_RWBUFFER_FORMAT> DeformedTangents; // GL does not support SNORM images, so instead we write to SINT
// Previous Position
#if PERMUTATION_PREV
Buffer<float4> PrevBoneMatrices;
RWBuffer<float> PrevDeformedPositions;
#endif
//----------------------------------------------------------------------------------
[numthreads(GROUP_SIZE,1,1)]
void UpdateSkinPositionCS(uint3 GroupID : SV_GroupID,
uint3 DispatchThreadID : SV_DispatchThreadID,
uint3 GroupThreadID : SV_GroupThreadID)
{
const uint VertexIndex = DispatchThreadID.x + SectionVertexBaseIndex;
if (DispatchThreadID.x < NumVertexToProcess && VertexIndex < NumTotalVertices)
{
const uint PositionOffset = VertexIndex * 3;
const uint WeightOffset = VertexIndex * WeightStride / 4;
#if !GPUSKIN_UNLIMITED_BONE_INFLUENCE
const FGPUSkinIndexAndWeight IndicesAndWeights = GetBlendIndicesAndWeights(VertexWeights, WeightOffset);
#endif
const float4 InputPosition = float4(
RestPositions[PositionOffset],
RestPositions[PositionOffset+1],
RestPositions[PositionOffset+2],
1.0);
// Current position
{
#if GPUSKIN_UNLIMITED_BONE_INFLUENCE
const FBoneMatrix BlendedMatrix = ComputeBoneMatrixWithUnlimitedInfluences(BoneMatrices, VertexWeights, WeightIndexSize, WeightLookup[VertexIndex]);
#else
const FBoneMatrix BlendedMatrix = ComputeBoneMatrixWithLimitedInfluences(BoneMatrices, IndicesAndWeights);
#endif
const float3 OutputPosition = mul(BlendedMatrix, InputPosition);
DeformedPositions[PositionOffset ] = OutputPosition.x;
DeformedPositions[PositionOffset+1] = OutputPosition.y;
DeformedPositions[PositionOffset+2] = OutputPosition.z;
if (bWriteTangent)
{
const float4 InputTangentZ = TangentBias_SkinCache(RestTangents[2 * VertexIndex + GPUSKIN_RWBUFFER_OFFSET_TANGENT_Z]);
//const float4 InputTangentZ = TangentBias(RestTangents[2 * VertexIndex + GPUSKIN_RWBUFFER_OFFSET_TANGENT_Z]);
// Use similar code than GPU skin cache, but this should use the inverse transpose for correct normal stransformation
//const const float4x4 InvTransposeBlendedMatrix = Transpose(Inverse(BlendedMatrix));
const float3 OutputTangentZ = mul(BlendedMatrix, float4(InputTangentZ.xyz,0)).xyz;
DeformedTangents[VertexIndex * 2 + GPUSKIN_RWBUFFER_OFFSET_TANGENT_Z] = TangentUnbias_SkinCache(float4(OutputTangentZ, InputTangentZ.w));
}
}
// Previous position
#if PERMUTATION_PREV
{
#if GPUSKIN_UNLIMITED_BONE_INFLUENCE
const FBoneMatrix PrevBlendedMatrix = ComputeBoneMatrixWithUnlimitedInfluences(PrevBoneMatrices, VertexWeights, WeightIndexSize, WeightLookup[VertexIndex]);
#else
const FBoneMatrix PrevBlendedMatrix = ComputeBoneMatrixWithLimitedInfluences(PrevBoneMatrices, IndicesAndWeights);
#endif
const float3 OutputPosition = mul(PrevBlendedMatrix, InputPosition);
PrevDeformedPositions[PositionOffset ] = OutputPosition.x;
PrevDeformedPositions[PositionOffset+1] = OutputPosition.y;
PrevDeformedPositions[PositionOffset+2] = OutputPosition.z;
}
#endif
}
}
#endif // SHADER_SKIN_UPDATE