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

RayTracingAccelerationStructure.AddInstancesIndirect

Declaration

public int AddInstancesIndirect(ref Rendering.RayTracingMeshInstanceConfig config, GraphicsBuffer instanceMatrices, int maxInstanceCount, GraphicsBuffer argsBuffer, uint argsOffset = 0, uint id);
public int AddInstancesIndirect(ref Rendering.RayTracingGeometryInstanceConfig config, GraphicsBuffer instanceMatrices, int maxInstanceCount, GraphicsBuffer argsBuffer, uint argsOffset = 0, uint id);

Параметры

Параметр Описание
конфигурация Общие параметры, используемые этими экземплярами трассировки лучей.
instanceMatrices GraphicsBuffer для содержащих матрицы преобразований.
maxInstanceCount Максимальное число экземпляров лучевых трассировок, добавляемых в структуру ускорения.
argsBuffer GraphicsBuffer, содержащий 2 целых значения на байтовом смещении argsOffset: стартовый экземпляр и количество экземпляров.
argsOffset Смещение в байтах в argsBuffer, где хранятся косвенные аргументы.
Идентификатор Необязательное значение экземпляра ID, которое можно получить в HLSL с помощью функции InstanceID(). Unity назначает последовательный экземпляр IDs каждому экземпляру сетки, начиная со значения id.

Возвращаемое значение

инт Значение, представляющее обработчик, который можно использовать для выполнения последующих действий (e.g. RemoveInstance), или 0, если экземпляры не добавлены успешно.

Описание

Добавляет массив экземпляров трассирования лучей в структуру ускорения, где матрицы экземпляров заданы с помощью GraphicsBuffer.

config аргумент function определяет соответствующую геометрию источника и соответствующие параметры для всех экземпляров трассирования лучей. Геометрия источника может быть определена либо с помощью Mesh или GraphicsBuffers, содержащий данные вершины и индекса.

Матрицы преобразования мира для экземпляров трассирования лучей указываются с помощью аргумента функции instanceMatrices. Поддерживаются только матрицы с плавающей запятой 4x4, где элементы хранятся с использованием расположения колонок (то же, что и расположение Matrix4x4). Буфер должен быть создан с помощью GraphicsBuffer.Target.Structured или GraphicsBuffer.Target.Append Вы можете указать содержимое буфера, просто вызвав instanceMatrices.SetData(Matrix4x4[]), или использовать более сложный алгоритм, где матричный буфер заполняется в вычислительном шейдере в конвейере отображения, управляемом GPU, например.

maxInstanceCount аргумент необходим для того, чтобы Unity мог выделить GPU памяти для структуры ускорения (TLAS), используемой для трассирования лучей. Окончательное количество действительных экземпляров трассирования лучей, добавленных в структуру ускорения, зависит как от maxInstanceCount значение и argsBuffer значения (начальный экземпляр и количество экземпляров). Добавлением экземпляров занимается внутренний вычислительный шейдер, который запускается по одному разу на каждый AddInstanceIndirect вызов при построении структуры ускорения.

Когда AddInstancesIndirect используется, Unity включает INSTANCING_ON Для объявления ключевого слова shader в HLSL добавьте строку #pragma multi_compile _ INSTANCING_ON в проходе шейдера, указанном в RayTracingShader.SetShaderPass или CommandBuffer.SetRayTracingShaderPass. Чтобы получить доступ к данным по экземплярам, относящимся к этому массиву экземпляров лучевой трассировки, используйте InstanceIndex() - unity_BaseInstanceID для создания нулевого индекса экземпляра в шейдерах.

После добавления всех требуемых экземпляров используйте RayTracingAccelerationStructure.Build или CommandBuffer.BuildRayTracingAccelerationStructure построить структуру ускорения на GPU.

Эта функциональность не имеет каких-либо особых требований к оборудованию в дополнение к требованиям поддержки трассирования лучей (SystemInfo.supportsRayTracing В DirectX Raytracing (DXR) эта функция заставляет все экземпляры Raytracing в массиве использовать только одну запись шейдера из таблицы шейдеров, что снижает нагрузку CPU на поток рендеринга для связывания ресурсов GPU с шейдерами.

Этот метод возвращает обработчик одного экземпляра, который можно использовать позже для выполнения действий, влияющих на все экземпляры трассировки лучей, добавленные с помощью этого метода.

Дополнительные ресурсы: RayTracingAccelerationStructure.RemoveInstance, RayTracingAccelerationStructure.Build, GraphicsBuffer.CopyCount.

Declaration

public int AddInstancesIndirect(ref Rendering.RayTracingMultiGeometryInstanceConfig config, GraphicsBuffer instanceData, GraphicsBuffer instanceIndices, int maxInstanceCount, GraphicsBuffer argsBuffer, uint argsOffset = 0, uint id);
public int AddInstancesIndirect(ref Rendering.RayTracingMultiGeometryInstanceConfig config, GraphicsBuffer instanceData, Type instanceType, GraphicsBuffer instanceIndices, int maxInstanceCount, GraphicsBuffer argsBuffer, uint argsOffset = 0, uint id);

Параметры

Параметр Описание
конфигурация Общие параметры, используемые этими экземплярами трассировки лучей.
instanceData GraphicsBuffer для хранения данных пользовательского экземпляра.
instanceType Тип, определяемый в скриптах для описания формата данных экземпляра.
instanceIndices Необязательный GraphicsBuffer, который содержит индексы экземпляров трассирования лучей из instanceData для добавления в структуру ускорения.
maxInstanceCount Максимальное число экземпляров лучевых трассировок, добавляемых в структуру ускорения.
argsBuffer GraphicsBuffer, содержащий 2 целых значения на байтовом смещении argsOffset: стартовый экземпляр и количество экземпляров.
argsOffset Смещение в байтах в argsBuffer, где хранятся косвенные аргументы.
Идентификатор Необязательное значение экземпляра ID, которое можно получить в HLSL с помощью функции InstanceID(). Unity назначает последовательный экземпляр IDs каждому экземпляру сетки, начиная со значения id.

Возвращаемое значение

инт Значение, представляющее обработчик, который можно использовать для выполнения последующих действий (e.g. RemoveInstance), или 0, если экземпляры не добавлены успешно.

Описание

Добавляет массив экземпляров трассирования лучей в структуру ускорения, где каждый экземпляр может иметь различную матрицу преобразования, геометрию и материал.

config аргумент function определяет геометрии, материалы и другие общие параметры для всех экземпляров трассирования лучей. Исходные геометрии могут быть определены с помощью GraphicsBuffers, содержащего вершины и индексные данные. Используйте config.subGeometries массив, чтобы указать, где каждая геометрия начинается и заканчивается в буферах вершин и индексов. Вы можете легко использовать Mesh данных с помощью этого метода, вызвав методы геттера из Mesh класс, чтобы получить вершинный и индексный буферы и связанные с ними данные. Используйте config.materials массив для хранения материалов, которые будут использоваться экземплярами трассирования лучей.

instanceData Каждый экземпляр должен содержать следующие обязательные данные: матрицу преобразования экземпляра, индекс в config.subGeometries для указания используемой геометрии и индекса в config.materials Матрица преобразования должна быть матрицей с плавающей запятой 4x4, в которой элементы хранятся с использованием расположения столбцов (то же самое, что и расположение Matrix4x4). Геометрия и индексы материалов представлены с использованием целых значений. Если значения находятся вне их соответствующего действительного диапазона, Unity зажимает значения до размера матрицы. config.subGeometries и config.materials соответственно.

Чтобы определить формат данных экземпляра, передайте определенную пользователем структуру либо как аргумент шаблона общего типа, либо с помощью instanceType аргумент, например, путем вызова AddInstancesIndirect<MyInstanceData> или эквивалентный, с использованием typeof(MyInstanceData) на 2000 год instanceType аргумент. Структура может иметь любое имя и формат, но она должна содержать следующие обязательные именованные поля: objectToWorld, geometryIndex и materialIndex. Unity вызывает исключение, если какое-либо из этих полей не присутствует в структуре, которую вы предоставляете.

instanceIndices буфер необязателен и должен быть создан с помощью GraphicsBuffer.Target.Structured или GraphicsBuffer.Target.Append При использовании функции instanceIndices буфер, значения в argsBuffer (startInstance и instanceCount) указывают индексы в этот буфер вместо instanceData Используйте буфер. GraphicsBuffer.Target.Append флаг, если вы добавляете индексы экземпляров из вычислительного шейдера в instanceIndices В этом случае, вызов CommandBuffer.CopyCounterValue или GraphicsBuffer.CopyCount чтобы скопировать окончательное число экземпляров из instanceIndices в argsBuffer. Таким образом, вы можете контролировать количество экземпляров, которые будут добавлены в структуру ускорения из вычислительного шейдера, например, путем удаления некоторых экземпляров.

maxInstanceCount аргумент необходим для того, чтобы Unity мог выделить GPU памяти для структуры ускорения (TLAS), используемой для трассирования лучей. Окончательное количество действительных экземпляров трассирования лучей, добавленных в структуру ускорения, зависит от maxInstanceCount значение, количество индексов в instanceIndices буфера, и argsBuffer значения (начальный экземпляр и количество экземпляров). Добавлением экземпляров занимается внутренний вычислительный шейдер, который запускается по одному разу на каждый AddInstancesIndirect вызов, когда структура ускорения построена на GPU.

Когда AddInstancesIndirect используется, Unity включает INSTANCING_ON Для объявления ключевого слова shader в HLSL добавьте строку #pragma multi_compile _ INSTANCING_ON в проходе шейдера, указанном в RayTracingShader.SetShaderPass или CommandBuffer.SetRayTracingShaderPass. Для доступа к данным по экземплярам относительно массива экземпляров трассирования лучей, добавленных с помощью одного AddInstancesIndirect вызов, использование InstanceIndex() - unity_BaseInstanceID для создания нулевого индекса экземпляра в шейдерах попаданий. Если требуется доступ к дополнительным данным по экземплярам в шейдере попаданий, используйте config.materialProperties для привязки данных.

См. GetMeshInfo HLSL функция от UnityRayTracingMeshUtils.cginc для получения дополнительной информации о том, как читать вершинные данные из config.vertexBuffer для каждой геометрии в данном графическом процессоре. config.subGeometries массив, Unity готовит MeshInfo вход во встроенную unity_MeshInfo_RT для каждой записи в структурированном буфере. config.vertexAttributes массив, Unity готовит VertexAttributeInfo вход во встроенную unity_MeshVertexDeclaration_RT структурированный буфер. MeshInfo и VertexAttributesInfo содержат базовую информацию для чтения вершин и индексов в шейдерах.

После добавления всех требуемых экземпляров используйте RayTracingAccelerationStructure.Build или CommandBuffer.BuildRayTracingAccelerationStructure построить структуру ускорения на GPU.

Эта функциональность не имеет каких-либо особых требований к оборудованию в дополнение к требованиям поддержки трассирования лучей (SystemInfo.supportsRayTracing В DirectX Raytracing (DXR), эта функция заставляет Unity установить одну запись шейдера для каждого Материала, предоставленного в файле config.materials массив, который снижает нагрузку CPU на поток рендеринга для связывания ресурсов GPU с шейдерами.

Этот метод возвращает обработчик одного экземпляра, который можно использовать позже для выполнения действий, влияющих на все экземпляры трассировки лучей, добавленные с помощью этого метода.

Дополнительные ресурсы: RayTracingAccelerationStructure.RemoveInstance, RayTracingAccelerationStructure.Build, Mesh.GetVertexBuffer, Mesh.GetIndexBuffer, Mesh.GetVertexAttributes.

using System.Collections.Generic;
using System.Runtime.InteropServices;
using Unity.Collections;
using UnityEngine;
using UnityEngine.Rendering;

[ExecuteInEditMode] public class MeshInstancing : MonoBehaviour { [SerializeField] RayTracingShader rayTracingShader;

[SerializeField] Material material1; [SerializeField] Material material2;

private uint cameraWidth = 0; private uint cameraHeight = 0;

private int instanceRows = 100; private int instanceColumns = 100;

private RenderTexture rayTracingOutput;

private RayTracingAccelerationStructure rtas;

private GraphicsBuffer vertexBuffer; private GraphicsBuffer indexBuffer; private GraphicsBuffer instanceDataBuffer; private GraphicsBuffer indirectArgsBuffer;

private void ReleaseResources() { cameraWidth = 0; cameraHeight = 0;

if (rtas != null) rtas.Release();

if (rayTracingOutput != null) rayTracingOutput.Release();

if (vertexBuffer != null) vertexBuffer.Release();

if (indexBuffer != null) indexBuffer.Release();

if (instanceDataBuffer != null) instanceDataBuffer.Release();

if (indirectArgsBuffer != null) indirectArgsBuffer.Release();

rtas = null; rayTracingOutput = null; vertexBuffer = null; indexBuffer = null; instanceDataBuffer = null; indirectArgsBuffer = null; }

struct Vertex { public Vertex(Vector3 pos, Vector3 n) { position = pos; normal = n; } public Vector3 position; public Vector3 normal; }

// objectToWorld, materialIndex, and geometryIndex fields are mandatory. public struct RayTracingPerInstanceData { public Matrix4x4 objectToWorld; public int data1; public uint materialIndex; public uint geometryIndex; public float data2; public Vector4 data3; };

private void CreateResources() { if (rtas == null) { RayTracingAccelerationStructure.Settings settings = new RayTracingAccelerationStructure.Settings { managementMode = RayTracingAccelerationStructure.ManagementMode.Manual, rayTracingModeMask = RayTracingAccelerationStructure.RayTracingModeMask.Everything, layerMask = -1, buildFlagsStaticGeometries = RayTracingAccelerationStructureBuildFlags.PreferFastTrace | RayTracingAccelerationStructureBuildFlags.MinimizeMemory, enableCompaction = true }; rtas = new RayTracingAccelerationStructure(settings); }

if (cameraWidth != Camera.main.pixelWidth || cameraHeight != Camera.main.pixelHeight) { if (rayTracingOutput != null) rayTracingOutput.Release();

rayTracingOutput = new RenderTexture(Camera.main.pixelWidth, Camera.main.pixelHeight, 0, RenderTextureFormat.ARGBHalf); rayTracingOutput.enableRandomWrite = true; rayTracingOutput.Create();

cameraWidth = (uint)Camera.main.pixelWidth; cameraHeight = (uint)Camera.main.pixelHeight; }

// The vertex and index buffers for the source geometry will be specified in RayTracingMultiGeometryInstanceConfig.vertexBuffer and indexBuffer. // Setup a vertex buffer that contains a quad and a triangle. The vertex contains the position and the normal. if (vertexBuffer == null) { List<Vertex> vertices = new List<Vertex> { // Add a quad. new Vertex(new Vector3(1, 0, -1), new Vector3(0, 1, 0)), new Vertex(new Vector3(1, 0, 1), new Vector3(0, 1, 0)), new Vertex(new Vector3(-1, 0, 1), new Vector3(0, 1, 0)), new Vertex(new Vector3(-1, 0, -1), new Vector3(0, 1, 0)),

// Add a triangle. new Vertex(new Vector3(1, 0, 0), new Vector3(0, 0, 1)), new Vertex(new Vector3(-1, 0, 0), new Vector3(0, 0, 1)), new Vertex(new Vector3(0, 3, 0), new Vector3(0, 0, 1)), };

vertexBuffer = new GraphicsBuffer(GraphicsBuffer.Target.Raw | GraphicsBuffer.Target.Vertex, vertices.Count, Marshal.SizeOf(typeof(Vertex))); vertexBuffer.SetData(vertices); }

// The geometry sub-ranges will be specified in RayTracingMultiGeometryInstanceConfig.subGeometries. if (indexBuffer == null) { List<uint> indices = new List<uint>() { // 2 triangles for the quad. 0, 1, 2, 0, 2, 3,

// 1 triangle. 4, 5, 6, };

indexBuffer = new GraphicsBuffer(GraphicsBuffer.Target.Raw | GraphicsBuffer.Target.Index, indices.Count, sizeof(uint)); indexBuffer.SetData(indices); }

if (instanceDataBuffer == null) { int instanceCount = instanceRows * instanceColumns;

// Generate a list of transformation matrices. NativeArray<Matrix4x4> matrices = new NativeArray<Matrix4x4>(instanceCount, Allocator.Temp);

int index = 0;

Matrix4x4 m = Matrix4x4.identity;

float angle = 0;

// Arrange the instances into a matrix. for (int row = 0; row < instanceRows; row++) { float z = row + 0.5f - instanceRows * 0.5f;

for (int column = 0; column < instanceColumns; column++) { float x = column + 0.5f - instanceColumns * 0.5f;

angle += 10.0f;

Quaternion rotation = Quaternion.Euler(0, angle, 0);

m.SetTRS(new Vector3(5.5f * x, 4.001f, 5.5f * z), rotation, new Vector3(2, 2, 2));

matrices[index] = m;

index++; } }

instanceDataBuffer = new GraphicsBuffer(GraphicsBuffer.Target.Raw, instanceCount, Marshal.SizeOf(typeof(RayTracingPerInstanceData)));

RayTracingPerInstanceData[] perInstanceData = new RayTracingPerInstanceData[instanceCount];

Random.InitState(12345);

for (int i = 0; i < instanceCount; i++) { perInstanceData[i] = new RayTracingPerInstanceData { // Assign a random geometry and material to each instance. objectToWorld = matrices[i], materialIndex = (uint)Random.Range(0, 2), geometryIndex = (uint)Random.Range(0, 2), data1 = i, data2 = 3.14f, data3 = new Vector4(1, 2, 3, 4), }; }

instanceDataBuffer.SetData(perInstanceData); }

if (indirectArgsBuffer == null) { indirectArgsBuffer = new GraphicsBuffer(GraphicsBuffer.Target.Raw, 1, 2 * sizeof(int)); int[] ints = new int[2] { 0, // instanceStart instanceRows * instanceColumns // instanceCount };

indirectArgsBuffer.SetData(ints); } }

void OnDestroy() { ReleaseResources(); }

void OnDisable() { ReleaseResources(); }

[ImageEffectOpaque] void OnRenderImage(RenderTexture src, RenderTexture dest) { if (SystemInfo.supportsRayTracing == false) { Debug.Log("The Ray Tracing API is not supported by this GPU or by the current graphics API."); Graphics.Blit(src, dest); return; }

if (rayTracingShader == null) { Debug.Log("Please set the RayTracingShader."); Graphics.Blit(src, dest); return; }

CreateResources();

rtas.ClearInstances();

CommandBuffer cmdBuffer = new CommandBuffer();

Material[] materials = new Material[2]; materials[0] = material1; materials[1] = material2;

VertexAttributeDescriptor[] vertexDescs = new VertexAttributeDescriptor[2]; vertexDescs[0] = new VertexAttributeDescriptor(VertexAttribute.Position, VertexAttributeFormat.Float32, 3, 0); vertexDescs[1] = new VertexAttributeDescriptor(VertexAttribute.Normal, VertexAttributeFormat.Float32, 3, 0);

RayTracingMultiGeometryInstanceConfig instances = new RayTracingMultiGeometryInstanceConfig();

instances.vertexBuffer = vertexBuffer; instances.vertexAttributes = vertexDescs; instances.indexBuffer = indexBuffer; instances.materials = materials; instances.rayTracingMode = UnityEngine.Experimental.Rendering.RayTracingMode.Static;

// Configure the 2 geometries. // The geometries in this example are considered opaque. When cutout materials are used (for example foliage), use RayTracingSubMeshFlags.Enabled flag alone to enable any hit shaders. instances.subGeometries = new RayTracingSubGeometryDesc[2] { // The quad. new RayTracingSubGeometryDesc { indexStart = 0, indexCount = 2 * 3, flags = RayTracingSubMeshFlags.Enabled | RayTracingSubMeshFlags.ClosestHitOnly },

// The triangle is right after the quad in the vertex buffer. new RayTracingSubGeometryDesc() { indexStart = 2 * 3, indexCount = 3, flags = RayTracingSubMeshFlags.Enabled | RayTracingSubMeshFlags.ClosestHitOnly } };

// Not using instance indices in this example. // We add all the instances from instanceDataBuffer. rtas.AddInstancesIndirect<RayTracingPerInstanceData>(instances, instanceDataBuffer, null, -1, indirectArgsBuffer, 0);

cmdBuffer.BuildRayTracingAccelerationStructure(rtas);

cmdBuffer.SetRayTracingShaderPass(rayTracingShader, "Test");

// Input cmdBuffer.SetRayTracingAccelerationStructure(rayTracingShader, Shader.PropertyToID("g_AccelStruct"), rtas); cmdBuffer.SetRayTracingFloatParam(rayTracingShader, Shader.PropertyToID("g_Zoom"), Mathf.Tan(Mathf.Deg2Rad * Camera.main.fieldOfView * 0.5f));

// Output cmdBuffer.SetRayTracingTextureParam(rayTracingShader, Shader.PropertyToID("g_Output"), rayTracingOutput);

cmdBuffer.DispatchRays(rayTracingShader, "MainRayGenShader", cameraWidth, cameraHeight, 1);

Graphics.ExecuteCommandBuffer(cmdBuffer);

cmdBuffer.Release();

Graphics.Blit(rayTracingOutput, dest); } }

Скрипт в этом примере вызывает AddInstancesIndirect<T> для добавления ряда экземпляров трассирования лучей с использованием случайных геометрий и материалов к структуре ускорения.