Unity 6.3
0 онлайн 34 гостей 3 в системе
Вход

Graphics.RenderPrimitivesIndirect

Declaration

public static void RenderPrimitivesIndirect(ref RenderParams rparams, MeshTopology topology, GraphicsBuffer argsBuffer, int commandCount = 1, int startCommand = 0);

Параметры

Параметр Описание
рпарам Параметры, используемые Unity для отображения примитивов.
топология Примитивная топология (например, треугольники или линии).
argsBuffer Графический буфер, предоставляющий аргументы команды рендеринга (см. IndirectDrawArgs).
commandCount Количество команд рендеринга, которые будут выполнены в argsBuffer.
startCommand Первая команда для выполнения в argsBuffer.

Описание

Отображает примитивы с GPU экземпляром и пользовательским шейдером, используя аргументы команды отображения из argsBuffer.

Эта функция обеспечивает способ контроля аргументов команды отображения из GPU для отображения заданного количества примитивов и экземпляров. Используйте RenderParams.worldBounds определить границы для сортировки и сортировки геометрии, отображаемой с помощью метода, как единого объекта.

Эта функция работает только на платформах, которые поддерживают вычисление шейдеров.

Добавить следующие строки в раздел pass для доступа к команде, экземпляру и вершине IDкак указано в UnityIndirect.cgincДополнительные ресурсы: RenderMeshIndirect.

#define UNITY_INDIRECT_DRAW_ARGS IndirectDrawArgs
#include "UnityIndirect.cginc"

Для настройки функций доступа ID в начале функции шейдера добавьте следующую строку:

InitIndirectDrawArgs(0);

В следующем примере выполняются две команды косвенного рендеринга. Каждая команда рендеринга выполняет 10 экземпляров Mesh. Соответствующий Материал должен использовать следующий пользовательский шейдер:

using UnityEngine;

public class ExampleClass : MonoBehaviour { public Material material; public Mesh mesh;

GraphicsBuffer meshTriangles; GraphicsBuffer meshPositions; GraphicsBuffer commandBuf; GraphicsBuffer.IndirectDrawArgs[] commandData; const int commandCount = 2;

void Start() { // note: remember to check "Read/Write" on the mesh asset to get access to the geometry data meshTriangles = new GraphicsBuffer(GraphicsBuffer.Target.Structured, mesh.triangles.Length, sizeof(int)); meshTriangles.SetData(mesh.triangles); meshPositions = new GraphicsBuffer(GraphicsBuffer.Target.Structured, mesh.vertices.Length, 3 * sizeof(float)); meshPositions.SetData(mesh.vertices); commandBuf = new GraphicsBuffer(GraphicsBuffer.Target.IndirectArguments, commandCount, GraphicsBuffer.IndirectDrawArgs.size); commandData = new GraphicsBuffer.IndirectDrawArgs[commandCount]; }

void OnDestroy() { meshTriangles?.Dispose(); meshTriangles = null; meshPositions?.Dispose(); meshPositions = null; commandBuf?.Dispose(); commandBuf = null; }

void Update() { RenderParams rp = new RenderParams(material); rp.worldBounds = new Bounds(Vector3.zero, 10000*Vector3.one); // use tighter bounds rp.matProps = new MaterialPropertyBlock(); rp.matProps.SetBuffer("_Triangles", meshTriangles); rp.matProps.SetBuffer("_Positions", meshPositions); rp.matProps.SetInt("_BaseVertexIndex", (int)mesh.GetBaseVertex(0)); rp.matProps.SetMatrix("_ObjectToWorld", Matrix4x4.Translate(new Vector3(-4.5f, 0, 0))); commandData[0].vertexCountPerInstance = mesh.GetIndexCount(0); commandData[0].instanceCount = 10; commandData[1].vertexCountPerInstance = mesh.GetIndexCount(0); commandData[1].instanceCount = 10; commandBuf.SetData(commandData); Graphics.RenderPrimitivesIndirect(rp, MeshTopology.Triangles, commandBuf, commandCount); } }

Используйте следующий пример шейдера с приведенным выше примером кода C#:

          Shader "ExampleShader"
{
    SubShader
    {
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

#include "UnityCG.cginc" #define UNITY_INDIRECT_DRAW_ARGS IndirectDrawArgs #include "UnityIndirect.cginc"

struct v2f { float4 pos : SV_POSITION; float4 color : COLOR0; };

StructuredBuffer<int> _Triangles; StructuredBuffer<float3> _Positions; uniform uint _BaseVertexIndex; uniform float4x4 _ObjectToWorld;

v2f vert(uint svVertexID: SV_VertexID, uint svInstanceID : SV_InstanceID) { InitIndirectDrawArgs(0); v2f o; uint cmdID = GetCommandID(0); uint instanceID = GetIndirectInstanceID(svInstanceID); float3 pos = _Positions[_Triangles[GetIndirectVertexID(svVertexID)] + _BaseVertexIndex]; float4 wpos = mul(_ObjectToWorld, float4(pos + float3(instanceID, cmdID, 0.0f), 1.0f)); o.pos = mul(UNITY_MATRIX_VP, wpos); o.color = float4(cmdID & 1 ? 0.0f : 1.0f, cmdID & 1 ? 1.0f : 0.0f, instanceID / float(GetIndirectInstanceCount()), 0.0f); return o; }

float4 frag(v2f i) : SV_Target { return i.color; } ENDCG } } }