| mesh | 要绘制的 Mesh。 | 
| submeshIndex | 要绘制网格的哪个子集。这只适用于由若干种材质构成的网格。 | 
| material | 要使用的 Material。 | 
| bounds | 围绕要绘制的实例的包围体。 | 
| bufferWithArgs | GPU 缓冲区包含相应的参数,指示要绘制此网格的实例数。 | 
| argsOffset | 缓冲区中的字节偏移,绘制参数起始位置。 | 
| properties | 要应用的其他材质属性。请参阅 MaterialPropertyBlock。 | 
| castShadows | 确定网格是否可以投射阴影。 | 
| receiveShadows | 确定网格是否可以接受阴影。 | 
| layer | 要使用的 Layer。 | 
| camera | If null (default), the mesh will be drawn in all cameras. Otherwise it will be drawn in the given Camera only. | 
                  
| lightProbeUsage | 实例的 LightProbeUsage。 | 
This function is now obsolete. Use Graphics.RenderMeshIndirect instead. Draws the same mesh multiple times using GPU instancing.
        This function only works on platforms that support compute shaders.
类似于 Graphics.DrawMeshInstanced,此函数用于绘制同一网格的多个实例,但与之不同的是,此函数中代表要绘制实例数的参数来自 /bufferWithArgs/。
如果您需要使用实例化的着色器多次绘制同一网格,则可以使用该函数。这些网格不会被视锥体或烘焙遮挡物做进一步的剔除处理,也不进行排序以提高透明度或 Z 效率。
带参数的缓冲区 bufferWithArgs 必须在给定的 argsOffset 偏移处具有五个整数:
每个实例的索引数、实例数、起始索引位置、基顶点位置、起始实例位置。
仅当网格中的子网格具有不同拓扑(例如,三角形和线条)时,Unity 才需要 submeshIndex 参数。否则,有关要绘制哪个子网格的所有信息都将来自 bufferWithArgs 参数。
下面是一个可用于绘制同一网格的多个实例的脚本:
      
using UnityEngine; using System.Collections;
public class ExampleClass : MonoBehaviour { public int instanceCount = 100000; public Mesh instanceMesh; public Material instanceMaterial; public int subMeshIndex = 0;
private int cachedInstanceCount = -1; private int cachedSubMeshIndex = -1; private ComputeBuffer positionBuffer; private ComputeBuffer argsBuffer; private uint[] args = new uint[5] { 0, 0, 0, 0, 0 };
void Start() { argsBuffer = new ComputeBuffer(1, args.Length * sizeof(uint), ComputeBufferType.IndirectArguments); UpdateBuffers(); }
void Update() { // Update starting position buffer if (cachedInstanceCount != instanceCount || cachedSubMeshIndex != subMeshIndex) UpdateBuffers();
// Pad input if (Input.GetAxisRaw("Horizontal") != 0.0f) instanceCount = (int)Mathf.Clamp(instanceCount + Input.GetAxis("Horizontal") * 40000, 1.0f, 5000000.0f);
// Render Graphics.DrawMeshInstancedIndirect(instanceMesh, subMeshIndex, instanceMaterial, new Bounds(Vector3.zero, new Vector3(100.0f, 100.0f, 100.0f)), argsBuffer); }
void OnGUI() { GUI.Label(new Rect(265, 25, 200, 30), "Instance Count: " + instanceCount.ToString()); instanceCount = (int)GUI.HorizontalSlider(new Rect(25, 20, 200, 30), (float)instanceCount, 1.0f, 5000000.0f); }
void UpdateBuffers() { // Ensure submesh index is in range if (instanceMesh != null) subMeshIndex = Mathf.Clamp(subMeshIndex, 0, instanceMesh.subMeshCount - 1);
// Positions if (positionBuffer != null) positionBuffer.Release(); positionBuffer = new ComputeBuffer(instanceCount, 16); Vector4[] positions = new Vector4[instanceCount]; for (int i = 0; i < instanceCount; i++) { float angle = Random.Range(0.0f, Mathf.PI * 2.0f); float distance = Random.Range(20.0f, 100.0f); float height = Random.Range(-2.0f, 2.0f); float size = Random.Range(0.05f, 0.25f); positions[i] = new Vector4(Mathf.Sin(angle) * distance, height, Mathf.Cos(angle) * distance, size); } positionBuffer.SetData(positions); instanceMaterial.SetBuffer("positionBuffer", positionBuffer);
// Indirect args if (instanceMesh != null) { args[0] = (uint)instanceMesh.GetIndexCount(subMeshIndex); args[1] = (uint)instanceCount; args[2] = (uint)instanceMesh.GetIndexStart(subMeshIndex); args[3] = (uint)instanceMesh.GetBaseVertex(subMeshIndex); } else { args[0] = args[1] = args[2] = args[3] = 0; } argsBuffer.SetData(args);
cachedInstanceCount = instanceCount; cachedSubMeshIndex = subMeshIndex; }
void OnDisable() { if (positionBuffer != null) positionBuffer.Release(); positionBuffer = null;
if (argsBuffer != null) argsBuffer.Release(); argsBuffer = null; } }
下面是一个表面着色器,可以与上面的示例脚本配合使用:
          Shader "Instanced/InstancedSurfaceShader" {
    Properties {
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _Glossiness ("Smoothness", Range(0,1)) = 0.5
        _Metallic ("Metallic", Range(0,1)) = 0.0
    }
    SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 200
        CGPROGRAM
        // Physically based Standard lighting model
        #pragma surface surf Standard addshadow fullforwardshadows
        #pragma multi_compile_instancing
        #pragma instancing_options procedural:setup
        sampler2D _MainTex;
        struct Input {
            float2 uv_MainTex;
        };
    #ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED
        StructuredBuffer<float4> positionBuffer;
    #endif
        void rotate2D(inout float2 v, float r)
        {
            float s, c;
            sincos(r, s, c);
            v = float2(v.x * c - v.y * s, v.x * s + v.y * c);
        }
        void setup()
        {
        #ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED
            float4 data = positionBuffer[unity_InstanceID];
            float rotation = data.w * data.w * _Time.y * 0.5f;
            rotate2D(data.xz, rotation);
            unity_ObjectToWorld._11_21_31_41 = float4(data.w, 0, 0, 0);
            unity_ObjectToWorld._12_22_32_42 = float4(0, data.w, 0, 0);
            unity_ObjectToWorld._13_23_33_43 = float4(0, 0, data.w, 0);
            unity_ObjectToWorld._14_24_34_44 = float4(data.xyz, 1);
            unity_WorldToObject = unity_ObjectToWorld;
            unity_WorldToObject._14_24_34 *= -1;
            unity_WorldToObject._11_22_33 = 1.0f / unity_WorldToObject._11_22_33;
        #endif
        }
        half _Glossiness;
        half _Metallic;
        void surf (Input IN, inout SurfaceOutputStandard o) {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
            o.Albedo = c.rgb;
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}
      下面是一个自定义着色器,可以与上面的示例脚本配合使用:
          Shader "Instanced/InstancedShader" {
    Properties {
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
    }
    SubShader {
        Pass {
            Tags {"LightMode"="ForwardBase"}
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_fwdbase nolightmap nodirlightmap nodynlightmap novertexlight
            #pragma target 4.5
            #include "UnityCG.cginc"
            #include "UnityLightingCommon.cginc"
            #include "AutoLight.cginc"
            sampler2D _MainTex;
        #if SHADER_TARGET >= 45
            StructuredBuffer<float4> positionBuffer;
        #endif
            struct v2f
            {
                float4 pos : SV_POSITION;
                float2 uv_MainTex : TEXCOORD0;
                float3 ambient : TEXCOORD1;
                float3 diffuse : TEXCOORD2;
                float3 color : TEXCOORD3;
                SHADOW_COORDS(4)
            };
            void rotate2D(inout float2 v, float r)
            {
                float s, c;
                sincos(r, s, c);
                v = float2(v.x * c - v.y * s, v.x * s + v.y * c);
            }
            v2f vert (appdata_full v, uint instanceID : SV_InstanceID)
            {
            #if SHADER_TARGET >= 45
                float4 data = positionBuffer[instanceID];
            #else
                float4 data = 0;
            #endif
                float rotation = data.w * data.w * _Time.x * 0.5f;
                rotate2D(data.xz, rotation);
                float3 localPosition = v.vertex.xyz * data.w;
                float3 worldPosition = data.xyz + localPosition;
                float3 worldNormal = v.normal;
                float3 ndotl = saturate(dot(worldNormal, _WorldSpaceLightPos0.xyz));
                float3 ambient = ShadeSH9(float4(worldNormal, 1.0f));
                float3 diffuse = (ndotl * _LightColor0.rgb);
                float3 color = v.color;
                v2f o;
                o.pos = mul(UNITY_MATRIX_VP, float4(worldPosition, 1.0f));
                o.uv_MainTex = v.texcoord;
                o.ambient = ambient;
                o.diffuse = diffuse;
                o.color = color;
                TRANSFER_SHADOW(o)
                return o;
            }
            fixed4 frag (v2f i) : SV_Target
            {
                fixed shadow = SHADOW_ATTENUATION(i);
                fixed4 albedo = tex2D(_MainTex, i.uv_MainTex);
                float3 lighting = i.diffuse * shadow + i.ambient;
                fixed4 output = fixed4(albedo.rgb * i.color * lighting, albedo.w);
                UNITY_APPLY_FOG(i.fogCoord, output);
                return output;
            }
            ENDCG
        }
    }
}