@@ -308,85 +308,152 @@ inline uniform float VdbSampler_sample(const VdbSampler *uniform sampler,
308
308
// Value range computation.
309
309
// ---------------------------------------------------------------------------
310
310
311
- inline void extendValueRangeFilterFloat (const void * uniform _grid,
312
- const vec3ui * uniform offset,
313
- uniform uint32 level,
314
- uniform uint32 attributeIndex,
315
- uniform box1f * uniform range)
316
- {
317
- uniform VdbSampler sampler;
318
- memset (&sampler, 0 , sizeof (uniform VdbSampler));
319
- sampler. grid = (const VdbGrid * uniform )_grid;
320
- sampler. maxSamplingDepth = VKL_VDB_NUM_LEVELS - 1 ;
321
- // We set none of the other members as the internal code does not require
322
- // them.
323
-
324
- float vminFilter = pos_inf;
325
- float vmaxFilter = neg_inf;
326
- const uniform uint32 res = vklVdbLevelRes (level);
327
- const VdbGrid * uniform grid = (const VdbGrid * uniform )_grid;
328
- const uniform vec3ui os = * offset;
329
- const uniform int radius = 1 ; // TRILINEAR INTERPOLATION!
330
- // We compute min/max over the voxels (one filter radius) after upper bound.
331
- // These are voxels that can be interpolated into our node, so we must include
332
- // them for conservative value ranges.
333
- foreach (z = - radius... res + radius, y = - radius... res + radius) {
334
- const int32 x = res;
335
- const float sample = VdbSampler_sample (
336
- &sampler, make_vec3i (x + os. x, y + os. y, z + os. z), attributeIndex);
337
- vminFilter = min (vminFilter, sample);
338
- vmaxFilter = max (vmaxFilter, sample);
339
- }
340
- // We only have to go to x = res+radius as we added those voxels above.
341
- foreach (z = - radius... res + radius, x = - radius... res) {
342
- const int32 y = res;
343
- const float sample = VdbSampler_sample (
344
- &sampler, make_vec3i (x + os. x, y + os. y, z + os. z), attributeIndex);
345
- vminFilter = min (vminFilter, sample);
346
- vmaxFilter = max (vmaxFilter, sample);
347
- }
348
- // We only have to go to x = res+radius and y = res+radius as we added those
349
- // voxels above.
350
- foreach (y = - radius... res, x = - radius... res) {
351
- const int32 z = res;
352
- const float sample = VdbSampler_sample (
353
- &sampler, make_vec3i (x + os. x, y + os. y, z + os. z), attributeIndex);
354
- vminFilter = min (vminFilter, sample);
355
- vmaxFilter = max (vmaxFilter, sample);
356
- }
357
-
358
- range-> lower = min (reduce_min (vminFilter), range-> lower);
359
- range-> upper = max (reduce_max (vmaxFilter), range-> upper);
360
- }
361
-
362
311
/*
363
- * Compute the value range on the given tile
312
+ * Compute the value range for the given node and index range.
364
313
*/
365
- export void EXPORT_UNIQUE (VdbSampler_valueRangeTileFloat,
366
- const void * uniform _grid,
367
- const vec3ui * uniform offset,
368
- uniform uint32 level,
369
- uniform uint32 attributeIndex,
370
- uniform box1f * uniform range)
314
+ inline uniform box1f
315
+ VdbSampler_computeNodeValueRange (const VdbGrid * uniform grid,
316
+ uniform uint64 voxel,
317
+ const uniform vec2ui &rangeX,
318
+ const uniform vec2ui &rangeY,
319
+ const uniform vec2ui &rangeZ,
320
+ uniform uint32 attributeIndex)
371
321
{
372
- range-> lower = pos_inf;
373
- range-> upper = neg_inf;
374
- extendValueRangeFilterFloat (_grid, offset, level, attributeIndex, range);
322
+ const uniform VKLFormat leafFormat = vklVdbVoxelIsLeafPtr (voxel)
323
+ ? vklVdbVoxelLeafGetFormat (voxel)
324
+ : VKL_FORMAT_INVALID ;
325
+ const void * uniform leafPtr = vklVdbVoxelLeafGetPtr (voxel);
326
+ const uniform float background = 0.f ;
327
+ uniform box1f valueRange = make_box1f (background, background);
328
+
329
+ switch (leafFormat) {
330
+ case VKL_FORMAT_TILE :
331
+ valueRange. lower = VdbSampler_sampleTileFloatLeaf (
332
+ ((const Data1D * uniform )leafPtr), attributeIndex);
333
+ valueRange. upper = valueRange. lower;
334
+ break ;
335
+ case VKL_FORMAT_CONSTANT_ZYX :
336
+ valueRange = make_box1f (pos_inf, neg_inf);
337
+ if (grid-> allLeavesCompact) {
338
+ for (uniform unsigned int x = rangeX. x; x < rangeX. y; ++ x) {
339
+ for (uniform unsigned int y = rangeY. x; y < rangeY. y; ++ y) {
340
+ for (uniform unsigned int z = rangeZ. x; z < rangeZ. y; ++ z) {
341
+ const uniform float sample =
342
+ VdbSampler_sampleConstantFloatLeafCompact (
343
+ ((const uniform Data1D * uniform )leafPtr),
344
+ make_vec3ui (x, y, z),
345
+ attributeIndex);
346
+ extend (valueRange, sample);
347
+ }
348
+ }
349
+ }
350
+ } else {
351
+ for (uniform unsigned int x = rangeX. x; x < rangeX. y; ++ x) {
352
+ for (uniform unsigned int y = rangeY. x; y < rangeY. y; ++ y) {
353
+ for (uniform unsigned int z = rangeZ. x; z < rangeZ. y; ++ z) {
354
+ const uniform float sample =
355
+ VdbSampler_sampleConstantFloatLeafStrided (
356
+ ((const uniform Data1D * uniform )leafPtr),
357
+ make_vec3ui (x, y, z),
358
+ attributeIndex);
359
+ extend (valueRange, sample);
360
+ }
361
+ }
362
+ }
363
+ }
364
+ break ;
365
+ default :
366
+ break ;
367
+ }
368
+
369
+ return valueRange;
375
370
}
376
371
377
372
/*
378
373
* Compute the value range on the given constant float leaf.
379
374
*/
380
- export void EXPORT_UNIQUE (VdbSampler_valueRangeConstantFloat ,
375
+ export void EXPORT_UNIQUE (VdbSampler_computeValueRange ,
381
376
const void * uniform _grid,
382
- const vec3ui * uniform offset ,
377
+ const vec3ui * uniform centerNodeOffset ,
383
378
uniform uint32 level,
384
379
uniform uint32 attributeIndex,
385
380
uniform box1f * uniform range)
386
381
{
382
+ const VdbGrid * uniform grid = (const VdbGrid * uniform )_grid;
383
+
384
+ // We need to consider voxels outside this node in the value range because of
385
+ // reconstruction filter support.
386
+ //
387
+ // In particular, we support filters that use up to a 4x4x4 neighborhood.
388
+ //
389
+ // In the following 1D illustration, we show voxels in the current leaf node
390
+ // marked as a '#'. We also show voxels from neighboring nodes, and
391
+ // mark those that could be used for interpolation with a '?'.
392
+ //
393
+ // | | | | | | | |?|#|#|#|#|#|#|#|#|?|?| | | | | | |
394
+ //
395
+ // We therefore iterate over a 3x3x3 neighborhood of nodes and compute the
396
+ // value range over the following voxel range (in each dimension):
397
+ //
398
+ // "previous node" : [VKL_VDB_RES_LEAF - 1, VKL_VDB_RES_LEAF[
399
+ // "central node" : [0, VKL_VDB_RES_LEAF[
400
+ // "next node" : [0, 2[
401
+ //
402
+ // Note that the upper limit is exclusive. In 3D, each dimension follows
403
+ // the same pattern.
404
+ //
405
+ // The following array encodes the iteration range for the previous,
406
+ // central, and next leaf node:
407
+ const uniform vec2ui voxelRange[] = {
408
+ make_vec2ui (VKL_VDB_RES_LEAF - 1 , VKL_VDB_RES_LEAF ),
409
+ make_vec2ui (0 , VKL_VDB_RES_LEAF ),
410
+ make_vec2ui (0 , 2 )
411
+ };
412
+
387
413
range-> lower = pos_inf;
388
414
range-> upper = neg_inf;
389
- extendValueRangeFilterFloat (_grid, offset, level, attributeIndex, range);
415
+
416
+ uniform VdbSampler sampler;
417
+ memset (&sampler, 0 , sizeof (uniform VdbSampler));
418
+ sampler. grid = (const VdbGrid * uniform )_grid;
419
+ sampler. maxSamplingDepth = VKL_VDB_NUM_LEVELS - 1 ;
420
+
421
+ // Iterate over a 3x3x3 neighborhood of leaf nodes, and compute the value
422
+ // range for each of those nodes.
423
+ for (uniform int ix = 0 ; ix < 3 ; ++ ix) {
424
+ for (uniform int iy = 0 ; iy < 3 ; ++ iy) {
425
+ for (uniform int iz = 0 ; iz < 3 ; ++ iz) {
426
+ // This is the offset of the current node relative to the central node.
427
+ const uniform vec3i nodeOffset =
428
+ make_vec3i ((ix - 1 ) * VKL_VDB_RES_LEAF ,
429
+ (iy - 1 ) * VKL_VDB_RES_LEAF ,
430
+ (iz - 1 ) * VKL_VDB_RES_LEAF );
431
+
432
+ // *centerNodeOffset is relative to the rootOrigin, but
433
+ // VdbSampler_traverse expects an index space coordinate.
434
+ const uniform vec3i nodeOrigin = make_vec3i (
435
+ grid-> rootOrigin. x + centerNodeOffset-> x + nodeOffset. x,
436
+ grid-> rootOrigin. y + centerNodeOffset-> y + nodeOffset. y,
437
+ grid-> rootOrigin. z + centerNodeOffset-> z + nodeOffset. z
438
+ );
439
+
440
+ uniform uint64 voxel;
441
+ uniform vec3ui domainOffset;
442
+ VdbSampler_traverse (&sampler, nodeOrigin, voxel, domainOffset);
443
+
444
+ const uniform range1f nodeValueRange =
445
+ VdbSampler_computeNodeValueRange (grid,
446
+ voxel,
447
+ voxelRange[ix],
448
+ voxelRange[iy],
449
+ voxelRange[iz],
450
+ attributeIndex);
451
+
452
+ range-> lower = min (range-> lower, nodeValueRange. lower);
453
+ range-> upper = max (range-> upper, nodeValueRange. upper);
454
+ }
455
+ }
456
+ }
390
457
}
391
458
392
459
// ---------------------------------------------------------------------------
0 commit comments