[BUG] NanoVDB, no generic way to sample quantized float values in PNanoVDB.h
Environment
Operating System: Windows 2019 Version / Commit SHA: NanoVDB 32.3, OpenVDB 8.1 Other: C++, HLSL
Describe the bug
While testing the quantized NanoVDB floating point values (excellent addition to the library by the way), I noticed there was no "simple" and generic way to read floating point values. Although it is possible to abstract all the C++-side code and be floating point format agnostic, reading values in the HLSL shader requires some hard-coded changes, depending on the format.
For example when using pnanovdb_hdda_zero_crossing function (PNanoVDB.h), it is not ready yet for quantized models. I'm expecting this function to be optimal, and to keep using it to render my level sets, but it needs some adjustements to work correctly.
To Reproduce
Steps to reproduce the behavior:
- Load a Fp4, Fp8, Fp16, FpN quantized model in the viewer
- Use the HLSL mode (PNanoVDB.h)
- Model is filled with holes
Note that I haven't tried using the viewer for this, as it does not support a HLSL mode yet, and the GLSL mode doesn't even work on my machine anymore (it used to work with 29.3). Feel free to contact me for additional details if needed.
Expected behavior
- Ideally, I would like an optimal and easy way to sample floating point values in a grid/root, without having to hard-code it (and without shader variations)
- pnanovdb_hdda_zero_crossing from PNanoVDB.h should work with all floating point formats
Proposed solution
A sub-optimal but generic solution could be along the lines of:
PNANOVDB_FORCE_INLINE float pnanovdb_root_read_float_typed(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_address_t address, PNANOVDB_IN(pnanovdb_coord_t) ijk, pnanovdb_uint32_t level)
{
float ret;
if (level == 0 && grid_type != PNANOVDB_GRID_TYPE_FLOAT)
{
if (grid_type == PNANOVDB_GRID_TYPE_FPN)
{
ret = pnanovdb_leaf_fpn_read_float(buf, address, ijk);
}
else
{
ret = pnanovdb_leaf_fp_read_float(buf, address, ijk, grid_type - PNANOVDB_GRID_TYPE_FP4 + 2u);
}
}
else
{
ret = pnanovdb_read_float(buf, address);
}
return ret;
}
And adapting the pnanovdb_hdda_zero_crossing function would look like:
pnanovdb_address_t address = pnanovdb_readaccessor_get_value_address_and_level(grid_type, buf, acc, PNANOVDB_REF(ijk), PNANOVDB_REF(level));
float v0 = pnanovdb_root_read_float_typed(grid_type, buf, address, ijk, level);
instead of the current:
pnanovdb_address_t address = pnanovdb_readaccessor_get_value_address(PNANOVDB_GRID_TYPE_FLOAT, buf, acc, PNANOVDB_REF(ijk));
float v0 = pnanovdb_read_float(buf, address);
Thanks - we're looking into this now