[DXR] How to access Previous ObjectToWorld Matrix in ClosestHit for Dynamic Motion Vectors?

Hi everyone,

I am currently developing a custom Ray Tracing pipeline in Unity. My goal is to generate several G-Buffer and lighting passes (BaseColor, Normal, Roughness, Metalness, Penumbra, Diffuse, Specular, etc.) to be used as inputs for NVIDIA NRD (Real-time Denoiser) before final composition.

I’ve hit a roadblock regarding Motion Vectors (MV). Currently, my MV pass only works correctly for static geometry (camera movement only). I am struggling to calculate proper Motion Vectors for dynamic/moving objects because I cannot find a way to access the previous frame’s ObjectToWorld matrix inside the ClosestHit shader.

In the standard rasterization pipeline, we usually have unity_MatrixPreviousM, but this doesn’t seem to be automatically available or populated in the Ray Tracing ClosestHit shaders.
My questions are:

Is there a built-in way in Unity’s DXR implementation to retrieve the previous transform for a specific instance?

If not, what is the best practice for passing this data?

Any advice, code snippets, or architectural suggestions would be greatly appreciated!

Thanks in advance!

Hi!

We have internal tests for using motion vectors in closest hit shaders so it’s expected to work.
Are you using unity_MatrixPreviousM in a .shader file?
Normally you should have a Camera in the scene and set DepthTextureMode.MotionVectors bit into Camera.depthTextureMode. For example:

// Enable motion vectors on your camera by attaching a script using this code.
private void OnEnable()
{
    GetComponent<Camera>().depthTextureMode = DepthTextureMode.Depth | DepthTextureMode.MotionVectors;
}

DepthTextureMode.MotionVectors will instruct Unity to keep track of the latest world matrix which will be set into unity_MatrixPreviousM. Let me know if you can’t get it working, I can make a small sample for you.

Thank you so much for the reply, it works now!

By the way, does Unity have any plans to support DX12 Bindless?

I was looking through the git commit history of the NVIDIA NRD Sample and noticed that they initially used the Ray Tracing Pipeline, but later switched entirely to Compute Shaders + Inline Ray Tracing + Bindless.

I suspect that using Inline Ray Tracing combined with bindless texture sampling might offer better performance than the standard Ray Tracing Pipeline?

Hi!

There’s internal interest for bindless as well but there’s no clearly defined timeline for supporting it.
Inline ray tracing is designed to work well with bindless graphics. On NVIDIA GPUs, ray tracing pipelines can offer better performance because they implement shader execution reordering which can bring noticeable perf improvements but I believe it depends on the complexity of the effect you want to implement for example ray traced shadows is less complex to implement than ray traced reflections because you don’t have to deal with all materials types (material evaluation + lighting model).

Thanks for the articles you mentioned; they were extremely helpful.

I have one more question. Since Unity currently has no plans to support Bindless, I intend to implement it via a native plugin.

However, I haven’t found a function similar to RenderTexture.GetNativeTexturePtr or GraphicsBuffer.GetNativeBufferPtr to retrieve the native pointer for the RayTracingAccelerationStructure.

Is there any way to retrieve the native pointer for RayTracingAccelerationStructure? Or could this be exposed in a future update?

Indeed, it looks like there’s no access to the native buffer of the RTAS object but this can be added easily since internally we bind the top-level acceleration structure to shaders which it’s just a GraphicsBuffer. I’ll add a task to the list and let you know when it’s available. Some details - the underlying GraphicsBuffer can be recreated at any point during the lifetime of the RTAS to fit the amount of ray tracing instances added so it won’t be a good idea to store the GetNativeBufferPtr result anywhere.

Hi @KuanMi

The RayTracingAccelerationStructure.GetNativeBufferPtr will be available starting with Unity 6.5 a7.