GPU instancing

1, 概念:
    GPUInstasncing 是优化drawcall的方法,它可以在单独的drawcall中渲染多个具有相同材质的网格副本。每个网格的副本称为一个实例。这在一个场景中绘制出现多次的物体非常有用。    比如,树木或灌木。
    GPU instancing 在一个相同的Drawcall中渲染相同的网格。为了增加变化减少重复,每个示例可以有不同的属性,比如颜色或缩放。在frameDebugger中渲染多个实例的drawcall称为drawmesh.

2,平台限制
    除了WebGL 1.0外,GPUinstancing在每个平台都可用。
    Note:只有当Shader和SRPBatcher不兼容时:

3,SRP Batcher
    GPU instancing和SRPBatcher不兼容,SRP Batcher优先于GPU instancing。如果某个物体符合SRPBatcher的兼容条件,unity将使用SRPBatcher而非SRP Batcher来渲染它.    如果你的项目使用了SRPBatcher,而你针对某个物体使用GPU instancing,你可以按照下面的方法去做:
    1,使用Graphics.DrawMeshInstanced。这个API会绕过物体本身用的方式,并使用具体的参数直接在屏幕上绘制一个网格。
    2,手动去掉SRPBatcher的兼容。关于这个怎么做的信息,请参看Intentionally removeing compatibility.
    
4,使用 GPU instancing
    unity针对那些共享了相同网格和材质的物体使用GPU instancing.    下面举例说明这样的网格和材质:
    1,这个材质的Shader必须支持GPU instancing。unity的Standard Shader支持GPU instancing, 所有的suerface shader也一样。为了让任何其他Shader都添加GPU instancing的支持。
       参见Create Shaders that Support GPU instancing[后续加链接]
    2, 网格必须来自如下来源之一,通过行为分组:
        (1),通过meshrender或者Graphics.RenderMesh调用的。行为机制:unity会把这些mesh添加到一个列表然后检测符合实例化条件的对象。
            unity不支持GPU instancing的情况:
             SkinnedMeshRenderers
             已兼容SRPBather的物体上的MeshRenderer组件
        (2), 通过Graphics.RenderMeshInstanced或Graphics.RenderMeshIndirect方法调用的。这些方法对使用相同Shader的同一网格渲染了多次。每次对这些方法的调用都会产生独立的DrawCall。
            unity不会合并这些drawcall。
            
    针对一个材质使用GPU instancing,选择Enable GPU instancing来开启。

5,光照
    GPU instancing 支持unity的烘焙全局光照系统。unity Standard Shaders和Surface Shaders支持GPU instancing 并且默认支持unity的烘焙全局光照。
    每个GPU instancing 都支持下列来源之一的全局光照:
    1,任何数量的Light Probes
    2, 光照贴图
        Note:单个实例可以引用光照贴图的多个实例
    3,Light Probe Proxy Volume(LPPV)组件
        Note:必须为包含所有实例的空间体积烘焙LPPV
        
    GPU instancing自动兼容以下内容
    1,被light probe影响的动态Mesh Renderers
    2,static Mesh renderer 可被烘焙到同一张光照贴图上去。此文中提到的MeshRenderer是static 指的是在Static Editor flags中包含了Contribute GI 选项。如下图所示:


    
6,性能影响因素:
    那些有少量顶点的网格在使用GPU instancing时不是很有效果的。因为GPU不能以充分使用GPU资源的方式来分配工作。这种低效的处理方式可能对性能有不利影响。低效开始的阈值取决于GPU。
    一般来说,对于顶点数少于256的网格来说就不使用GPU instancing了。
    如果你想多次渲染一个低顶点数的网格,最好的做法是创建一个包含所有网格信息的缓冲区,并使用它来绘制网格。

### Unity 中 GPU Instancing 使用教程 #### 启用材质上的 GPU Instancing 支持 为了使材质支持 GPU Instancing,需在 Shader 文件中添加特定的宏定义。这可以通过编辑现有的着色器来完成: ```csharp #pragma surface surf Standard addshadow fullforwardshadows #pragma multi_compile_instancing ``` 这段代码中的 `#pragma multi_compile_instancing` 声明告诉编译器该材质应该支持实例化渲染[^4]。 #### 设置模型和材质 对于要应用 GPU Instancing 的 GameObjects,确保它们使用的是启用了此功能的材质。此外,这些对象应当拥有相同的 Mesh 和 Material,以便能够被有效地批量处理。如果需要为不同的实例提供独特的外观,则可通过设置每个实例的颜色或其他可变参数来实现这一点[^3]。 #### 编写脚本来管理实例数据 下面是一个简单的 C# 脚本例子,展示了如何在一个场景内创建多个带有不同变换属性的游戏对象,并将它们作为单一批次传递给 GPU 进行渲染: ```csharp using UnityEngine; public class GPUIstancingExample : MonoBehaviour { public Transform prefab; // 需要实例化的预制件 private Matrix4x4[] matrices = new Matrix4x4[10]; void Start() { for (int i = 0; i < matrices.Length; ++i) { Vector3 position = Random.insideUnitSphere * 5f; Quaternion rotation = Random.rotationUniform; matrices[i] = Matrix4x4.TRS(position, rotation, Vector3.one); } Graphics.DrawMeshInstanced(prefab.GetComponent<MeshFilter>().sharedMesh, matrices, prefab.GetComponent<Renderer>().material, 0); } } ``` 上述代码片段实现了如下操作:首先初始化了一个大小固定的数组用于存储各个实例的世界空间转换矩阵;接着循环填充这个数组,其中每一项代表一个新生成游戏对象的位置、方向以及尺度信息;最后调用 `Graphics.DrawMeshInstanced()` 方法一次性提交所有实例的数据至图形管线执行渲染命令[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小李也疯狂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值