Closed wi-re closed 4 years ago
Yep, this is a problem, thanks for pointing this out! It looks like possibly a rendering issue rather than an OpenVDB issue so far. Maybe this might be due to how 1.1.1 now reads the transform from the OpenVDB file, so perhaps the light's now placed inside the volume or near the bunny's feet?
Interessting Idea, to test that i quickly tried setting the light to the same position as the camera
cam->setOrbit ( Vector3DF(-10,30,0), Vector3DF(14.2f,15.3f,18.0f), 130, 1.0f );
and
lgt->setOrbit ( Vector3DF(-10,30,0), Vector3DF(14.2f, 15.3f, 18.0f), 130, 1.0 );
The result I'm getting is this:
Which is very similar to the original light position, but different, i.e. the side is shaded slightly different in the large spot area
So it's probably not a problem of that. The loadVDB function simply takes the voxel size of the vdb file and applies it as a linear transform and the whole model is offset so that it's in positive space
voffset = mVoxMin * -1; // offset to positive space (hack)
and the camera and light should be somewhere outside of the first octant with the negative. Further, modifying the levelset rendering function to assign the normal to the color, i.e. clr = float4{ norm.x*0.5f + 0.5f, norm.y * 0.5f + 0.5f, norm.z * 0.5f + 0.5f ,1.f};
yields the following image:
So there are certainly some issues with the geometry itself, which seem to follow some regular structure (at least in parts)
Thanks! What I've got so far is that there's one bug where the light and the camera are in different coordinate spaces when the transformation matrix isn't the identity (in this case, it's a scaling matrix of 1/20 in each axis), and another bug where the ray direction wasn't of unit length (in this case, it had length 20), causing volume undersampling. I'm working on fixing the gridline artifacts at the moment - my best guess is that they might be due to not updating the apron correctly, though I'm not 100% sure on that yet.
Scaling the VDB file to have a voxel size of 1 (forcing the transform matrix to be an identity matrix) seems to help in avoiding many of the artifacts but still leaves some amount of gridline artifacts Which seem to be primarily aligned with the ray direction. Manually moving the vdb model so that the minimum voxel position (-24 -8 -16) is on the origin (0 0 0) makes no difference to the result (which should align the index space of the vdb file exactly with the gvdb index space and avoid issues caused by the offsetting of the read leaf nodes)
OK, I think I've finally figured out what was going on here! Fix coming soon.
The gridline artifacts are in part due to the switch to using texture and surface objects instead of using (deprecated) texture and surface references. The texture references GVDB 1.1 used used point filtering by default, while the new texture objects use linear filtering with wrapping. Because kernelCopyTexZYX (which is used to copy bricks from the VDB volume to the GVDB volume) samples at the corners of voxels instead of the centers of voxels, voxels on the face of each brick are being averaged with voxels on the other side of the brick, resulting in the gridline discontinuities you can see every 8 voxels here.
(Postscript: Checking further down the pipeline as well and backporting the fixed SaveVBX code, this makes it so that the two versions' .vbx files match up as well except for the transformation matrix.)
Hi Rene,
I've just pushed a commit that should fix this issue - here's what the output from gImportVDB should look like now! It looks like it also fixes the shadow undersampling issue that you can see on the side of the bunny. Please try this out when you get the chance and let me know if this fixes your issue.
There's more information in dae0e22f, but briefly, there wound up being four issues: the default filter mode was changed to linear from point sampling (I changed it back), SetSteps uses application-space units (so scaling the volume wound up causing the sample to undersample; the values passed to SetSteps have been changed, since this avoids changing how the API works at the moment, although I think this might be revisited in the future), lights were in the wrong coordinate space (GVDB now converts to index space when preparing to render), and the value of epsilon
introduced in 07fa281 wound up being too small for the size of this volume (I may also be revisiting GVDB's HDDA in the future).
This commit also adds some fixes for building with OpenVDB 7.0 and vcpkg - it looks like there was some work to rename the debug OpenVDB library and DLL, but it wasn't quite finished, so the README now includes a workaround for that.
Thanks again!
Hey,
I just checked out the current github version and it also works the same for me. Loading from the saved vbx file (i.e. via gInteractiveGL) also works properly now. Just to make sure I get how this import works, the process to actually load and query a openvdb volume via gvdb would be:
LoadVDB
, which first loads the file via openvdb and iterates over the leafs to find the mVoxMin
and mVoxMax
values (in vdb space coordinates)voffset
value to the inverse of mVoxMin
to ensure all leaves are in positive coordinate spacemVoxMin
and mVoxMax
to be the position of the first leaf nodeFinishTopology
, which calls Computebounds
, which sets mVoxMin
and mVoxMax
based on the smallest and largest index space coordinates, which also get saved in mObjMin
and mObjMax
voffset
(which is not available after this function is done)prepareVDB
to prepare the device state for the volumePrepareRender
, which sets the XformVDBNode* node = getNodeAtPoint ( gvdb, wpos, &offs, &vmin, &vdel, &nid );
for a position in index space (?) which returns the correct offsets and information to find the correct part of the texture datat = getTrilinear ( gvdb, chan, wpos, offs, vmin, vdel );
with the information from getNodeAtPoint
to get the value of the gvdb volume at this position.To transform from an actual global position to the correct position w.r.t. the vdb file, the position would need to be translated by voffset and then scaled by voxelsize, i.e. SetTransform(-voffset, voxelsize,...)
and not just scaled by voxelsize as is done right now. Finally, the apron makes sure that getGradientLevelSet
(which uses positions offset by .5 voxels in each direction) are in the same brick as the position.
So to summarize: if one was to write their own query function using an imported vdb file the steps would be
cuVDBInfo
as a VDBInfo*
and voxelsize and voffset getNodeAtPoint
with the cuVDBInfo
and the index space position to get the correct brickfloat3 p = offs + (wp-vmin)/vdel;
tex3D<float> ( gvdb->volIn[chan], p.x, p.y, p.z );
getGradient
with p
Yes, this looks about right. For the first set of bullet points, note that LoadVDB
takes care of the steps through and including FinishTopology
. Additionallly, the xform appears to only be used for the rendering functions (it transforms from index/world-space to the application's coordinate space), so if you're querying voxels rather than ray tracing, you might be able to skip calling PrepareRender
.
The coordinate spaces can be a bit confusing at the moment, since voxelsize was removed inside the library itself (i.e. for GVDB, index-space is now the same as world-space), but there's an arbitrary 4x4 (really 3x4, as the fourth component of the output is ignored) matrix for converting from GVDB's space to the space in which you're sending rays, which will include the scaling factor from OpenVDB. It's also confusing because I don't think there's a standardized name for the coordinate space that xform
maps to at the moment - I'm using "application-space" for now. (I'm hoping to clean this up, possibly renaming things to make the coordinate spaces more explicit, in the future.)
The numbered bullet points look good to me!
(Sorry for the delay, just got back to this!)
Thanks for the response, this should close the issue for now and considering more specific problems of using gvdb in my use case I would send you a message directly should any questions arise as these are not really issues related to the library as a whole.
Thanks again for your help!
The sample that's supposed to load an openVDB file and render it to a file is not working in any version past the 3a59e39a2899ccefd3724b6b285f64cdab42ce74 commit (Windows, I have no way to test the sample under Linux). The output of the sample should look like this (image based on output of #3a59e39a2899ccefd3724b6b285f64cdab42ce74 , which is identical to the output shown on the samples page https://developer.nvidia.com/gvdb-samples ) But the result i'm getting on multiple machines (varying GPU architectures, CUDA versions and OS versions) looks like this: However, due to the complexity of the 37ebd2e2a18e3303ce3a688c9de0276c0e9330a8 commit, I cannot find an exact reason as to why this happens.
The output of the program for version 1.11 (not working) is:
The output of the program for version 1.1 (working) is: