unity-shader-GPU-Instancing
unity-shader-GPU-Instancing
前篇
- 官方资料
- GPU instancing - https://docs.unity3d.com/Manual/GPUInstancing.html
- U3D优化批处理-GPU Instancing了解一下 - https://zhuanlan.zhihu.com/p/34499251
- Unity中基于Gpu Instance进行大量物体渲染的实现与分析(一) - https://blog.csdn.net/leonwei/article/details/73274808
提示
合批优先级
翻译自官网: https://docs.unity3d.com/Manual/GPUInstancing.html
在合批的时候, static batching 优先于 instancing. 如果你把 go 标记成 static batching, unity 会成功的进行合批, 会禁止 instancing, 即使它使用了一个 instancing shader. 如果发生这种情况, inspector 窗口会有个 建议你禁止 static batching 的警告信息. 做法是打开 player settings (edit -> project settings -> player), 打开对应平台的 other settings, 展开 rendering, 取消勾选 static batching.
instancing 优先于 dynamic batching. 如果 unity 可以 instance 一个 mesh, 那么它会禁止 dynamic batching 那个 mesh.
合批的优先级是: static batching > instancing > dynamic batching.
编写 instancing shader
shader
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65Shader "test/GpuInstancing2"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Color ("Color", Color) = (1, 1, 1, 1)
_Intensity ("Intensity", float) = 1
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// INSTANCE 编译宏
#pragma multi_compile_instancing
#include "UnityCG.cginc"
struct appdata {
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f {
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
UNITY_VERTEX_INPUT_INSTANCE_ID // necessary only if you want to access instanced properties in fragment Shader.
};
sampler2D _MainTex;
float4 _MainTex_ST;
UNITY_INSTANCING_BUFFER_START(Props) // uniform 变量定义域, Props 参数可以是任意字符串
UNITY_DEFINE_INSTANCED_PROP(float4, _Color)
UNITY_DEFINE_INSTANCED_PROP(float, _Intensity)
UNITY_INSTANCING_BUFFER_END(Props)
v2f vert (appdata v) {
v2f o;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_TRANSFER_INSTANCE_ID(v, o); // necessary only if you want to access instanced properties in the fragment Shader.
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag (v2f i) : SV_Target {
UNITY_SETUP_INSTANCE_ID(i); // necessary only if any instanced properties are going to be accessed in the fragment Shader.
//访问每个 Instance 独有的属性. 这个宏会使用 Instance ID作为索引到 Uniform数组 中去取当前 Instance 对应的数据
float4 val = UNITY_ACCESS_INSTANCED_PROP(Props, _Color) * UNITY_ACCESS_INSTANCED_PROP(Props, _Intensity);
fixed4 col = tex2D(_MainTex, i.uv) * val;
return col;
}
ENDCG
}
}
}效果
测试打断顺序
因为 unity 渲染 不透明物体时, 渲染顺序是由远 ( 参考总结: graphic-前向渲染管线浅析.md 中的 深度测试提前:Early-Z技术)
因为绘制中间的两个物体时, 使用了不同的材质, 所以打断了 gpu instancing.