1. 程式人生 > >基於計算著色器實現BlendShape三維人臉表情動畫驅動

基於計算著色器實現BlendShape三維人臉表情動畫驅動

為什麼要用計算著色器呢? 因為人臉表情基模型頂點數實在是太多了,而且有不止一個模型,動畫越精細,表情基模型越多,這個時候僅僅用CPU計算顯然是不夠的,所以就開始上GPU了,平行計算。

直接上計算著色器的程式碼:

1、ComputeShader.compute

#pragma kernel Cul 

RWStructuredBuffer<float3> vertBuffer;
StructuredBuffer<float3> blendshapeBuffer;
StructuredBuffer<float3> naturalBuffer;
float weight;
//表情基權重 [numthreads(32,32,1)] void Cul(uint3 id : SV_DispatchThreadID) { int index = id.x * 32 * 4 + id.y; vertBuffer[index] = vertBuffer[index] + (blendshapeBuffer[index] - naturalBuffer[index]) * weight; }

2、ComputeShaderCS.cs

[RequireComponent(typeof(MeshFilter))]
public class ComputeShaderCS :
MonoBehaviour { //表情基的Mesh網格 0為natural模型 public Mesh[] meshs; //每個表情基的權重值陣列(限制在0-1) [Range(0,1)] public float[] weights; //計算著色器 public ComputeShader shader; ComputeBuffer vertBuffer; //頂點緩衝 ComputeBuffer blendshapeBuffer; //表情基模型緩衝 ComputeBuffer naturalBuffer; //natural模型緩衝
//模型網格資訊 Mesh mesh; private void Start() { //獲取模型的網格資訊 mesh = GetComponent<MeshFilter>().mesh; //分配緩衝空間(每個float佔4個位元組,一個Vector3包括3個float,所佔大小為4*3) vertBuffer = new ComputeBuffer(meshs[0].vertices.Length, 4 * 3); blendshapeBuffer = new ComputeBuffer(meshs[0].vertices.Length, 4 * 3); naturalBuffer = new ComputeBuffer(meshs[0].vertices.Length, 4 * 3); } private void Update() { //不必每一幀執行,此處為便於測試 RunShader(); } //執行計算著色器 void RunShader() { int kernel = shader.FindKernel("Cul"); Vector3[] vertices = new Vector3[meshs[0].vertices.Length]; //初始化緩衝 vertBuffer.SetData(meshs[0].vertices); naturalBuffer.SetData(meshs[0].vertices); //填充緩衝 shader.SetBuffer(kernel, "vertBuffer", vertBuffer); shader.SetBuffer(kernel, "naturalBuffer", naturalBuffer); //根據權重值與表情基計算新的頂點位置 for (int w = 1; w < weights.Length; w++) { if (weights[w] <= 0) continue; //初始化緩衝 blendshapeBuffer.SetData(meshs[w].vertices); //填充緩衝 shader.SetBuffer(kernel, "blendshapeBuffer", blendshapeBuffer); //設定權重 shader.SetFloat("weight", weights[w]); //執行Compute Shader shader.Dispatch(kernel, 4, 4, 1); } //獲取計算結果 vertBuffer.GetData(vertices); //更改網格結構 mesh.vertices = vertices; } void OnDestroy() { if (vertBuffer != null) vertBuffer.Release(); if (blendshapeBuffer != null) blendshapeBuffer.Release(); if (naturalBuffer != null) naturalBuffer.Release(); } }

效果

在這裡插入圖片描述 在這裡插入圖片描述

原始碼