Adaug proiectul Unity

This commit is contained in:
2026-11-01 23:39:55 +02:00
parent cb14d9d37d
commit 863eac8f2c
23463 changed files with 5412601 additions and 0 deletions
@@ -0,0 +1,51 @@
# Create an acceleration structure
[`IRayTracingAccelStruct`](xref:UnityEngine.Rendering.UnifiedRayTracing.IRayTracingAccelStruct) is the data structure used to represent a collection of instances and geometries that are used for GPU ray tracing.
Create an acceleration structure with the following code:
```C#
var options = new AccelerationStructureOptions();
IRayTracingAccelStruct rtAccelStruct = rtContext.CreateAccelerationStructure(options);
```
## Build options
[`AccelerationStructureOptions`](xref:UnityEngine.Rendering.UnifiedRayTracing.AccelerationStructureOptions) allows you to configure the build algorithm. The trade-off is as follows: A faster build results in worse ray tracing performance, and conversely, a slower build can improve ray tracing performance.
The following fields can be configured:
|Field|Description|
|-|-|
|`buildFlags`|Adjust the buildFlags to prioritize either faster construction of the acceleration structure or faster ray tracing.|
|`useCPUBuild` (Compute backend)|When set to true, Unity builds the acceleration structure on the CPU instead of the GPU. This option has no effect when using the `Hardware` backend. CPU-based builds use a more advanced algorithm, resulting in a higher-quality acceleration structure, which enhances overall ray tracing performance.|
The following example demonstrates how to get the best ray tracing performance. These options make the acceleration structure longer to build, however.
```HLSL
var options = new AccelerationStructureOptions() {
buildFlags = BuildFlags.PreferFastTrace,
useCPUBuild = true
}
```
## Populate the acceleration structure
Unlike [`RayTracingAccelerationStructure`](xref:UnityEngine.Rendering.RayTracingAccelerationStructure), there is no support for automatic synchronization between the acceleration structure's instances and the scene instances. You need to add them manually, for example:
```C#
var instanceDesc = new MeshInstanceDesc(mesh, 0 /*subMeshIndex*/);
instanceDesc.localToWorldMatrix = /* desired transform */;
rtAccelStruct.AddInstance(instanceDesc);
```
To trace rays against all the Mesh-based GameObjects in your scene, add them to the [`IRayTracingAccelStruct`](xref:UnityEngine.Rendering.UnifiedRayTracing.IRayTracingAccelStruct). For example:
```C#
var meshRenderers = UnityEngine.Object.FindObjectsByType<MeshRenderer>(FindObjectsSortMode.None);
foreach (var renderer in meshRenderers)
{
var mesh = renderer.GetComponent<MeshFilter>().sharedMesh;
int subMeshCount = mesh.subMeshCount;
for (int i = 0; i < subMeshCount; ++i)
{
var instanceDesc = new MeshInstanceDesc(mesh, i);
instanceDesc.localToWorldMatrix = renderer.transform.localToWorldMatrix;
rtAccelStruct.AddInstance(instanceDesc);
}
}
```
@@ -0,0 +1,73 @@
# Create the ray tracing context
The [`RayTracingContext`](xref:UnityEngine.Rendering.UnifiedRayTracing.RayTracingContext) serves as the initial API entry point, allowing the creation of all essential objects required to execute ray tracing code.
Follow these steps:
1. Load the ray tracing resources.
2. Create the context.
## Load the ray tracing resources
The [`RayTracingContext`](xref:UnityEngine.Rendering.UnifiedRayTracing.RayTracingContext) needs a few utility shaders that the [`RayTracingResources`](xref:UnityEngine.Rendering.UnifiedRayTracing.RayTracingResources) object supplies. You can load these resources in several different ways.
If your project uses SRP (Scriptable Render Pipeline), load the resources via [`RayTracingResources.LoadFromRenderPipelineResources`](xref:UnityEngine.Rendering.UnifiedRayTracing.RayTracingResources.LoadFromRenderPipelineResources()). This always works in the Editor.
```C#
var rtResources = new RayTracingResources();
bool result = rtResources.LoadFromRenderPipelineResources();
```
You can instruct Unity to also include the resources in Player builds:
```C#
using UnityEngine.Rendering;
using UnityEngine.Rendering.UnifiedRayTracing;
#if UNITY_EDITOR
class MyURTStripping: IRenderPipelineGraphicsSettingsStripper<RayTracingRenderPipelineResources>
{
public bool active => true;
public bool CanRemoveSettings(RayTracingRenderPipelineResources settings) => false;
}
#endif
```
You can also load the resources via the Asset Database:
```C#
var rtResources = new RayTracingResources();
rtResources.Load();
```
**Note:** Since the Player doesn't give access to the Asset Database, this method only works in the Editor.
To load the [`RayTracingResources`](xref:UnityEngine.Rendering.UnifiedRayTracing.RayTracingResources) in the Player, you can also build an AssetBundle that includes the following SRP Core files:
- `Runtime/UnifiedRayTracing/Common/GeometryPool/GeometryPoolKernels.compute`
- `Runtime/UnifiedRayTracing/Common/Utilities/CopyBuffer.compute`
- `Runtime/UnifiedRayTracing/Compute/RadeonRays/kernels/copyPositions.compute`
- `Runtime/UnifiedRayTracing/Compute/RadeonRays/kernels/bit_histogram.compute`
- `Runtime/UnifiedRayTracing/Compute/RadeonRays/kernels/block_reduce_part.compute`
- `Runtime/UnifiedRayTracing/Compute/RadeonRays/kernels/block_scan.compute`
- `Runtime/UnifiedRayTracing/Compute/RadeonRays/kernels/build_hlbvh.compute`
- `Runtime/UnifiedRayTracing/Compute/RadeonRays/kernels/restructure_bvh.compute`
- `Runtime/UnifiedRayTracing/Compute/RadeonRays/kernels/scatter.compute`
For more information about building and loading AssetBundles, refer to [AssetBundles](xref:AssetBundlesIntro).
After you build the AssetBundle, use the following code to load it:
```C#
var rtResources = new RayTracingResources();
// Load the AssetBundle
var asssetBundle = AssetBundle.LoadFromFile("Assets/pathToYourBuiltAssetBundles/unifiedraytracing");
// Load the RayTracingResources
rtResources.LoadFromAssetBundle(asssetBundle);
```
## Create the context
Once the [`RayTracingResources`](xref:UnityEngine.Rendering.UnifiedRayTracing.RayTracingResources) are loaded, use them to create the [`RayTracingContext`](xref:UnityEngine.Rendering.UnifiedRayTracing.RayTracingContext).
```C#
var context = new RayTracingContext(rtResources);
```
By default, Unity checks if the device supports hardware ray tracing, and selects either hardware ray tracing or compute shaders. To manually select the backend, pass in a `RayTracingBackend`. For example:
```C#
var backend = RayTracingBackend.Compute;
var context = new RayTracingContext(backend, rtResources);
```
@@ -0,0 +1,53 @@
# Create a unified ray tracing shader
Depending on the backend you choose in the [`RayTracingContext`](xref:UnityEngine.Rendering.UnifiedRayTracing.RayTracingContext), write your ray tracing code in either a `.raytrace` or a `.compute` shader.
To create both a `.raytrace` shader and a `.compute` shader, write your shader code in a unified ray tracing shader (`.urtshader`).
To create a shader, follow these steps:
1. Create the shader asset file.
2. Load the shader.
## Create the shader asset file
To create a unified ray tracing shader:
1. Launch the Unity Editor.
1. In the **Project** window, open the **Assets** folder.
1. Open or create the folder in which you want to create your shader.
1. Open the context menu (right-click) and select **Create** &gt; **Shader** &gt; **Unified Ray Tracing Shader**.
1. Enter a name for the shader.
Ray tracing occurs in the `RayGenExecute` function. You can edit the example code snippet.
For more information about writing a ray tracing shader, refer to [Write your shader code](write-shader.md).
## Load the shader
To load the `.urtshader` file in the Editor, use the following code snippet:
```C#
IRayTracingShader shader = rtContext.LoadRayTracingShader("Assets/yourShader.urtshader");
```
To load the shader in the Player, add the `.urtshader` shader to an <xref:UnityEngine.AssetBundle> then load it with the following:
```C#
// Load the AssetBundle
var asssetBundle = AssetBundle.LoadFromFile("Assets/pathToYourBuiltAssetBundles/yourAssetBundle");
// Load the shader
IRayTracingShader shader = rtContext.LoadRayTracingShaderFromAssetBundle(asssetBundle, "Assets/yourShader.urtshader");
```
To have more control, load the underlying Compute or Ray Tracing shader asset yourself and pass it to [`RayTracingContext.CreateRayTracingShader`](xref:UnityEngine.Rendering.UnifiedRayTracing.RayTracingContext.CreateRayTracingShader(UnityEngine.Object)).
[`RayTracingContext.LoadRayTracingShaderFromAssetBundle`](xref:UnityEngine.Rendering.UnifiedRayTracing.RayTracingContext.LoadRayTracingShaderFromAssetBundle(UnityEngine.AssetBundle,System.String)) is a convenience function that performs the following operations:
```C#
public IRayTracingShader LoadRayTracingShaderFromAssetBundle(AssetBundle assetBundle, string name)
{
Object asset = assetBundle.LoadAsset(name, BackendHelpers.GetTypeOfShader(BackendType));
return CreateRayTracingShader(asset);
}
```
@@ -0,0 +1,55 @@
# Execute your ray tracing code
This section assumes you have [a shader](create-shader.md) containing your ray tracing logic and an [acceleration structure](create-acceleration-structure.md) representing the geometry that the rays will intersect.
To execute your ray tracing shader on the GPU:
1. Build the acceleration structure.
2. Bind resources to the shader.
3. Dispatch the shader.
## Build the acceleration structure
You must build the acceleration structure after you create it and every time you modify it. For example:
```C#
IRayTracingAccelStruct rtAccelStruct = /* your acceleration structure */;
var cmd = new CommandBuffer();
// A scratch buffer is required to build the acceleration structure, this helper function allocates one with the required size.
GraphicsBuffer buildScratchBuffer = RayTracingHelper.CreateScratchBufferForBuild(rtAccelStruct);
// Build the ray tracing acceleration structure
rtAccelStruct.Build(cmd, buildScratchBuffer);
```
## Bind resources to the shader
You must bind the acceleration structure and any additional GPU resources declared in your shader, such as constants, buffers, and textures. For example:
```C#
IRayTracingShader rtShader = /* your shader */;
// Bind the acceleration structure. It is declared in the shader as: UNIFIED_RT_DECLARE_ACCEL_STRUCT(_YourAccelStruct);
rtShader.SetAccelerationStructure(cmd, "_YourAccelStruct", rtAccelStruct);
// Bind the other GPU resources (constants/uniforms, buffers and textures)
rtShader.SetIntParam(cmd, Shader.PropertyToID("_YourInteger"), 5);
```
## Dispatch the shader
To make the GPU run your ray tracing shader, call the [`Dispatch`](xref:UnityEngine.Rendering.UnifiedRayTracing.IRayTracingShader.Dispatch(UnityEngine.Rendering.CommandBuffer,UnityEngine.GraphicsBuffer,System.UInt32,System.UInt32,System.UInt32)) method. For example:
```C#
const int threadCountX = 256, threadCountY = 256, threadCountZ = 1;
// A scratch buffer is required to trace rays, this helper function allocates one with the required size.
GraphicsBuffer traceScratchBuffer = RayTracingHelper.CreateScratchBufferForTrace(rtShader, threadCountX, threadCountY, threadCountZ);
// Dispatch rays. Workgrid dimensions are supplied in threads, not workgroups
rtShader.Dispatch(cmd, traceScratchBuffer, threadCountX, threadCountY, threadCountZ);
// Execute the command buffer to effectively run all the previously registered commands.
Graphics.ExecuteCommandBuffer(cmd);
```
**Note:** If its size satisfies the requirements for both operations, you can use the same scratch buffer for both the build and trace steps.
@@ -0,0 +1,28 @@
# Get started with ray tracing
The `UnifiedRayTracing` API enables you to write ray tracing code that executes on a wide range of GPUs. Unlike the [`RayTracingAccelerationStructure`](xref:UnityEngine.Rendering.RayTracingAccelerationStructure) API,
its key advantage is that it is able to operate without requiring hardware ray tracing support. It achieves this by offering multiple backends that can be dynamically selected based on the GPU’s capabilities.
## Backends
The following backends are available:
- `Hardware`: Requires a GPU that supports hardware-accelerated ray tracing. This backend uses the [`RayTracingAccelerationStructure`](xref:UnityEngine.Rendering.RayTracingAccelerationStructure) API.
- `Compute` : Software implementation of ray tracing that works only on GPUs that support compute shaders.
By abstracting these different implementations behind a unified interface, the API allows you to write your ray tracing code once, and have it automatically adapt to the appropriate backend.
## Main concepts
The API entry point is the [`RayTracingContext`](xref:UnityEngine.Rendering.UnifiedRayTracing.RayTracingContext) which is initialized for a specific backend.
The [`RayTracingContext`](xref:UnityEngine.Rendering.UnifiedRayTracing.RayTracingContext) enables you to create the 2 essential objects you need to perform ray tracing:
- an acceleration structure ([`IRayTracingAccelStruct`]((xref:UnityEngine.Rendering.UnifiedRayTracing.IRayTracingAccelStruct))) which represents the geometry to trace rays against.
- a shader ([`IRayTracingShader`]((xref:UnityEngine.Rendering.UnifiedRayTracing.IRayTracingShader))) which contains your ray tracing code that will run on the GPU.
![RayTracingContext class features](../Images/RayTracingContext.jpg)
For more information, refer to [Using the API workflow](workflow.md).
## Limitations
In order to accomodate both hardware-accelerated and non-accelerated GPUs, the API is more constrained than Unity's [`RayTracingAccelerationStructure` API](xref:UnityEngine.Rendering.RayTracingAccelerationStructure).
- The API doesn't support any automatic scene updates. You must explicitly call [`IRayTracingAccelStruct.AddInstance`](xref:UnityEngine.Rendering.UnifiedRayTracing.IRayTracingAccelStruct.AddInstance(UnityEngine.Rendering.UnifiedRayTracing.MeshInstanceDesc)) or
[`IRayTracingAccelStruct.RemoveInstance`](xref:UnityEngine.Rendering.UnifiedRayTracing.IRayTracingAccelStruct.RemoveInstance(System.Int32)) to update the acceleration structure.
- The API supports only ray tracing with mesh geometries.
- Once a hit is found, the `TraceRay` function returns immediately with the hit information. You need to write the shading code in the ray generation shader (`.urtshader`).
@@ -0,0 +1,26 @@
# Release your ray tracing objects
You must free up the memory your ray tracing objects use after you finish with them.
Dispose of the following:
- Scratch buffers. Use [`GraphicsBuffer.Dispose`](xref:UnityEngine.GraphicsBuffer.Dispose()) after you've executed the final command buffer.
- Ray tracing acceleration structures. Use [`IRayTracingAccelStruct.Dispose`](xref:UnityEngine.Rendering.UnifiedRayTracing.IRayTracingAccelStruct.Dispose()) after you've executed the final command buffer.
- Ray tracing context. Use [`RayTracingContext.Dispose`](xref:UnityEngine.Rendering.UnifiedRayTracing.RayTracingContext.Dispose()) after you dispose of all its acceleration structures.
**Note**: Unity automatically disposes of [`RayTracingResources`](xref:UnityEngine.Rendering.UnifiedRayTracing.RayTracingResources) and [`IRayTracingShader`](xref:UnityEngine.Rendering.UnifiedRayTracing.IRayTracingShader).
For example:
```C#
RayTracingContext rtContext = new RayTracingContext(rtResources);
IRayTracingShader rtShader = rtContext.LoadRayTracingShader("Assets/yourShader.urtshader");
IRayTracingAccelStruct rtAccelStruct = rtContext.CreateAccelerationStructure(new AccelerationStructureOptions());
GraphicsBuffer rtScratchBuffer = RayTracingHelper.CreateScratchBufferForBuild(rtAccelStruct);
// ... create and dispatch your ray tracing command buffers ...
rtScratchBuffer.Dispose();
rtAccelStruct.Dispose();
rtContext.Dispose();
```
@@ -0,0 +1,74 @@
# Unified ray tracing shader code reference
This section presents the different functions and structs provided by the API for tracing rays in a shader.
All types are defined inside the `UnifiedRT` namespace. In your code, you need to prefix them with ```UnifiedRT::```. Alternatively, you can add ```using namespace UnifiedRT;``` after your `TraceRayAndQueryHit.hlsl` include statement.
## function TraceRayClosestHit
```HLSL
Hit TraceRayClosestHit(DispatchInfo dispatchInfo, RayTracingAccelStruct accelStruct, uint instanceMask, Ray ray, uint rayFlags)
```
Searches for intersections between a ray and an acceleration structure. It returns hit information about the closest triangle encountered along the ray.
### Parameters
|Type|Name|Description|
|-|-|-|
|[`DispatchInfo`](#struct-dispatchinfo)|*dispatchInfo*|The dispatch info. Must be the value that is passed by `RayGenExecute`.|
|`RayTracingAccelStruct`|*accelStruct*|The acceleration structure to test the ray against.|
|`uint`|*instanceMask*|The lower 8 bits of this mask are used to include geometry instances based on the instance mask that was set in `MeshInstanceDesc` for each instance.|
|[`Ray`](#struct-ray)|*ray*|Describes the ray segment that is intersected against the acceleration structure.|
|`uint`|*rayFlags*|Flags that filter out the triangles that participate in the intersection test. Can be one of the following: <ul><li>kRayFlagNone</li><li>kRayFlagCullBackFacingTriangles</li><li>kRayFlagCullFrontFacingTriangles</li> </ul>|
### Returns
[`Hit`](#struct-hit) containing geometry information about the hit triangle. When no primitive has intersected with the ray, `hit.IsValid()` returns false.
## function TraceRayAnyHit
```HLSL
bool TraceRayAnyHit(DispatchInfo dispatchInfo, RayTracingAccelStruct accelStruct, uint instanceMask, Ray ray, uint rayFlags)
```
Searches for any intersection between a ray and an acceleration structure. The search ends as soon as a valid triangle hit is found. This function can typically be used to trace shadow rays or perform occlusion queries.
### Parameters
|Type|Name|Description|
|-|-|-|
|[`DispatchInfo`](#struct-dispatchinfo)|*dispatchInfo*|The dispatch info. Must be the value that is passed by `RayGenExecute`.|
|`RayTracingAccelStruct`|*accelStruct*|The acceleration structure to test the ray against.|
|`uint`|*instanceMask*|The lower 8 bits of this mask are used to include geometry instances based on the instance mask that was set in `MeshInstanceDesc` for each instance.|
|[`Ray`](#struct-ray)|*ray*|Describes the ray segment that is intersected against the acceleration structure.|
|`uint`|*rayFlags*|Flags that filter out the triangles that participate in the intersection test. Can be one of the following: <ul><li>kRayFlagNone</li><li>kRayFlagCullBackFacingTriangles</li><li>kRayFlagCullFrontFacingTriangles</li> </ul>|
### Returns
A boolean that is true if any primitive was hit by the ray.
## struct Ray
Describes a ray.
The `tMin` and `tMax` fields define the segment of the ray to be tested against the acceleration structures's primitives.
Mathematically, the ray consists of all the points defined as `P = ray.origin + t * ray.direction`, where `ray.tMin ≤ t ≤ ray.tMax`.
### Fields
|Type|Name|Description|
|-|-|-|
|`float3`|*origin*|The ray's origin.|
|`float3`|*direction*|The ray's direction.|
|`float`|*tMin*|The ray's starting point.|
|`float`|*tMax*|The ray's endpoint.|
## struct DispatchInfo
Provides information about the current thread that is invoked.
### Fields
|Type|Name|Description|
|-|-|-|
|`uint3`|*dispatchThreadID*|Same semantic as `SV_DispatchThreadID`.|
|`uint`|*localThreadIndex*|Same semantic as `SV_GroupIndex`.|
|`uint3`|*dispatchDimensionsInThreads*|Total numbers of threads dispatched in the X, Y, and Z workgrid directions.|
|`uint`|*globalThreadIndex*|Global thread index that is unique within the workgrid.|
## struct Hit
Describes a Hit.
### Fields
|Type|Name|Description|
|-|-|-|
|`uint`|*instanceID*|Matches the `instanceID` supplied from C# in `MeshInstanceDesc.instanceID`.|
|`uint`|*primitiveIndex*|Index of the hit triangle in its source Mesh.|
|`float2`|*uvBarycentrics*|Barycentric coordinates of the hit triangle.|
|`float`|*hitDistance*|Defines the hit position: `hitPos = ray.origin + ray.direction * hit.hitDistance`.|
|`bool`|*isFrontFace*|Indicates whether the hit triangle is front-facing or back-facing.|
### Methods
```HLSL
bool IsValid();
```
Returns true when a hit has been found. When a hit is invalid `hit.instanceID` is equal to `~0` and the other fields are undefined.
@@ -0,0 +1,161 @@
# Sample code: Tracing camera rays
This section demonstrates how to use the API to cast rays from the scene's Main camera and output the results into a `RenderTexture`, providing the complete code for implementation.
![Example of output texture for a scene with a simple cube](../Images/ExampleOutputTexture.png)
Save the following code in your **Assets** folder as a file named `shootCameraRays.urtshader`:
```HLSL
// Include file for the UnifiedRayTracing API functions
#include "Packages/com.unity.render-pipelines.core/Runtime/UnifiedRayTracing/TraceRayAndQueryHit.hlsl"
// Use this macro to declare the acceleration structure binding
UNIFIED_RT_DECLARE_ACCEL_STRUCT(_AccelStruct);
uint _RenderWidth;
uint _RenderHeight;
float4 _CameraFrustum;
float4x4 _CameraToWorldMatrix;
RWTexture2D<float4> _OutputTexture;
UnifiedRT::Ray GenerateFrustumRay(float2 frameCoord, uint2 resolution)
{
float2 ndcCoords01 = (frameCoord + 0.5) / float2(resolution);
float3 viewDirection = float3(
lerp(_CameraFrustum.x, _CameraFrustum.y, ndcCoords01.x),
lerp(_CameraFrustum.z, _CameraFrustum.w, ndcCoords01.y),
-1.0);
UnifiedRT::Ray ray;
ray.origin = transpose(_CameraToWorldMatrix)[3].xyz;
ray.direction = mul((float3x3) _CameraToWorldMatrix, normalize(viewDirection));
ray.tMin = 0.0f;
ray.tMax = 100000.0f;
return ray;
}
// Entry point of the shader. DispatchInfo provides the current thread index in the dispatch
void RayGenExecute(UnifiedRT::DispatchInfo dispatchInfo)
{
UnifiedRT::Ray ray = GenerateFrustumRay(dispatchInfo.dispatchThreadID.xy, uint2(_RenderWidth, _RenderHeight));
// Retrieve the acceleration structure
UnifiedRT::RayTracingAccelStruct accelStruct = UNIFIED_RT_GET_ACCEL_STRUCT(_AccelStruct);
// Trace a ray in the acceleration structure
UnifiedRT::Hit hitResult = UnifiedRT::TraceRayClosestHit(dispatchInfo, accelStruct, 0xFFFFFFFF, ray, UnifiedRT::kRayFlagNone);
float2 uv = hitResult.uvBarycentrics;
// display the hit triangle barycentrics coordinates as an RGB color
float3 color = hitResult.IsValid() ? float3(uv.x, uv.y, 1.0 - uv.x - uv.y) : 0.0;
_OutputTexture[dispatchInfo.dispatchThreadID.xy] = float4(color, 1.0);
}
```
The following C# MonoBehaviour is responsible for creating the acceleration structure, loading the ray tracing shader and dispatching it to the GPU.
Save it as a script file in your **Assets** folder and attach it to one of your scene GameObjects.
```C#
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.UnifiedRayTracing;
public class ShootCameraRays : MonoBehaviour
{
RayTracingResources m_RtResources;
RayTracingContext m_RtContext;
IRayTracingShader m_RtShader;
IRayTracingAccelStruct m_RtAccelStruct;
// Ray tracing results are written to this texture
const int width = 1024;
const int height = 576;
public RenderTexture OutputTexture;
void Start()
{
var renderTexDesc = new RenderTextureDescriptor(width, height);
renderTexDesc.graphicsFormat = UnityEngine.Experimental.Rendering.GraphicsFormat.R8G8B8A8_SRGB;
renderTexDesc.enableRandomWrite = true;
OutputTexture = new RenderTexture(renderTexDesc);
m_RtResources = new RayTracingResources();
m_RtResources.Load();
// Create the RayTracingContext
var backend = RayTracingContext.IsBackendSupported(RayTracingBackend.Hardware) ? RayTracingBackend.Hardware : RayTracingBackend.Compute;
m_RtContext = new RayTracingContext(backend, m_RtResources);
// Load the unified ray tracing shader
m_RtShader = m_RtContext.LoadRayTracingShader("Assets/shootCameraRays.urtshader");
// Create the ray tracing acceleration structure
m_RtAccelStruct = m_RtContext.CreateAccelerationStructure(new AccelerationStructureOptions());
// Add an instance to the acceleration structure for each MeshRenderer in the current scene
uint instanceID = 0;
var meshRenderers = UnityEngine.Object.FindObjectsByType<MeshRenderer>(FindObjectsSortMode.None);
foreach (var renderer in meshRenderers)
{
var mesh = renderer.GetComponent<MeshFilter>().sharedMesh;
int subMeshCount = mesh.subMeshCount;
for (int i = 0; i < subMeshCount; ++i)
{
var instanceDesc = new MeshInstanceDesc(mesh, i);
instanceDesc.localToWorldMatrix = renderer.transform.localToWorldMatrix;
instanceDesc.instanceID = instanceID++;
m_RtAccelStruct.AddInstance(instanceDesc);
}
}
}
void OnDestroy()
{
m_RtAccelStruct.Dispose();
m_RtContext.Dispose();
OutputTexture?.Release();
}
void Update()
{
// A scratch buffer is required to build the acceleration structure and for the ray traversal, this helper function allocates one with the required size.
GraphicsBuffer scratchBuffer = RayTracingHelper.CreateScratchBufferForBuildAndDispatch(m_RtAccelStruct, m_RtShader, width, height, 1);
var cmd = new CommandBuffer();
// build the ray tracing acceleration structure
m_RtAccelStruct.Build(cmd, scratchBuffer);
// bind the shader gpu resources
m_RtShader.SetAccelerationStructure(cmd, "_AccelStruct", m_RtAccelStruct);
m_RtShader.SetIntParam(cmd, Shader.PropertyToID("_RenderWidth"), width);
m_RtShader.SetIntParam(cmd, Shader.PropertyToID("_RenderHeight"), height);
m_RtShader.SetVectorParam(cmd, Shader.PropertyToID("_CameraFrustum"), GetCameraFrustum(Camera.main));
m_RtShader.SetMatrixParam(cmd, Shader.PropertyToID("_CameraToWorldMatrix"), Camera.main.cameraToWorldMatrix);
m_RtShader.SetTextureParam(cmd, Shader.PropertyToID("_OutputTexture"), OutputTexture);
// dispatch rays. Workgrid dimensions are supplied in threads, not workgroups
m_RtShader.Dispatch(cmd, scratchBuffer, width, height, 1);
Graphics.ExecuteCommandBuffer(cmd);
scratchBuffer?.Dispose();
}
// utility function to extract a frustum from a camera
Vector4 GetCameraFrustum(Camera camera)
{
Vector3[] frustumCorners = new Vector3[4];
camera.CalculateFrustumCorners(new Rect(0, 0, 1, 1), 1.0f, Camera.MonoOrStereoscopicEye.Mono, frustumCorners);
float left = frustumCorners[0].x;
float right = frustumCorners[2].x;
float bottom = frustumCorners[0].y;
float top = frustumCorners[2].y;
return new Vector4(left, right, bottom, top);
}
}
```
You can now enter Play mode and visualize the ray tracing results. Follow these steps:
1. Select the GameObject you attached the `ShootCameraRays` MonoBehaviour to.
2. In the **Inspector** window, go to the **ShootCameraRays** component and double-click **Output Texture**.
3. The Inspector now displays a preview of the render texture containing the ray tracing results.
@@ -0,0 +1,15 @@
# Ray tracing with the UnifiedRayTracing API
The `UnifiedRayTracing` API enables you to write ray tracing code that can execute on a wide range of GPUs. It leverages hardware ray tracing acceleration on supported GPUs, while providing a compute shader-based software fallback for those that do not.
|Section|Description|
|-|-|
|[Get started with ray tracing](get-started.md)|Learn the essential information about the API.|
|[Ray tracing workflow](workflow.md)|Create a ray tracing context, and create and execute a ray tracing shader.|
|[Create the ray tracing context](create-ray-tracing-context.md)|How to create the API entry point.|
|[Create an acceleration structure](create-acceleration-structure.md)|Create and initialize an acceleration structure describing your geometry.|
|[Create a unified ray tracing shader](create-shader.md)|Create a unified ray tracing shader file.|
|[Write your shader code](write-shader.md)|Write the ray tracing logic in your a unified ray tracing shader file.|
|[Execute your ray tracing code](execute-shader.md)|How to execute your ray tracing shader.|
|[Sample code](trace-camera-rays-full-sample.md)|Complete code example showcasing tracing rays from the scene's camera.|
|[Unified ray tracing shader code reference](shader-code-reference.md)|API reference for the unified ray tracing shader code.|
|[Release your ray tracing objects](release-resources.md)|Learn how to release your ray tracing resources.|
@@ -0,0 +1,58 @@
# Ray tracing workflow
To use the API to trace rays in Unity, follow these steps:
1. Create the ray tracing context.
2. Create an acceleration structure.
3. Create a shader.
4. Build your acceleration structure.
5. Execute your shader.
6. Dispose of your objects.
## Create the ray tracing context
The context serves as the API entry point. Create it using the following parameters:
1. `backend`: The chosen backend, which can be either `Hardware` or `Compute`.
2. `resources`: A collection of assets required by the context to function.
```C#
var rtContext = new RayTracingContext(backend, rtResources);
```
For more information, refer to [Create the ray tracing Context](create-ray-tracing-context.md).
## Create an acceleration structure
The acceleration structure is the data structure used to represent a collection of instances and geometries that are used for GPU ray tracing.
```C#
IRayTracingAccelStruct rtAccelStruct = rtContext.CreateAccelerationStructure(options);
```
After creating the structure, populate it with mesh instances using the [`AddInstance`](xref:UnityEngine.Rendering.UnifiedRayTracing.IRayTracingAccelStruct.AddInstance(UnityEngine.Rendering.UnifiedRayTracing.MeshInstanceDesc)) method.
For more information, refer to [Create an acceleration structure](create-acceleration-structure.md).
## Create a unified ray tracing shader
Depending on the chosen backend, the `RayTracingContext` runs either a `ComputeShader` or a `RayTracingShader`. The API introduces the unified ray tracing shader (`.urtshader`), which is a shader type that generates both variants for you.
```C#
IRayTracingShader rtShader = rtContext.LoadRayTracingShader("Assets/yourShader.urtshader");
```
For more information, refer to [Create a unified ray tracing shader](create-shader.md).
## Build your acceleration structure
Whenever it is modified or used for the first time, the acceleration structure needs to be built or rebuilt. This can be achieved with the following code:
```C#
rtAccelStruct.Build(cmd, buildScratchBuffer);
```
For more information, refer to [Execute your ray tracing code](execute-shader.md).
## Execute your shader
To execute your shader, call the [`Dispatch`](xref:UnityEngine.Rendering.UnifiedRayTracing.IRayTracingShader.Dispatch(UnityEngine.Rendering.CommandBuffer,UnityEngine.GraphicsBuffer,System.UInt32,System.UInt32,System.UInt32))
method of `IRayTracingShader`.
```C#
rtShader.Dispatch(cmd, traceScratchBuffer, threadCountX, threadCountY, threadCountZ);
```
For more information, refer to [Execute your ray tracing code](execute-shader.md).
## Dispose of your objects
For more information, refer to [Release your ray tracing objects](release-resources.md).
@@ -0,0 +1,95 @@
# Write your ray tracing code
This section guides you through the process of implementing ray tracing logic in a unified ray tracing shader (`.urtshader`).
Follow these steps:
1. Include the UnifiedRayTracing API.
2. Declare the acceleration structure.
3. Define the ray generation function.
4. Define a ray.
5. Retrieve the acceleration structure.
6. Trace the ray.
## Include the UnifiedRayTracing API
At the top of your `.urtshader` add the following statement:
```HLSL
#include "Packages/com.unity.render-pipelines.core/Runtime/UnifiedRayTracing/TraceRayAndQueryHit.hlsl"
```
## Declare the acceleration structure
Declare the acceleration structure binding with the following macro:
```HLSL
UNIFIED_RT_DECLARE_ACCEL_STRUCT(_YourAccelStruct);
```
Ensure that the name you declare here matches the one specified in your C# code when calling [`IRayTracingShader.SetAccelerationStructure`](xref:UnityEngine.Rendering.UnifiedRayTracing.IRayTracingShader.SetAccelerationStructure(UnityEngine.Rendering.CommandBuffer,System.String,UnityEngine.Rendering.UnifiedRayTracing.IRayTracingAccelStruct)).
**Note**: You can declare and use multiple acceleration structures within the same shader.
## Define the ray generation function
This is your kernel function that will be invoked by the GPU for each thread of your dispatch workgrid. It must be defined as follows:
```HLSL
void RayGenExecute(UnifiedRT::DispatchInfo dispatchInfo)
{
}
```
The [`DispatchInfo`](shader-code-reference.md#struct-dispatchinfo) struct provides information about the currently invoked thread. For instance, you can query its location within the workgrid using:
```HLSL
uint3 threadID = dispatchInfo.dispatchThreadID;
```
At this point, you have a valid `.urtshader` file. The next steps involve implementing the ray tracing logic.
## Define a ray
Use the `Ray` struct to define a ray. For example, here is a ray starting at the origin and pointing towards the positive Z-axis:
```HLSL
UnifiedRT::Ray ray;
ray.origin = 0;
ray.direction = float3(0, 0, 1);
ray.tMin = 0;
ray.tMax = 1000.0f;
```
The `tMin` and `tMax` fields define the segment of the ray to be tested against the acceleration structure's primitives.
In mathematical terms, the ray consists of all the points defined as `P = ray.origin + t * ray.direction` where `ray.tMin ≤ t ≤ ray.tMax`.
## Retrieve the acceleration structure
This is achieved with the following macro:
```HLSL
UnifiedRT::RayTracingAccelStruct accelStruct = UNIFIED_RT_GET_ACCEL_STRUCT(_YourAccelStruct);
```
## Trace the ray
Invoke one of the following functions that perform ray tracing: [`TraceRayClosestHit`](shader-code-reference.md#function-tracerayclosesthit) or [`TraceRayAnyHit`](shader-code-reference.md#function-tracerayanyhit).
```HLSL
UnifiedRT::Hit hitResult = UnifiedRT::TraceRayClosestHit(dispatchInfo, accelStruct, 0xFFFFFFFF, ray, 0);
```
The returned [`Hit`](shader-code-reference.md#struct-hit) structure provides geometry information about the found intersection such as the instance ID or the triangle index.
Use `hitResult.IsValid()` to check whether a hit has been found.
## Full shader code example
Here is a complete example of a unified ray tracing shader:
```HLSL
// Include file for the UnifiedRayTracing API functions
#include "Packages/com.unity.render-pipelines.core/Runtime/UnifiedRayTracing/TraceRayAndQueryHit.hlsl"
// Use this macro to declare the acceleration structure binding
UNIFIED_RT_DECLARE_ACCEL_STRUCT(_AccelStruct);
void RayGenExecute(UnifiedRT::DispatchInfo dispatchInfo)
{
UnifiedRT::Ray ray;
ray.origin = 0;
ray.direction = float3(0, 0, 1);
ray.tMin = 0;
ray.tMax = 1000.0f;
UnifiedRT::RayTracingAccelStruct accelStruct = UNIFIED_RT_GET_ACCEL_STRUCT(_AccelStruct);
UnifiedRT::Hit hitResult = UnifiedRT::TraceRayClosestHit(dispatchInfo, accelStruct, 0xFFFFFFFF, ray, 0);
if (hitResult.IsValid())
{
// Handle found intersection
}
}
```
When you create a unified ray tracing shader, Unity prefills the shader with a similar code template.
## Additional resources
- [Create a unified ray tracing shader](create-shader.md)
- [Ray tracing shader code reference](shader-code-reference.md)