unity-shader-GPU-Instancing

unity-shader-GPU-Instancing


前篇


提示

合批优先级

翻译自官网: 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
    65
    Shader "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.