_xiaofang/xiaofang/Assets/Obi/Resources/Compute/ClothRendering.compute
杨号敬 bcc74f0465 add
2024-12-18 02:18:45 +08:00

180 lines
5.8 KiB
Plaintext

#pragma kernel UpdateSkinConstraints
#pragma kernel UpdateClothMesh
#include "MathUtils.cginc"
struct Influence
{
int index;
float weight;
};
struct SkinmapData
{
int firstInfluence;
int firstInfNumber;
int firstParticleBindPose;
int firstSkinWeight;
int firstSkinWeightNumber;
int firstBoneBindPose;
int bindPoseCount;
};
struct SkeletonData
{
int firstBone;
int boneCount;
};
struct MeshData
{
int firstVertex;
int vertexCount;
int firstTriangle;
int triangleCount;
};
StructuredBuffer<int> particleIndices;
StructuredBuffer<int> rendererIndices; // for each vertex/particle, index of its renderer.
StructuredBuffer<float4> renderablePositions;
StructuredBuffer<quaternion> renderableOrientations;
StructuredBuffer<float4> colors;
StructuredBuffer<float4> restPositions;
StructuredBuffer<quaternion> restOrientations;
StructuredBuffer<int> skinConstraintOffsets;
StructuredBuffer<int> skinmapIndices; // for each renderer, index of its skinmap.
StructuredBuffer<int> meshIndices; // for each renderer, index of its mesh.
StructuredBuffer<int> skeletonIndices; // for each renderer, index of its skeleton.
StructuredBuffer<int> particleOffsets; // for each renderer, index of its first particle in the batch.
StructuredBuffer<int> vertexOffsets; // for each renderer, index of its first vertex in the batch.
StructuredBuffer<SkinmapData> skinData;
StructuredBuffer<Influence> influences;
StructuredBuffer<int> influenceOffsets;
StructuredBuffer<float4x4> particleBindMatrices;
StructuredBuffer<float4x4> boneBindMatrices;
StructuredBuffer<SkeletonData> skeletonData;
StructuredBuffer<float3> bonePos;
StructuredBuffer<quaternion> boneRot;
StructuredBuffer<float3> boneScl;
StructuredBuffer<MeshData> meshData;
StructuredBuffer<float3> positions;
StructuredBuffer<float3> normals;
StructuredBuffer<float4> tangents;
RWStructuredBuffer<float4> skinConstraintPoints;
RWStructuredBuffer<float4> skinConstraintNormals;
RWByteAddressBuffer vertices;
// Variables set from the CPU
uint vertexCount;
uint constraintCount;
float4x4 world2Solver;
[numthreads(128, 1, 1)]
void UpdateSkinConstraints (uint3 id : SV_DispatchThreadID)
{
unsigned int i = id.x;
if (i >= constraintCount) return;
int rendererIndex = rendererIndices[i];
// get skin map and mesh data:
SkinmapData skin = skinData[skinmapIndices[rendererIndex]];
SkeletonData skel = skeletonData[skeletonIndices[rendererIndex]];
// invalid skeleton:
if (skel.boneCount <= 0)
return;
// get index of this particle in its original actor:
int originalParticleIndex = i - particleOffsets[rendererIndex];
// get first influence and amount of influences for this particle:
int influenceStart = influenceOffsets[skin.firstSkinWeightNumber + originalParticleIndex];
int influenceCount = influenceOffsets[skin.firstSkinWeightNumber + originalParticleIndex + 1] - influenceStart;
float4 pos = FLOAT4_ZERO;
float4 norm = FLOAT4_ZERO;
for (int k = influenceStart; k < influenceStart + influenceCount; ++k)
{
Influence inf = influences[skin.firstSkinWeight + k];
float4x4 bind = boneBindMatrices[skin.firstBoneBindPose + inf.index];
int boneIndex = skel.firstBone + inf.index;
float4x4 deform = TRS(bonePos[boneIndex], boneRot[boneIndex], boneScl[boneIndex]);
float4x4 trfm = mul(world2Solver, mul(deform, bind));
pos.xyz += mul(trfm, float4(restPositions[particleIndices[i]].xyz, 1)).xyz * inf.weight;
norm.xyz += mul(trfm, float4(rotate_vector(restOrientations[particleIndices[i]], float3(0, 0, 1)), 0)).xyz * inf.weight;
}
int constraintIndex = skinConstraintOffsets[rendererIndex] + originalParticleIndex;
skinConstraintPoints[constraintIndex] = pos;
skinConstraintNormals[constraintIndex] = norm;
}
[numthreads(128, 1, 1)]
void UpdateClothMesh (uint3 id : SV_DispatchThreadID)
{
unsigned int i = id.x;
if (i >= vertexCount) return;
int rendererIndex = rendererIndices[i];
// get skin map and mesh data:
SkinmapData skin = skinData[skinmapIndices[rendererIndex]];
MeshData mesh = meshData[meshIndices[rendererIndex]];
// get index of this vertex in its original mesh:
int originalVertexIndex = i - vertexOffsets[rendererIndex];
// get index of the vertex in the mesh batch:
int batchedVertexIndex = mesh.firstVertex + originalVertexIndex;
// get first influence and amount of influences for this vertex:
int influenceStart = influenceOffsets[skin.firstInfNumber + originalVertexIndex];
int influenceCount = influenceOffsets[skin.firstInfNumber + originalVertexIndex + 1] - influenceStart;
float3 position = float3(0,0,0);
float3 normal = float3(0,0,0);
float4 tangent = FLOAT4_ZERO;
float4 color = FLOAT4_ZERO;
for (int k = influenceStart; k < influenceStart + influenceCount; ++k)
{
Influence inf = influences[skin.firstInfluence + k];
int p = particleIndices[particleOffsets[rendererIndex] + inf.index];
float4x4 deform = mul(m_translate(FLOAT4X4_IDENTITY,renderablePositions[p].xyz), q_toMatrix(renderableOrientations[p]));
float4x4 trfm = mul(deform, particleBindMatrices[skin.firstParticleBindPose + inf.index]);
// update vertex/normal/tangent:
position += mul(trfm, float4(positions[batchedVertexIndex], 1)).xyz * inf.weight;
normal += mul(trfm, float4(normals[batchedVertexIndex], 0)).xyz * inf.weight;
tangent += float4(mul(trfm, float4(tangents[batchedVertexIndex].xyz, 0)).xyz, tangents[batchedVertexIndex].w) * inf.weight;
color += colors[p] * inf.weight;
}
int base = i * 14;
vertices.Store3( base<<2, asuint(position));
vertices.Store3((base + 3)<<2, asuint(normal));
vertices.Store4((base + 6)<<2, asuint(tangent));
vertices.Store4((base + 10)<<2, asuint(color));
}