Hi again community,
I actually was on the right trails but had made some mistakes on the way.
For those who might be interested, here is how I included ray-traced procedural geometries in the HDRP, so that those procedural geometries correctly interact with other ray-traced geometries (reflexion, shadows, …):
Unity editor preparation steps:
0) Configure the project for HDRP with ray-tracing enabled
1) Create a 3D object, for example a cube.
2) Create a material using the HDRP/lit shader, and assign the material to the object.
3) On the Material, check the “Recursive rendering” box so that this geometry is rendered through ray-tracing.
4) On the Mesh Renderer, check the box “Ray Trace Procedurally”. Unity will automatically configure the corresponding Acceleration Structure to leverage its “intersection” shader instead of the mesh triangles. The object will disappear for now since we haven’t specify the “intersection” shader yet.
Shader steps:
5) We need to modify the shader: create a new shader which is a copy of the HDRP/lit shader, rename it, and assign it to the material.
6 - quick and dirty) To check the configuration so far or just validate it can work, add below code at the end of the HLSL program of the “ForwardDXR” pass.
[shader("intersection")]
void IntersectionMain()
{
float3 or = ObjectRayOrigin();
float3 dir = normalize(ObjectRayDirection());
AttributeData attr;
attr.barycentrics = float2(0, 0);
float r = 0.35;
float3 toCenter = float3(0., 0., 0.)-ObjectRayOrigin();
float dirCos = dot(normalize(toCenter), dir);
float minCos = cos(asin(r / length(toCenter)));
if (dirCos > minCos) {
ReportHit(1, 0, attr);
}
}
A sphere should be displayed in the center of the object, and it should be reflected by other ray-traced objects. However, since the shader expects a ray / triangle intersection, the shade is messed up (normals in particular are completely wrong).
6 - alternative “cleaner” way) Actually only the intersection code of the shader should be updated, so create a .hlsl file and replace below “include” line by your new file:
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RaytracingIntersection.hlsl"
Then in this file you can use the content of the initial “RaytracingIntersection.hlsl” as basis, add your intersection shader and update the rest of the file accordingly (in particular the normal computation).
Here is an example to get a simple sphere:
// Modify AttributeData struct like this:
struct AttributeData
{
// Barycentric value of the intersection
float2 barycentrics; // Makes sense in ray / triangle intersection, not really there
float3 normalOS;
};
// Modify GetCurrentIntersectionVertex like this:
void GetCurrentIntersectionVertex(AttributeData attributeData, out IntersectionVertex outVertex) {
outVertex.normalOS = attributeData.normalOS;
float3 rayDir = float3(0,1,0); // The HDRP does not provide RayIntersection to this function :(
outVertex.tangentOS = float4(normalize(cross(cross(attributeData.normalOS, rayDir), attributeData.normalOS)), 1);
outVertex.texCoord0 = 0.0;
outVertex.texCoord1 = 0.0;
outVertex.texCoord2 = 0.0;
outVertex.texCoord3 = 0.0;
outVertex.color = 0.0;
}
// Add the intersection shader:
float HitSphere(float3 sphereCenter, float sphereRadius, float3 rayOrigin, float3 rayDirection) {
float3 oc = rayOrigin - sphereCenter;
float a = dot(rayDirection, rayDirection);
float b = 2.0 * dot(oc, rayDirection);
float c = dot(oc,oc) - sphereRadius*sphereRadius;
float discriminant = b*b - 4*a*c;
if (discriminant < 0.0) {
return -1.0;
}
else {
float numerator = -b - sqrt(discriminant);
return numerator > 0.0 ? numerator / (2.0 * a) : -1;
}
}
[shader("intersection")]
void IntersectionMain()
{
float3 or = ObjectRayOrigin();
float3 dir = normalize(ObjectRayDirection());
AttributeData attr;
attr.barycentrics = float2(0, 0);
float3 sphereCenter = 0.;
float sphereRadius = 0.15 * abs(frac(_Time.y/2)-0.5) + 0.2; // Make the radius vary with time just for fun (the procedural geometry is raytraced each frame)
float hitDist = HitSphere(sphereCenter, sphereRadius, or, dir);
if (hitDist >= 0.) {
attr.normalOS = normalize(or + hitDist * dir - sphereCenter);
ReportHit(hitDist, 0, attr);
}
}
Note that shadow ray-tracing is disabled on this screenshot, thus we see a cube shadow on the floor
(I don’t have an RTX graphic card :'()
Of course it only gets interesting when using a less trivial intersection shader, like a ray-march based on Signed Distance Fields:

Nothing impressive but that’s the idea…
I hope it can help some people, since such a trivial example would have been greatly appreciated!
Maybe there could be a specific scene in the SmallOfficeRayTracing project example?
Anyway, let me know if there is a better or cleaner way to do this!
In particular it would be great if there was an easier way to override the RaytracingIntersection.hlsl code, through the ShaderGraph for example (which seems to be the prefered way to edit shaders in HDRP).