unity GPU Instance的初步使用

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);
        }
    }
}

下面是运行效果


be2d987219f46e1f349480c0106d7520.png
de16b4041825011364141ccf436c7b4e.png

可以看到场景中出现了几千个物体 并且左侧是没有实例话的组件的,等于直接通过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));
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容