GPU Instancing的定义
- 一种Draw call的优化方案,使用一个Draw call就能渲染具有多个相同材质的网格对象。而这些网格的每个copy称为一个实例(Instancing)。此技术在一个场景中对于需要绘制多个相同对象来说是一个行之有效办法,例如树木 灌木丛 或者大量 重复性物体。
Unity中的表现:
- GPU Instancing 在同一个Draw call中渲染完全相同的网格。可以通过添加变量来减少重复的外观,每个实例可以具有不同的属性,例如颜色或缩放。在Frame Debugger中如有Draw calls显示多个实例时会显示 Darw Mesh(Instanced)。
注意问题
- 在SRP Batcher下 非要在SRP下使用GPU instance的话那可以使用Graphics.DrawMeshInstanced,用C#代码中绘制出网格体。
- SkinedMeshRender不直接支持GPU Instance技术,仅支持MeshRender。如果希望支持SkinedMeshRender可以使用官方的一项方案Animator Instancing。GitHub - Unity-Technologies/Animation-Instancing: This technique is designed to instance Characters(SkinnedMeshRender).This technique is designed to instance Characters(SkinnedMeshRender). - GitHub - Unity-Technologies/Animation-Instancing: This technique is designed to instance Characters(SkinnedMeshRender).
https://github.com/Unity-Technologies/Animation-Instancing - GPU Instancing可以受光照影响,也可以支持光照烘培。
如何在自定义Shader中使用GPU Instancing
Shader "Unlit/MyGPUInstance"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
//第一步: sharder 增加变体使用shader可以支持instance
#pragma multi_compile_instancing
#pragma vertex vert
#pragma fragment frag
// make fog work
#pragma multi_compile_fog
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
//第二步:instancID 加入顶点着色器输入结构
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f
{
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION;
//第三步:instancID加入顶点着色器输出结构
UNITY_VERTEX_INPUT_INSTANCE_ID
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert (appdata v)
{
v2f o;
//第四步:instanceid在顶点的相关设置
UNITY_SETUP_INSTANCE_ID(v);
//第五步:传递 instanceid 顶点到片元
UNITY_TRANSFER_INSTANCE_ID(v, o);
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
//第六步:instanceid在片元的相关设置
UNITY_SETUP_INSTANCE_ID(i);
// sample the texture
fixed4 col = tex2D(_MainTex, i.uv);
// apply fog
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
ENDCG
}
}
}
其他的一些问题:
- URP渲染管线中,会发现GPU Instancing没有生效,原因是UPR默认开启SRP Batch,你可以选择关闭它。
- 如果已经GPU Instancing的物体 需要修改实例的一些属性,需要使用MaterialPropertyBlock,也就是通过C#代码来控制,这样可以不破坏GPU Instancing
- 如上所说,SRP Bacth和GUP Instancing 在URP中只能支持其中一个而SRP Batcher优先级最高,对于写草和树的Shader,比较建议直接支持GPU Instancing,而不支持SRP Batcher, 在移动端上效率相对SRP Batcher更好。