1:GPU Instance介绍
GPU Instancing通过利用GPU的并行处理能力,允许在单个绘制调用中渲染多个相同的网格副本。每个副本可以具有不同的属性,如颜色或比例,以增加变化并减少外观上的重复,这种技术可以显著降低每个场景使用的绘制调用数量,从而提高渲染性能
2:GPU Instance使用的前提,适用的场景
1:相同材质、相同网格的物体,并且材质球的shader需要支持gpu instance 并且材质球需要开启enable gpu instance
2:实例化属性需通过固定通道(如 UNITY_INSTANCING_BUFFER_START)传递,复杂材质可能需额外处理,对动态批处理的物体数量有限制(通常受 GPU 缓冲区大小影响)
3:大量重复物体:如草地、树木这类的静态物体
3:Demeo实验
1:通过在场景中生成几千个cube来测试,mesh我们直接用unity自带的cubeMesh,把这个脚本放到场景节点下
using UnityEngine;
public class GPUInstancingExample : MonoBehaviour
{
public Mesh instanceMesh;
public Material instanceMaterial;
public int instanceCount = 1023 * 4;
public float radius = 50f;
private Matrix4x4[] matrices;
private Vector4[] colors;
private MaterialPropertyBlock mpb;
Mesh GetDefaultCubeMesh()
{
GameObject temp = GameObject.CreatePrimitive(PrimitiveType.Cube);
Mesh mesh = temp.GetComponent<MeshFilter>().sharedMesh;
GameObject.Destroy(temp);
return mesh;
}
void Start()
{
if (instanceMesh == null)
instanceMesh = GetDefaultCubeMesh();
matrices = new Matrix4x4[instanceCount];
colors = new Vector4[instanceCount];
mpb = new MaterialPropertyBlock();
for (int i = 0; i < instanceCount; i++)
{
Vector3 pos = Random.insideUnitSphere * radius;
Quaternion rot = Quaternion.Euler(0, Random.Range(0, 360), 0);
Vector3 scale = Vector3.one * Random.Range(0.5f, 1.5f);
matrices[i] = Matrix4x4.TRS(pos, rot, scale);
colors[i] = new Vector4(Random.value, Random.value, Random.value, 1f);
}
mpb.SetVectorArray("_Color", colors);
}
void Update()
{
int batchSize = 1023; // Unity单次DrawMeshInstanced最大数量
for (int i = 0; i < instanceCount; i += batchSize)
{
int batchCount = Mathf.Min(batchSize, instanceCount - i);
Graphics.DrawMeshInstanced(instanceMesh, 0, instanceMaterial,
new System.ArraySegment<Matrix4x4>(matrices, i, batchCount).Array, batchCount, mpb);
}
}
}
下面是运行效果


可以看到场景中出现了几千个物体 并且左侧是没有实例话的组件的,等于直接通过gpu画出来了,并且可以核批,Saved By Batching高达5000多,极大的节省了性能
4:拓展
1:从上面可以看到 直接通过gpu instance的物体 并没有实例出实际的物体在Hierarchy面板上
传统的物体我们是通过transform.postion对其进行移动
2:如果我们需要对物体进行移动应该怎么办,实际就是通过变换矩阵的位置来对其进行移动操作
假设你有一批物体的矩阵列表 Matrix4x4[] matrices,你想统一向右移动1个单位:
for (int i = 0; i < matrices.Length; i++)
{
Vector3 pos = matrices[i].GetColumn(3); // 获取位置(矩阵第4列)
pos += new Vector3(1, 0, 0); // 向右移动1单位
matrices[i].SetColumn(3, new Vector4(pos.x, pos.y, pos.z, 1));
}