744 字
4 分钟
蒙皮和BS的Compute Shader参考
Unity 的蒙皮和 Bs 的 ComputeShader 的一种实现的参考。
// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)
#pragma kernel main#pragma kernel main SKIN_NORM#pragma kernel main SKIN_NORM SKIN_TANG
#include "HLSLSupport.cginc"#include "Internal-Skinning-Util.cginc"
struct BlendShapeVertex{ int index; float3 pos; float3 norm; float3 tang;};
uint g_FirstVert; // First vertex from blend shape buffer to useuint g_VertCount; // Sparse vertex count, not the full amount of vertices in meshfloat g_Weight;
[numthreads(64, 1, 1)]void main(uint3 threadID : SV_DispatchThreadID, SAMPLER_UNIFORM RWStructuredBuffer<MeshVertex> inOutMeshVertices, SAMPLER_UNIFORM StructuredBuffer<BlendShapeVertex> inBlendShapeVertices){ const uint t = threadID.x;
if (t >= g_VertCount) { return; }
BlendShapeVertex blendShapeVert = inBlendShapeVertices[t + g_FirstVert];
const uint vertIndex = blendShapeVert.index;
inOutMeshVertices[vertIndex].pos += blendShapeVert.pos * g_Weight;#if SKIN_NORM inOutMeshVertices[vertIndex].norm += blendShapeVert.norm * g_Weight;#endif#if SKIN_TANG inOutMeshVertices[vertIndex].tang.xyz += blendShapeVert.tang * g_Weight;#endif}// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)
// Generic compute skinning ... with pos, norm, and tangent skinning
#pragma kernel main SKIN_BONESFORVERT=0#pragma kernel main SKIN_BONESFORVERT=0 SKIN_NORM#pragma kernel main SKIN_BONESFORVERT=0 SKIN_TANG#pragma kernel main SKIN_BONESFORVERT=0 SKIN_NORM SKIN_TANG#pragma kernel main SKIN_BONESFORVERT=1#pragma kernel main SKIN_BONESFORVERT=1 SKIN_NORM#pragma kernel main SKIN_BONESFORVERT=1 SKIN_TANG#pragma kernel main SKIN_BONESFORVERT=1 SKIN_NORM SKIN_TANG#pragma kernel main SKIN_BONESFORVERT=2#pragma kernel main SKIN_BONESFORVERT=2 SKIN_NORM#pragma kernel main SKIN_BONESFORVERT=2 SKIN_TANG#pragma kernel main SKIN_BONESFORVERT=2 SKIN_NORM SKIN_TANG#pragma kernel main SKIN_BONESFORVERT=4#pragma kernel main SKIN_BONESFORVERT=4 SKIN_NORM#pragma kernel main SKIN_BONESFORVERT=4 SKIN_TANG#pragma kernel main SKIN_BONESFORVERT=4 SKIN_NORM SKIN_TANG
#include "HLSLSupport.cginc"
uint g_VertCount;
#if defined(SHADER_API_D3D11) || defined(SHADER_API_XBOXONE) || defined(SHADER_API_PS4) || defined(SHADER_API_GLCORE) || defined(SHADER_API_GLES3) || defined(SHADER_API_VULKAN) || defined(SHADER_API_METAL) || defined(SHADER_API_PSSL) || defined(SHADER_API_SWITCH)#define STRUCTURED_BUFFER_SUPPORT 1#else#define STRUCTURED_BUFFER_SUPPORT 0#endif
struct MeshVertex{ float3 pos;#if SKIN_NORM float3 norm;#endif#if SKIN_TANG float4 tang;#endif};
struct SkinInfluence{#if SKIN_BONESFORVERT <= 1 int index0;#elif SKIN_BONESFORVERT == 2 float weight0, weight1; int index0, index1;#elif SKIN_BONESFORVERT == 4 float weight0, weight1, weight2, weight3; int index0, index1, index2, index3;#endif};
#if SKIN_NORM && SKIN_TANG#define VERTEX_STRIDE 10#elif SKIN_NORM#define VERTEX_STRIDE 6#else#define VERTEX_STRIDE 3#endif
#if !STRUCTURED_BUFFER_SUPPORTMeshVertex FetchVert(SAMPLER_UNIFORM Buffer<float> vertices, const uint index, const uint stride){ MeshVertex vert;
uint offset = index * stride; vert.pos.x = vertices[offset++]; vert.pos.y = vertices[offset++]; vert.pos.z = vertices[offset++];
#if SKIN_NORM vert.norm.x = vertices[offset++]; vert.norm.y = vertices[offset++]; vert.norm.z = vertices[offset++];#endif
#if SKIN_TANG vert.tang.x = vertices[offset++]; vert.tang.y = vertices[offset++]; vert.tang.z = vertices[offset++]; vert.tang.w = vertices[offset++];#endif
return vert;}
void StoreVert(SAMPLER_UNIFORM RWBuffer<float> vertices, float3 pos, float3 normal, float4 tang, const uint index, const uint stride){ uint offset = index * stride; vertices[offset++] = pos.x; vertices[offset++] = pos.y; vertices[offset++] = pos.z;
#if SKIN_NORM vertices[offset++] = normal.x; vertices[offset++] = normal.y; vertices[offset++] = normal.z;#endif
#if SKIN_TANG vertices[offset++] = tang.x; vertices[offset++] = tang.y; vertices[offset++] = tang.z; vertices[offset++] = tang.w;#endif}
#endif
[numthreads(64, 1, 1)]#if !STRUCTURED_BUFFER_SUPPORTvoid main(uint3 threadID : SV_DispatchThreadID, SAMPLER_UNIFORM Buffer<float> inVertices, SAMPLER_UNIFORM StructuredBuffer<SkinInfluence> inSkin, SAMPLER_UNIFORM RWBuffer<float> outVertices, SAMPLER_UNIFORM StructuredBuffer<float4x4> inMatrices)#elsevoid main(uint3 threadID : SV_DispatchThreadID, SAMPLER_UNIFORM StructuredBuffer<MeshVertex> inVertices, SAMPLER_UNIFORM StructuredBuffer<SkinInfluence> inSkin, SAMPLER_UNIFORM RWStructuredBuffer<MeshVertex> outVertices, SAMPLER_UNIFORM StructuredBuffer<float4x4> inMatrices)#endif{ const uint t = threadID.x;
if (t >= g_VertCount) { return; }
#if !STRUCTURED_BUFFER_SUPPORT const MeshVertex vert = FetchVert(inVertices, t, VERTEX_STRIDE);#else const MeshVertex vert = inVertices[t];#endif SkinInfluence si = inSkin[t];
float3 vPos = vert.pos.xyz;#if SKIN_NORM float3 vNorm = vert.norm.xyz;#endif#if SKIN_TANG float3 vTang = vert.tang.xyz;#endif
float3 oPos = float3(0, 0, 0); float3 oNorm = float3(0, 0, 0); float4 oTang = float4(0, 0, 0, 0);
#if SKIN_BONESFORVERT == 0 uint startIndex = si.index0; uint endIndex = inSkin[t + 1].index0; float4x4 blendedMatrix = 0; for (uint i = startIndex; i < endIndex; i++) { uint weightAndIndex = inSkin[i].index0; float weight = float(weightAndIndex >> 16) * (1.0f / 65535.0f); uint index = weightAndIndex & 0xFFFF; blendedMatrix += inMatrices[index] * weight; }#elif SKIN_BONESFORVERT == 1 const float4x4 blendedMatrix = inMatrices[si.index0];#elif SKIN_BONESFORVERT == 2 const float4x4 blendedMatrix = inMatrices[si.index0] * si.weight0 + inMatrices[si.index1] * si.weight1;#elif SKIN_BONESFORVERT == 4 const float4x4 blendedMatrix = inMatrices[si.index0] * si.weight0 + inMatrices[si.index1] * si.weight1 + inMatrices[si.index2] * si.weight2 + inMatrices[si.index3] * si.weight3;#endif
oPos = mul(blendedMatrix, float4(vPos, 1)).xyz;
#if SKIN_NORM oNorm = mul(blendedMatrix, float4(vNorm, 0)).xyz;#endif
#if SKIN_TANG oTang.xyz = mul(blendedMatrix, float4(vTang, 0)).xyz; oTang.w = vert.tang.w;#endif
#if STRUCTURED_BUFFER_SUPPORT outVertices[t].pos = oPos;#if SKIN_NORM outVertices[t].norm = oNorm;#endif#if SKIN_TANG outVertices[t].tang = oTang;#endif#else StoreVert(outVertices, oPos, oNorm, oTang, t, VERTEX_STRIDE);#endif}