@@ -75,6 +75,7 @@ struct SProceduralGeomInfo
7575 float32_t radius;
7676};
7777
78+
7879struct 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
166160struct [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+
171197struct [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
179211enum 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
218342namespace nbl
0 commit comments