Skip to content

Commit c904134

Browse files
author
kevyuu
committed
Return materialId instead of materialPacked from rchit
1 parent cca8f72 commit c904134

File tree

5 files changed

+155
-106
lines changed

5 files changed

+155
-106
lines changed

71_RayTracingPipeline/app_resources/common.hlsl

Lines changed: 132 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ struct SProceduralGeomInfo
7575
float32_t radius;
7676
};
7777

78+
7879
struct STriangleGeomInfo
7980
{
8081
MaterialPacked material;
@@ -154,26 +155,57 @@ struct RayLight
154155
float32_t outIntensity;
155156
};
156157

157-
struct ProceduralHitAttribute
158-
{
159-
MaterialPacked material;
160-
float32_t3 center;
161-
};
162-
163-
164158
#ifdef __HLSL_VERSION
165159

166160
struct [raypayload] OcclusionPayload
167161
{
168162
float32_t attenuation : read(caller) : write(caller, anyhit);
169163
};
170164

165+
struct MaterialId
166+
{
167+
const static uint32_t PROCEDURAL_FLAG = (1 << 31);
168+
const static uint32_t PROCEDURAL_MASK = ~PROCEDURAL_FLAG;
169+
170+
uint32_t data;
171+
172+
static MaterialId createProcedural(uint32_t index)
173+
{
174+
MaterialId id;
175+
id.data = index | PROCEDURAL_FLAG;
176+
return id;
177+
}
178+
179+
static MaterialId createTriangle(uint32_t index)
180+
{
181+
MaterialId id;
182+
id.data = index;
183+
return id;
184+
}
185+
186+
uint32_t getMaterialIndex()
187+
{
188+
return data & PROCEDURAL_MASK;
189+
}
190+
191+
bool isHitProceduralGeom()
192+
{
193+
return data & PROCEDURAL_FLAG;
194+
}
195+
};
196+
171197
struct [raypayload] PrimaryPayload
172198
{
173-
MaterialPacked material : read(caller) : write(closesthit);
174199
float32_t3 worldNormal : read(caller) : write(closesthit);
175200
float32_t rayDistance : read(caller) : write(closesthit, miss);
176201
float32_t alphaThreshold : read(closesthit, anyhit) : write(caller);
202+
MaterialId materialId : read(caller) : write(closesthit);
203+
204+
};
205+
206+
struct ProceduralHitAttribute
207+
{
208+
float32_t3 center;
177209
};
178210

179211
enum ObjectType : uint32_t // matches c++
@@ -213,6 +245,98 @@ float32_t3 computeSpecular(Material mat, float32_t3 view_dir,
213245

214246
return float32_t3(mat.specular * specular);
215247
}
248+
249+
float3 unpackNormals3x10(uint32_t v)
250+
{
251+
// host side changes float32_t3 to EF_A2B10G10R10_SNORM_PACK32
252+
// follows unpacking scheme from https://github.com/KhronosGroup/SPIRV-Cross/blob/main/reference/shaders-hlsl/frag/unorm-snorm-packing.frag
253+
int signedValue = int(v);
254+
int3 pn = int3(signedValue << 22, signedValue << 12, signedValue << 2) >> 22;
255+
return clamp(float3(pn) / 511.0, -1.0, 1.0);
256+
}
257+
258+
float32_t3 fetchVertexNormal(int instID, int primID, STriangleGeomInfo geom, float2 bary)
259+
{
260+
uint idxOffset = primID * 3;
261+
262+
const uint indexType = geom.indexType;
263+
const uint vertexStride = geom.vertexStride;
264+
265+
const uint32_t objType = geom.objType;
266+
const uint64_t indexBufferAddress = geom.indexBufferAddress;
267+
268+
uint i0, i1, i2;
269+
switch (indexType)
270+
{
271+
case 0: // EIT_16BIT
272+
{
273+
i0 = uint32_t(vk::RawBufferLoad < uint16_t > (indexBufferAddress + (idxOffset + 0) * sizeof(uint16_t), 2u));
274+
i1 = uint32_t(vk::RawBufferLoad < uint16_t > (indexBufferAddress + (idxOffset + 1) * sizeof(uint16_t), 2u));
275+
i2 = uint32_t(vk::RawBufferLoad < uint16_t > (indexBufferAddress + (idxOffset + 2) * sizeof(uint16_t), 2u));
276+
}
277+
break;
278+
case 1: // EIT_32BIT
279+
{
280+
i0 = vk::RawBufferLoad < uint32_t > (indexBufferAddress + (idxOffset + 0) * sizeof(uint32_t));
281+
i1 = vk::RawBufferLoad < uint32_t > (indexBufferAddress + (idxOffset + 1) * sizeof(uint32_t));
282+
i2 = vk::RawBufferLoad < uint32_t > (indexBufferAddress + (idxOffset + 2) * sizeof(uint32_t));
283+
}
284+
break;
285+
default: // EIT_NONE
286+
{
287+
i0 = idxOffset;
288+
i1 = idxOffset + 1;
289+
i2 = idxOffset + 2;
290+
}
291+
}
292+
293+
const uint64_t normalVertexBufferAddress = geom.vertexBufferAddress + s_offsetsToNormalBytes[objType];
294+
float3 n0, n1, n2;
295+
switch (objType)
296+
{
297+
case OT_CUBE:
298+
{
299+
uint32_t v0 = vk::RawBufferLoad < uint32_t > (normalVertexBufferAddress + i0 * vertexStride, 2u);
300+
uint32_t v1 = vk::RawBufferLoad < uint32_t > (normalVertexBufferAddress + i1 * vertexStride, 2u);
301+
uint32_t v2 = vk::RawBufferLoad < uint32_t > (normalVertexBufferAddress + i2 * vertexStride, 2u);
302+
303+
n0 = normalize(nbl::hlsl::spirv::unpackSnorm4x8(v0).xyz);
304+
n1 = normalize(nbl::hlsl::spirv::unpackSnorm4x8(v1).xyz);
305+
n2 = normalize(nbl::hlsl::spirv::unpackSnorm4x8(v2).xyz);
306+
}
307+
break;
308+
case OT_SPHERE:
309+
case OT_CYLINDER:
310+
case OT_ARROW:
311+
case OT_CONE:
312+
{
313+
uint32_t v0 = vk::RawBufferLoad < uint32_t > (normalVertexBufferAddress + i0 * vertexStride);
314+
uint32_t v1 = vk::RawBufferLoad < uint32_t > (normalVertexBufferAddress + i1 * vertexStride);
315+
uint32_t v2 = vk::RawBufferLoad < uint32_t > (normalVertexBufferAddress + i2 * vertexStride);
316+
317+
n0 = normalize(unpackNormals3x10(v0));
318+
n1 = normalize(unpackNormals3x10(v1));
319+
n2 = normalize(unpackNormals3x10(v2));
320+
}
321+
break;
322+
case OT_RECTANGLE:
323+
case OT_DISK:
324+
case OT_ICOSPHERE:
325+
default:
326+
{
327+
n0 = normalize(vk::RawBufferLoad <
328+
float3 > (normalVertexBufferAddress + i0 * vertexStride));
329+
n1 = normalize(vk::RawBufferLoad <
330+
float3 > (normalVertexBufferAddress + i1 * vertexStride));
331+
n2 = normalize(vk::RawBufferLoad <
332+
float3 > (normalVertexBufferAddress + i2 * vertexStride));
333+
}
334+
}
335+
336+
float3 barycentrics = float3(0.0, bary);
337+
barycentrics.x = 1.0 - barycentrics.y - barycentrics.z;
338+
return normalize(barycentrics.x * n0 + barycentrics.y * n1 + barycentrics.z * n2);
339+
}
216340
#endif
217341

218342
namespace nbl

71_RayTracingPipeline/app_resources/raytrace.rchit.hlsl

Lines changed: 2 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -2,97 +2,6 @@
22

33
[[vk::push_constant]] SPushConstants pc;
44

5-
float3 unpackNormals3x10(uint32_t v)
6-
{
7-
// host side changes float32_t3 to EF_A2B10G10R10_SNORM_PACK32
8-
// follows unpacking scheme from https://github.com/KhronosGroup/SPIRV-Cross/blob/main/reference/shaders-hlsl/frag/unorm-snorm-packing.frag
9-
int signedValue = int(v);
10-
int3 pn = int3(signedValue << 22, signedValue << 12, signedValue << 2) >> 22;
11-
return clamp(float3(pn) / 511.0, -1.0, 1.0);
12-
}
13-
14-
float32_t3 fetchVertexNormal(int instID, int primID, STriangleGeomInfo geom, float2 bary)
15-
{
16-
uint idxOffset = primID * 3;
17-
18-
const uint indexType = geom.indexType;
19-
const uint vertexStride = geom.vertexStride;
20-
21-
const uint32_t objType = geom.objType;
22-
const uint64_t indexBufferAddress = geom.indexBufferAddress;
23-
24-
uint i0, i1, i2;
25-
switch (indexType)
26-
{
27-
case 0: // EIT_16BIT
28-
{
29-
i0 = uint32_t(vk::RawBufferLoad < uint16_t > (indexBufferAddress + (idxOffset + 0) * sizeof(uint16_t), 2u));
30-
i1 = uint32_t(vk::RawBufferLoad < uint16_t > (indexBufferAddress + (idxOffset + 1) * sizeof(uint16_t), 2u));
31-
i2 = uint32_t(vk::RawBufferLoad < uint16_t > (indexBufferAddress + (idxOffset + 2) * sizeof(uint16_t), 2u));
32-
}
33-
break;
34-
case 1: // EIT_32BIT
35-
{
36-
i0 = vk::RawBufferLoad < uint32_t > (indexBufferAddress + (idxOffset + 0) * sizeof(uint32_t));
37-
i1 = vk::RawBufferLoad < uint32_t > (indexBufferAddress + (idxOffset + 1) * sizeof(uint32_t));
38-
i2 = vk::RawBufferLoad < uint32_t > (indexBufferAddress + (idxOffset + 2) * sizeof(uint32_t));
39-
}
40-
break;
41-
default: // EIT_NONE
42-
{
43-
i0 = idxOffset;
44-
i1 = idxOffset + 1;
45-
i2 = idxOffset + 2;
46-
}
47-
}
48-
49-
const uint64_t normalVertexBufferAddress = geom.vertexBufferAddress + s_offsetsToNormalBytes[objType];
50-
float3 n0, n1, n2;
51-
switch (objType)
52-
{
53-
case OT_CUBE:
54-
{
55-
uint32_t v0 = vk::RawBufferLoad < uint32_t > (normalVertexBufferAddress + i0 * vertexStride, 2u);
56-
uint32_t v1 = vk::RawBufferLoad < uint32_t > (normalVertexBufferAddress + i1 * vertexStride, 2u);
57-
uint32_t v2 = vk::RawBufferLoad < uint32_t > (normalVertexBufferAddress + i2 * vertexStride, 2u);
58-
59-
n0 = normalize(nbl::hlsl::spirv::unpackSnorm4x8(v0).xyz);
60-
n1 = normalize(nbl::hlsl::spirv::unpackSnorm4x8(v1).xyz);
61-
n2 = normalize(nbl::hlsl::spirv::unpackSnorm4x8(v2).xyz);
62-
}
63-
break;
64-
case OT_SPHERE:
65-
case OT_CYLINDER:
66-
case OT_ARROW:
67-
case OT_CONE:
68-
{
69-
uint32_t v0 = vk::RawBufferLoad < uint32_t > (normalVertexBufferAddress + i0 * vertexStride);
70-
uint32_t v1 = vk::RawBufferLoad < uint32_t > (normalVertexBufferAddress + i1 * vertexStride);
71-
uint32_t v2 = vk::RawBufferLoad < uint32_t > (normalVertexBufferAddress + i2 * vertexStride);
72-
73-
n0 = normalize(unpackNormals3x10(v0));
74-
n1 = normalize(unpackNormals3x10(v1));
75-
n2 = normalize(unpackNormals3x10(v2));
76-
}
77-
break;
78-
case OT_RECTANGLE:
79-
case OT_DISK:
80-
case OT_ICOSPHERE:
81-
default:
82-
{
83-
n0 = normalize(vk::RawBufferLoad <
84-
float3 > (normalVertexBufferAddress + i0 * vertexStride));
85-
n1 = normalize(vk::RawBufferLoad <
86-
float3 > (normalVertexBufferAddress + i1 * vertexStride));
87-
n2 = normalize(vk::RawBufferLoad <
88-
float3 > (normalVertexBufferAddress + i2 * vertexStride));
89-
}
90-
}
91-
92-
float3 barycentrics = float3(0.0, bary);
93-
barycentrics.x = 1.0 - barycentrics.y - barycentrics.z;
94-
return normalize(barycentrics.x * n0 + barycentrics.y * n1 + barycentrics.z * n2);
95-
}
965

976
[shader("closesthit")]
987
void main(inout PrimaryPayload payload, in BuiltInTriangleIntersectionAttributes attribs)
@@ -103,7 +12,8 @@ void main(inout PrimaryPayload payload, in BuiltInTriangleIntersectionAttributes
10312
const float32_t3 vertexNormal = fetchVertexNormal(instID, primID, geom, attribs.barycentrics);
10413
const float32_t3 worldNormal = normalize(mul(vertexNormal, WorldToObject3x4()).xyz);
10514

106-
payload.material = geom.material;
15+
payload.materialId = MaterialId::createTriangle(instID);
16+
10717
payload.worldNormal = worldNormal;
10818
payload.rayDistance = RayTCurrent();
10919

71_RayTracingPipeline/app_resources/raytrace.rgen.hlsl

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,15 +58,29 @@ void main()
5858
payload.alphaThreshold = nextRandomUnorm(rnd);
5959
TraceRay(topLevelAS, RAY_FLAG_NONE, 0xff, ERT_PRIMARY, 0, EMT_PRIMARY, rayDesc, payload);
6060

61-
if (payload.rayDistance < 0)
61+
const float32_t rayDistance = payload.rayDistance;
62+
if (rayDistance < 0)
6263
{
6364
hitValues += s_clearColor;
6465
continue;
6566
}
6667

67-
const float32_t3 worldPosition = pc.camPos + (camDirection * payload.rayDistance);
68+
const float32_t3 worldPosition = pc.camPos + (camDirection * rayDistance);
6869
const float32_t3 worldNormal = payload.worldNormal;
69-
const Material material = nbl::hlsl::_static_cast<Material>(payload.material);
70+
71+
Material material;
72+
MaterialId materialId = payload.materialId;
73+
// we use negative index to indicate that this is a procedural geometry
74+
if (materialId.isHitProceduralGeom())
75+
{
76+
const MaterialPacked materialPacked = vk::RawBufferLoad<MaterialPacked>(pc.proceduralGeomInfoBuffer + materialId.getMaterialIndex() * sizeof(SProceduralGeomInfo));
77+
material = nbl::hlsl::_static_cast<Material>(materialPacked);
78+
}
79+
else
80+
{
81+
const MaterialPacked materialPacked = vk::RawBufferLoad<MaterialPacked>(pc.triangleGeomInfoBuffer + materialId.getMaterialIndex() * sizeof(STriangleGeomInfo));
82+
material = nbl::hlsl::_static_cast<Material>(materialPacked);
83+
}
7084
RayLight cLight;
7185
cLight.inHitPosition = worldPosition;
7286
CallShader(pc.light.type, cLight);

71_RayTracingPipeline/app_resources/raytrace.rint.hlsl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,16 @@ void main()
3838
const int primID = PrimitiveIndex();
3939

4040
// Sphere data
41-
SProceduralGeomInfo sphere = vk::RawBufferLoad < SProceduralGeomInfo > (pc.proceduralGeomInfoBuffer + primID * sizeof(SProceduralGeomInfo));
41+
SProceduralGeomInfo sphere = vk::RawBufferLoad<SProceduralGeomInfo>(pc.proceduralGeomInfoBuffer + primID * sizeof(SProceduralGeomInfo));
4242

4343
const float32_t tHit = hitSphere(sphere, ray);
4444

4545
ProceduralHitAttribute hitAttrib;
46+
4647
// Report hit point
4748
if (tHit > 0)
4849
{
4950
hitAttrib.center = sphere.center;
50-
hitAttrib.material = sphere.material;
5151
ReportHit(tHit, 0, hitAttrib);
5252
}
5353
}

71_RayTracingPipeline/app_resources/raytrace_procedural.rchit.hlsl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ void main(inout PrimaryPayload payload, in ProceduralHitAttribute attrib)
88
const float32_t3 worldPosition = WorldRayOrigin() + WorldRayDirection() * RayTCurrent();
99
const float32_t3 worldNormal = normalize(worldPosition - attrib.center);
1010

11-
payload.material = attrib.material;
11+
payload.materialId = MaterialId::createProcedural(PrimitiveIndex()); // we use negative value to indicate that this is procedural
12+
1213
payload.worldNormal = worldNormal;
1314
payload.rayDistance = RayTCurrent();
1415

0 commit comments

Comments
 (0)