Community Tutorial: How to Create a Custom Ray Tracing Shader as a Plugin

Ok, I think I figured out what is missing in the tutorial
As I thought, it totally misses the geometry binds to the hit shaders and to do that we need

  1. bind geometry from the current view to the shader
  2. set it to the hit shader group using RHICmdList.SetRayTracingHitGroups()

in Engine/Plugins/FX/Niagara/Source/NiagaraShader/Private/NiagaraAsyncGpuTraceProviderHwrt.cpp there is a nice piece of code for doing that

static void BindNiagaraRayTracingMeshCommands(...)
{


FConcurrentLinearBulkObjectAllocator Allocator;
FRayTracingLocalShaderBindings* Bindings = nullptr;
FRHIUniformBuffer** UniformBufferArray = nullptr;

if (RHICmdList.Bypass())
{
	Bindings = reinterpret_cast<FRayTracingLocalShaderBindings*>(Allocator.Malloc(MergedBindingsSize, alignof(FRayTracingLocalShaderBindings)));
	UniformBufferArray = reinterpret_cast<FRHIUniformBuffer**>(Allocator.Malloc(UniformBufferArraySize, alignof(FRHIUniformBuffer*)));
}
else
{
	Bindings = reinterpret_cast<FRayTracingLocalShaderBindings*>(RHICmdList.Alloc(MergedBindingsSize, alignof(FRayTracingLocalShaderBindings)));
	UniformBufferArray = reinterpret_cast<FRHIUniformBuffer**>(RHICmdList.Alloc(UniformBufferArraySize, alignof(FRHIUniformBuffer*)));
}

    ...

	for (const FRayTracingShaderBindingData DirtyShaderBinding : DirtyShaderBindings)
{
	const FRayTracingMeshCommand& MeshCommand = *DirtyShaderBinding.RayTracingMeshCommand;

	FRayTracingLocalShaderBindings Binding = {};
	Binding.RecordIndex = DirtyShaderBinding.SBTRecordIndex;
	Binding.Geometry = DirtyShaderBinding.RayTracingGeometry;
	Binding.SegmentIndex = MeshCommand.GeometrySegmentIndex;
	Binding.UserData = PackUserData(MeshCommand);
	Binding.UniformBuffers = UniformBufferArray;
	Binding.NumUniformBuffers = NumUniformBuffers;

	Bindings[BindingIndex] = Binding;
	BindingIndex++;
}

RHICmdList.SetRayTracingHitGroups(
	SBT,
	Pipeline,
	NumTotalBindings,
	Bindings,
	bCopyDataToInlineStorage);
RHICmdList.SetRayTracingMissShader(SBT, 0, Pipeline, 0 /* ShaderIndexInPipeline */, 0, nullptr, 0);
RHICmdList.CommitShaderBindingTable(SBT);
}

After implementing this part (just copy this function to RayGenTest class and call it after setting the pipeline), and all works as expected :slight_smile:
This is my custom hw RT shader that set depth (aka normalized RayCurrentT value) as output color

After doing that, I guess you’re free to pick and use any payload you want

1 Like