不使用MeshRenderer去绘制Mesh【翻译】

Table of Contents

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com

原文地址

在 Unity 中不使用 MeshRenderer 渲染网格

1. 概述

  • 目的:使用 DrawMesh 系列方法在 Unity 中渲染大量网格,而无需创建和管理 GameObject。
  • 特点
    • 网格会受到光照影响,可以投射和接收阴影。
    • 可以针对所有相机或特定相机渲染。
    • 支持 GPU 实例化和 Compute Shader。

2. 常用方法

  • DrawMesh:最简单的渲染方法,使用指定材质渲染网格。
  • DrawMeshInstanced:通过 GPU 实例化渲染大量相同网格,支持小规模变化(如颜色)。
  • DrawMeshInstancedIndirect:通过 ComputeBuffer 传递实例数量和位置等数据,适用于大规模实例化。
  • DrawMeshInstancedProcedural:与 DrawMeshInstancedIndirect 类似,但实例数量可以直接从 C# 传递。
  • DrawProcedural:在 GPU 上执行绘制调用,无需顶点或索引缓冲区,适用于 Compute Shader。
  • DrawProceduralIndirect:与 DrawProcedural 类似,但实例数量等数据从 ComputeBuffer 传递。

3. 代码示例

  • DrawMesh
    public class ExampleDrawMesh : MonoBehaviour
    {
        public Mesh mesh;
        public Material material;
    
        void Update()
        {
            Graphics.DrawMesh(mesh, Vector3.zero, Quaternion.identity, material, 0);
        }
    }
    
  • DrawMeshNow
    public class ExampleDrawMeshNow : MonoBehaviour
    {
        public Mesh mesh;
        public Material material;
    
        public void OnPostRender()
        {
            material.SetPass(0);
            Graphics.DrawMeshNow(mesh, Vector3.zero, Quaternion.identity);
        }
    }
    
  • DrawMeshInstanced
    public class ExampleDrawMeshInstanced : MonoBehaviour
    {
        public Mesh mesh;
        public Material material;
        Matrix4x4[] matrices;
    
        void OnEnable()
        {
            matrices = new Matrix4x4[10];
            for (int i = 0; i < 10; i++)
            {
                Vector3 position = new Vector3(0, 0, i);
                Quaternion rotation = Quaternion.identity;
                Vector3 scale = new Vector3(0.3f, 0.3f, 0.3f);
                matrices[i] = Matrix4x4.TRS(position, rotation, scale);
            }
        }
    
        void Update()
        {
            Graphics.DrawMeshInstanced(mesh, 0, material, matrices);
        }
    }
    
  • DrawMeshInstancedIndirect
    public class ExampleDrawMeshInstancedIndirect : MonoBehaviour
    {
        public Mesh mesh;
        public Material material;
        ComputeBuffer argsBuffer;
        ComputeBuffer matricesBuffer;
        Bounds bounds;
    
        void Start()
        {
            argsBuffer = new ComputeBuffer(1, 5 * sizeof(uint), ComputeBufferType.IndirectArguments);
            argsBuffer.SetData(new uint[] {
                (uint)mesh.GetIndexCount(0),
                (uint)instanceCount,
                (uint)mesh.GetIndexStart(0),
                (uint)mesh.GetBaseVertex(0),
                0
            });
    
            bounds = new Bounds(Vector3.zero, new Vector3(10.0f, 10.0f, 10.0f));
    
            Matrix4x4[] matrices = new Matrix4x4[instanceCount];
            for (int i = 0; i < instanceCount; i++) {
                Vector3 offset = new Vector3(i * 0.3f, Mathf.Sin(i / 3f), 0);
                matrices[i] = Matrix4x4.TRS(transform.position + offset, Quaternion.identity, new Vector3(0.3f, 0.3f, 0.3f));
            }
            matricesBuffer = new ComputeBuffer(instanceCount, sizeof(float) * 4 * 4);
            matricesBuffer.SetData(matrices);
            material.SetBuffer("matricesBuffer", matricesBuffer);
        }
    
        void Update()
        {
            Graphics.DrawMeshInstancedIndirect(mesh, 0, material, bounds, argsBuffer);
        }
    
        void OnDisable()
        {
            matricesBuffer?.Release();
            matricesBuffer = null;
    
            argsBuffer?.Release();
            argsBuffer = null;
        }
    }
    

4. 使用场景

  • 动态更新位置:在每帧更新网格位置,如波浪运动。
  • 复杂模拟:使用 Compute Shader 进行网格位置的复杂计算(如群体模拟)。
  • 大规模实例化:通过 DrawMeshInstancedIndirect 实现高效的大规模实例化渲染。

5. 文件下载

  • 包含内容
    • DrawMeshDrawMeshInstancedDrawMeshInstancedIndirect 的脚本。
    • 两个着色器(基础着色器和 PBR 表面着色器)。
    • 使用 Compute Shader 移动网格的示例。
    • 示例场景展示脚本使用方法。

总结

  • 核心方法DrawMesh 系列方法提供了灵活的网格渲染方式,支持 GPU 实例化和 Compute Shader。
  • 性能优化:通过 DrawMeshInstancedIndirect 和 Compute Shader,可以将计算任务卸载到 GPU,提升性能。
  • 适用场景:适用于大规模实例化、动态位置更新和复杂模拟的渲染需求。
kumakoko avatar
kumakoko
pure coder