Version: Unity 6.0 (6000.0)
LanguageEnglish
  • C#

CommandBuffer.BuildRayTracingAccelerationStructure

Suggest a change

Success!

Thank you for helping us improve the quality of Unity Documentation. Although we cannot accept all submissions, we do read each suggested change from our users and will make updates where applicable.

Close

Submission failed

For some reason your suggested change could not be submitted. Please <a>try again</a> in a few minutes. And thank you for taking the time to help us improve the quality of Unity Documentation.

Close

Cancel

Declaration

public void BuildRayTracingAccelerationStructure(Rendering.RayTracingAccelerationStructure accelerationStructure);

Declaration

public void BuildRayTracingAccelerationStructure(Rendering.RayTracingAccelerationStructure accelerationStructure, Vector3 relativeOrigin);

Declaration

public void BuildRayTracingAccelerationStructure(Rendering.RayTracingAccelerationStructure accelerationStructure, Rendering.RayTracingAccelerationStructure.BuildSettings buildSettings);

Parameters

Parameter Description
accelerationStructure The RayTracingAccelerationStructure to be generated.
relativeOrigin The relative origin of ray tracing instances. The default value is Vector3.zero. To use camera-relative ray-tracing, set this parameter to the position of the camera.
buildSettings The BuildSettings to use.

Description

Adds a command to build the RayTracingAccelerationStructure to be used in a ray tracing dispatch or when using inline ray tracing (ray queries).

To ensure that the acceleration structure is up to date, call this method before using the acceleration structure in ray tracing shaders (for example before a CommandBuffer.DispatchRays call) or when using inline ray tracing.

In the following example, the Update method uses a compute shader dispatch to modify the vertex positions of a mesh instance, then the RayTracingAccelerationStructure is rebuilt.

using Unity.Collections;
using UnityEngine;
using UnityEngine.Rendering;

public class RayTracingInstanceManager : MonoBehaviour { public Material instanceMaterial; public ComputeShader vertexAnimationShader; public RayTracingShader rayTracingShader;

private RayTracingAccelerationStructure rtas; private CommandBuffer cmd; private RenderTexture rayTracingOutput; private uint cameraWidth = 0; private uint cameraHeight = 0; private uint meshResolution = 32; private Mesh instanceMesh;

void Start() { // Create command buffer cmd = new CommandBuffer(); cmd.name = "Ray Tracing Setup";

InitializeRayTracing(); }

private NativeArray<uint> CreateIndexArray(uint resolution) { uint indexCount = 2 * 3 * resolution * resolution; uint[] indices = new uint[indexCount];

int index = 0;

for (uint i = 0; i < resolution; i++) { for (uint j = 0; j < resolution; j++) { indices[index++] = i * (resolution + 1) + j; indices[index++] = (i + 1) * (resolution + 1) + j; indices[index++] = (i + 1) * (resolution + 1) + j + 1;

indices[index++] = i * (resolution + 1) + j; indices[index++] = (i + 1) * (resolution + 1) + j + 1; indices[index++] = i * (resolution + 1) + j + 1; } }

return new NativeArray<uint>(indices, Allocator.Persistent); }

struct Vertex { public Vector3 position; }

private NativeArray<Vertex> CreateVertexArray(uint resolution) { uint vertexCount = (resolution + 1) * (resolution + 1); Vertex[] vertices = new Vertex[vertexCount];

float invResolution = 1.0f / (float)resolution; float step = 2.0f * invResolution; int vertexIndex = 0; float posZ = -1.0f;

for (uint z = 0; z <= resolution; z++) { float posX = -1.0f;

for (uint x = 0; x <= resolution; x++) { vertices[vertexIndex].position = new Vector3(posX, 0, posZ);

vertexIndex++; posX += step; } posZ += step; }

return new NativeArray<Vertex>(vertices, Allocator.Temp); }

void InitializeRayTracing() { // Set up acceleration structure RayTracingAccelerationStructure.Settings settings = new RayTracingAccelerationStructure.Settings { managementMode = RayTracingAccelerationStructure.ManagementMode.Manual, layerMask = -1 }; rtas = new RayTracingAccelerationStructure(settings); // Create base mesh on GPU instanceMesh = new Mesh();

if (SystemInfo.supportsComputeShaders) { instanceMesh.vertexBufferTarget |= GraphicsBuffer.Target.Raw; instanceMesh.indexBufferTarget |= GraphicsBuffer.Target.Raw; }

using (NativeArray<Vertex> varray = CreateVertexArray(meshResolution)) { instanceMesh.SetVertexBufferParams(varray.Length, new VertexAttributeDescriptor(VertexAttribute.Position, VertexAttributeFormat.Float32, 3)); instanceMesh.SetVertexBufferData(varray, 0, 0, varray.Length); }

using (NativeArray<uint> iarray = CreateIndexArray(meshResolution)) { instanceMesh.SetIndexBufferParams(iarray.Length, IndexFormat.UInt32); instanceMesh.SetIndexBufferData(iarray, 0, 0, iarray.Length); instanceMesh.SetSubMesh(0, new SubMeshDescriptor(0, iarray.Length)); }

RayTracingMeshInstanceConfig gpuMeshInstance = new RayTracingMeshInstanceConfig(instanceMesh, 0, instanceMaterial);

// Make the acceleration structure update every time we call RayTracingAccelerationStructure.Build or CommandBuffer.BuildRayTracingAccelerationStructure. gpuMeshInstance.dynamicGeometry = true;

Matrix4x4 matrix = Matrix4x4.identity; matrix.SetTRS(new Vector3(0.0f, 0.0f, 0.0f), Quaternion.identity, Vector3.one);

rtas.AddInstance(gpuMeshInstance, matrix); }

void CreateResources() { 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; } }

void Update() { if (vertexAnimationShader == null) { Debug.LogError("Error: Compute shader is missing. Assign a compute shader to the vertexAnimationShader property."); return; }

GraphicsBuffer vertexBuffer = instanceMesh.GetVertexBuffer(0); cmd.SetComputeBufferParam(vertexAnimationShader, 0, "vertexBuffer", vertexBuffer);

cmd.SetComputeFloatParam(vertexAnimationShader, "realtimeSinceStartup", Time.realtimeSinceStartup); cmd.SetComputeIntParam(vertexAnimationShader, "vertexCount", vertexBuffer.count); cmd.SetComputeIntParam(vertexAnimationShader, "vertexSizeInBytes", vertexBuffer.stride);

if (vertexBuffer.stride % 4 != 0) Debug.Log("Vertex stride must be a multiple of 4.");

uint kernelGroupSizeX, kernelGroupSizeY, kernelGroupSizeZ; vertexAnimationShader.GetKernelThreadGroupSizes(0, out kernelGroupSizeX, out kernelGroupSizeY, out kernelGroupSizeZ);

int threadGroupsX = (int)(instanceMesh.vertexCount + kernelGroupSizeX - 1) / (int)kernelGroupSizeX; cmd.DispatchCompute(vertexAnimationShader, 0, threadGroupsX, 1, 1);

vertexBuffer.Dispose();

// Re-build acceleration to take into account modified mesh geometry. cmd.BuildRayTracingAccelerationStructure(rtas); // The command buffer will be executed in the next OnRenderImage }

[ImageEffectOpaque] void OnRenderImage(RenderTexture src, RenderTexture dest) { if (!SystemInfo.supportsRayTracing || !rayTracingShader) { Debug.LogWarning("Warning: The Ray Tracing API is not supported by this GPU or by the current graphics API."); Graphics.Blit(src, dest); return; } CreateResources(); cmd.SetRayTracingShaderPass(rayTracingShader, "Test"); // Input cmd.SetRayTracingAccelerationStructure(rayTracingShader, Shader.PropertyToID("g_AccelStruct"), rtas); cmd.SetRayTracingMatrixParam(rayTracingShader, Shader.PropertyToID("g_InvViewMatrix"), Camera.main.cameraToWorldMatrix); cmd.SetGlobalVector(Shader.PropertyToID("g_CameraPos"), Camera.main.transform.position); // Output cmd.SetRayTracingTextureParam(rayTracingShader, Shader.PropertyToID("g_Output"), rayTracingOutput); // Execute the raytracing shader cmd.DispatchRays(rayTracingShader, "MainRayGenShader", cameraWidth, cameraHeight, 1); // Execute command buffer Graphics.ExecuteCommandBuffer(cmd); cmd.Clear(); Graphics.Blit(rayTracingOutput, dest); }

void OnDisable() { // Cleanup if (rtas != null) { rtas.Dispose(); rtas = null; } if (instanceMesh != null) { DestroyImmediate(instanceMesh); instanceMesh = null; } if (cmd != null) { cmd.Release(); cmd = null; } if (rayTracingOutput != null) { rayTracingOutput.Release(); rayTracingOutput = null; } } }