[Unity] GPU动画实现(四)——生成动画数据

本文探讨了当前基于顶点生成动画存在的空间占用问题,并提出转向使用骨骼数据来优化。通过ComputeShader提高运行效率,详细介绍了创建和使用ComputeShader的步骤,以及如何根据顶点数和动画帧数生成相应的RenderTexture。最后,展示了生成的动画数据并保存为资源。
摘要由CSDN通过智能技术生成

目前使用的方法有一个很大缺陷在于基于顶点生成的动画占用的空间很大,一个理想的情况是基于骨骼数据,本文权当抛砖引玉,后续有时间考虑尝试一下基于骨骼数据生成动画。

本文内容大量参考自白菊花瓣丶的视频,感谢!

生成动画数据需要用到ComputeShader来提高运行的效率,首先在Resources下创建这样一个compute shader,在这里我将其命名为"AnimVertices"。

#pragma kernel CSMain
RWTexture2D<float4> Result;
StructuredBuffer<float3> vertices;
int time;

[numthreads(8,1,1)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
    Result[uint2(id.x, time)]= float4(vertices[id.x], 1.0);
}

在前面的介绍里提到该方法对顶点和动画帧数有要求,是因为顶点和动画帧数实实在在的影响了生成的动画数据大小,首先使用顶点数作为宽,动画帧数作为高,可以确定所需的图片大小为顶点数*动画帧数*16,16是因为这里使用的颜色格式为ARGBHalf。

		int animLength = (int)(60 * animation.length);
		//animLength = Mathf.NextPowerOfTwo(animLength);
		int texwidth = mesh.sharedMesh.vertexCount;
		texwidth = Mathf.NextPowerOfTwo(texwidth);

		Texture2D tex = new Texture2D(texwidth, animLength, TextureFormat.RGBAHalf, false);
		RenderTexture rt = new RenderTexture(texwidth, animLength, 0, RenderTextureFormat.ARGBHalf);

动画帧数直接使用动画长度*运行帧数来获得,同时直接通过Mesh获取顶点数(Mathf.NextPowerOfTwo可以获得大于等于传入参数的2的幂的数,据说利于压缩,这里未做求证),格式使用ARGBHalf是因为顶点位置可正可负,实际使用中精度可能不足,可视情况调整。

		cs.SetTexture(0, "Result", rt);

		for (int i = 0; i < animLength; i++)
		{
			float time = i / 60f;
			animation.SampleAnimation(gameObject, time);
			Mesh bakeMesh = Instantiate<Mesh>(mesh.sharedMesh);
			mesh.BakeMesh(bakeMesh);
			Vector3[] vertices = bakeMesh.vertices;
			int size = sizeof(int) * 3;
			//Debug.LogError(i + " " + size + " " + time);
			ComputeBuffer cb = new ComputeBuffer(vertices.Length, 12);
			cb.SetData(vertices);
			cs.SetInt("time", i);
			cs.SetBuffer(0, "vertices", cb);
			cs.Dispatch(0, Mathf.CeilToInt(vertices.Length / 8.0f), 1, 1);
			cb.Release();
		}

创建render texture之后,赋值给到compute shader的Result属性,每帧动画就是图片数据里的一行,采样动画数据,烘焙获得Mesh之后,将烘焙后的顶点直接传入cs。

		RenderTexture.active = rt;
		tex.ReadPixels(new Rect(0, 0, texwidth, animLength), 0, 0);
		tex.Apply();
		AssetDatabase.CreateAsset(tex, $"Assets/Resources/{AnimTexName}.asset");

最后同样使用AssetDatabase.CreateAsset将动画数据保存下来,这里我们拿到如下的一个数据。 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值