unity Gpu Instance

参考网址:
https://blog.csdn.net/leonwei/article/details/73274808
https://docs.unity3d.com/ScriptReference/Graphics.DrawMeshInstanced.html
https://docs.unity3d.com/ScriptReference/Graphics.DrawMeshInstancedIndirect.html
https://www.cnblogs.com/hont/p/7143626.html

draw the same mesh multiple times using GPU instancing.
similar to Graphics.DrawMesh, this function draws meshes for one frame without the overhead of creating unnecessary game objects.

use this function in situations where u want to draw the same mesh for a particular amount of times using an instanced shader. meshes are not further culled by the view frustum or baked occluders, nor sorted for transparency or z efficiency.

The transformation matrix of each instance of the mesh should be packed into the matrices array. You can specify the number of instances to draw, or by default it is the length of the matrices array. Other per-instance data, if required by the shader, should be provided by creating arrays on the MaterialPropertyBlock argument using SetFloatArray, SetVectorArray and SetMatrixArray.

To render the instances with light probes, provide the light probe data via the MaterialPropertyBlock and specify lightProbeUsage with LightProbeUsage.CustomProvided. Check LightProbes.CalculateInterpolatedLightAndOcclusionProbes for the details.

Note: You can only draw a maximum of 1023 instances at once.

InvalidOperationException will be thrown if the material doesn’t have Material.enableInstancing set to true, or the current platform doesn’t support this API (i.e. if GPU instancing is not available). See SystemInfo.supportsInstancing.

以下抄写自:https://docs.unity3d.com/ScriptReference/Graphics.DrawMeshInstancedIndirect.html
Description

Draw the same mesh multiple times using GPU instancing.
similar to Graphics.DrawMeshInstanced, this function draws many instances of the same mesh, but unlike that method, the arguments for how many instances to draw come from bufferWithArgs.

use this function in situations where u want to draw the same mesh for a particular amount of times using an instanced shader. meshes are not further culled by the view frustum or baked occluders, nor sorted for transparency or z efficiency.

buffer with arguments, bufferWithArgs, has to have five integer numbers at given argsOffset offset: index count per instance, instance count, start index location, base vertex location, start instance location.

unity only needs the submeshIndex argument if submeshes within the mesh have different topologies (e.g. Triangles and lines). otherwise, all the information about which submesh to draw comes from the bufferWithArgs argument.

Here is a script that can be used to draw many instances of the same mesh:

using UnityEngine;
using System.Collections;

public class GPUInstanceDemo : MonoBehaviour
{
    public int instanceCount = 5;
    public Mesh instanceMesh;
    public Material instanceMaterial;
    private int subMeshIndex = 0;
    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()
    {
        Graphics.DrawMeshInstancedIndirect(instanceMesh, subMeshIndex, instanceMaterial, new Bounds(Vector3.zero, new Vector3(100,100,100)), argsBuffer);
    }

    void UpdateBuffers()
    {
        if (positionBuffer != null)
            positionBuffer.Release();
        positionBuffer = new ComputeBuffer(instanceCount, 16);
        Vector4[] positions = new Vector4[instanceCount];
        for (int i = 0; i < instanceCount; i++)
        {
            float x = Random.Range(-5, 5);
            float y = Random.Range(-5, 5);
            float z = Random.Range(-5, 5);
            positions[i] = new Vector4(x, y, z);
        }
        positionBuffer.SetData(positions);
        instanceMaterial.SetBuffer("positionBuffer", positionBuffer);
    }

    void OnDisable()
    {
        if (positionBuffer != null)
            positionBuffer.Release();
        positionBuffer = null;

        if (argsBuffer != null)
            argsBuffer.Release();
        argsBuffer = null;
    }
}

shader代码:

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Instanced/InstancedShader" 
{
	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"


			#if SHADER_TARGET >= 45
			StructuredBuffer<float4> positionBuffer;
			#endif

			struct v2f
			{
				float4 pos : SV_POSITION;
			};

			v2f vert(appdata_full v, uint instanceID : SV_InstanceID)
			{
				#if SHADER_TARGET >= 45
				float4 data = positionBuffer[instanceID];
				#else
				float4 data = 0;
				#endif
				v2f o;
				v.vertex += data;
				o.pos = UnityObjectToClipPos(v.vertex);
				return o;
			}

			fixed4 frag(v2f i) : SV_Target
			{
				  #if SHADER_TARGET >= 45
					fixed4 data = fixed4(1,1,0,1);
				#else
					fixed4 data = fixed4(1, 0, 0, 1);
				#endif
					return data;
			}
			ENDCG
		}
	}
}

实现效果:
在这里插入图片描述
完整的案例,见官网。
但是有一个问题:
Graphics.DrawMeshInstancedIndirect(instanceMesh, subMeshIndex, instanceMaterial, new Bounds(Vector3.zero, new Vector3(100,100,100)), argsBuffer);
最后的两个参数不知道啥意思,待续……

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值