Community
Bifrost Forum
Welcome to the Bifrost Forum. This is the place for artists using Bifrost to ask and answer questions, browse popular topics, and share knowledge about creating effects procedurally using Bifrost. You can also visit the Bifrost Community on AREA to download an array of ready-to-use graphs, read Bifrost news and updates, and find the latest tutorials.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

"Voxelising" volumes in Bifrost

4 REPLIES 4
SOLVED
Reply
Message 1 of 5
bram0101
577 Views, 4 Replies

"Voxelising" volumes in Bifrost

I would like to be able to "voxelise" my volumes in Bifrost. Now, that does sound weird. Volumes are already voxels. But I am talking about a different kind of voxelisation, that is essentially the 3D equivalent of pixelation. Basically, I want to be able to see the voxels, as that is the visual style that I want to achieve.

 

Here is an example of a sphere converted to VDB and rendered in Arnold and the same sphere but then "voxelised":

image.pngimage.png

 

 

 

 

 

 

 

 

 

 

 

 

 

Now, in Arnold I can easily set the interpolation to closest instead of linear or cubic (which is how I made this example). Unfortunately, I do not use Arnold for my normal work and instead use Redshift, which does not have this option. Therefore, I have to "bake" it into the VDB.

 

I have done this before when working directly with OpenVDB in C++ and it basically comes down to resampling the volume with a point interpolator (the exact same as closest and nearest neighbour interpolation) and scaling the voxels down by a factor of 0.25 (quadrupling the resolution). You can see it as taking each voxel and replacing it with 4x4x4 voxels all of the same value.

 

Bifrost does have a volume resample node, but that only has linear and cubic interpolation and not closest interpolation. I tried converting it to fields to then convert it back to a volume, but those nodes also only have linear and cubic interpolation. I thought, maybe I could resample the volume to increase the resolution and then iterate over the voxel data to set each 4x4x4 group to the same value. But, I have no idea how to do that and each time Bifrost just takes hours on hours using up all my system memory and only one core, so I am clearly doing something wrong.

 

So, does anyone know how I could achieve this "voxelised" look with Bifrost?

 

I am using Maya 2022 and the version of Bifrost that is shipped with Maya 2022.

Labels (1)
4 REPLIES 4
Message 2 of 5

Unfortunately, there is no easy way to access the neighbors of a voxel at the moment so it will be difficult to implement a 4x4x4 filter. What you can do, however, is threshold the signed distance function (e.g. for values less than zero, set the fog value to one hundred and to zero otherwise).

 

voxel-smoke.png

 

graph.png

 

Try copy+pasting the following code into a new Bifrost graph:

<sub_root>
    <nodes>
        <node>
            <vnnNode name="convert_to_volume" type="BifrostGraph,Modeling::Converters,convert_to_volume" flag="0">
    <metadatas>
    <metadata name="DisplayMode">
        <value>2</value>
    </metadata>
    <metadata name="LayoutPos">
        <value>-854.5 -293</value>
    </metadata>
</metadatas>
    <ports>
        <port name="geometry" type="array&lt;Amino::Object&gt;" flag="2" is_input="yes" is_fan_in="yes">
            <ports>
                <port name="sphere_mesh" type="Amino::Object" flag="0" is_input="yes"/>
            </ports>
        </port>
        <port name="volume_mode" type="Geometry::Converters::VolumeMode" flag="0" is_input="yes" default_values="0"/>
        <port name="offset" type="float" flag="0" is_input="yes" default_values="0"/>
        <port name="store_level_set" type="bool" flag="0" is_input="yes" default_values="1"/>
        <port name="store_fog_density" type="bool" flag="0" is_input="yes" default_values="0"/>
        <port name="fog_density" type="float" flag="0" is_input="yes" default_values="1"/>
        <port name="min_hole_radius" type="float" flag="0" is_input="yes" default_values="0"/>
        <port name="properties" type="string" flag="0" is_input="yes" default_values="* !point_position !point_normal"/>
        <port name="resolution_mode" type="Geometry::Volume::AutoResolutionType" flag="0" is_input="yes" default_values="1"/>
        <port name="detail_size" type="float" flag="0" is_input="yes" default_values="0.1"/>
        <port name="enable_bandwidth" type="bool" flag="0" is_input="yes" default_values="0"/>
        <port name="bandwidth" type="float" flag="0" is_input="yes" default_values="0"/>
        <port name="volume_subdivision_structure" type="Geometry::Volume::AutoSubdivisionStructure" flag="0" is_input="yes" default_values="0"/>
        <port name="adaptivity" type="Geometry::Volume::Adaptivity" flag="0" is_input="yes" default_values="2"/>
        <port name="adaptivity_property" type="string" flag="0" is_input="yes"/>
        <port name="enable_resolution_bounds" type="bool" flag="0" is_input="yes" default_values="0"/>
        <port name="base_resolution" type="array&lt;Amino::Object&gt;" flag="2" is_input="yes" is_fan_in="yes"/>
        <port name="half_resolution" type="array&lt;Amino::Object&gt;" flag="2" is_input="yes" is_fan_in="yes"/>
        <port name="quarter_resolution" type="array&lt;Amino::Object&gt;" flag="2" is_input="yes" is_fan_in="yes"/>
        <port name="eighth_resolution" type="array&lt;Amino::Object&gt;" flag="2" is_input="yes" is_fan_in="yes"/>
        <port name="volume" type="array&lt;Amino::Object&gt;" flag="0" is_input="no"/>
    </ports>
</vnnNode>
        </node>
        <node>
            <vnnNode name="create_mesh_sphere" type="BifrostGraph,Modeling::Primitive,create_mesh_sphere" flag="0">
    <metadatas>
    <metadata name="DisplayMode">
        <value>2</value>
    </metadata>
    <metadata name="LayoutPos">
        <value>-1178.5 -302</value>
    </metadata>
</metadatas>
    <ports>
        <port name="radius" type="float" flag="0" is_input="yes" default_values="1"/>
        <port name="height_segments" type="int" flag="0" is_input="yes" default_values="14"/>
        <port name="axis_segments" type="int" flag="0" is_input="yes" default_values="20"/>
        <port name="position" type="Math::float3" flag="0" is_input="yes" default_values="0;0;0"/>
        <port name="up_axis" type="Math::float3" flag="0" is_input="yes" default_values="0;1;0"/>
        <port name="base_to_pivot" type="bool" flag="0" is_input="yes" default_values="0"/>
        <port name="sphere_mesh" type="Amino::Object" flag="0" is_input="no"/>
    </ports>
</vnnNode>
        </node>
        <node>
            <vnnNode name="first_in_array" type="BifrostGraph,Core::Array,first_in_array" flag="0">
    <metadatas>
    <metadata name="DisplayMode">
        <value>2</value>
    </metadata>
    <metadata name="LayoutPos">
        <value>-550.5 -294</value>
    </metadata>
</metadatas>
    <ports>
        <port name="array" type="array&lt;Amino::Object&gt;" flag="4096" is_input="yes"/>
        <port name="first" type="Amino::Object" flag="4096" is_input="no"/>
    </ports>
</vnnNode>
        </node>
        <node>
            <vnnNode name="get_geo_property" type="BifrostGraph,Geometry::Properties,get_geo_property" flag="0">
    <metadatas>
    <metadata name="DisplayMode">
        <value>2</value>
    </metadata>
    <metadata name="LayoutPos">
        <value>-283.496 -104</value>
    </metadata>
</metadatas>
    <ports>
        <port name="geometry" type="Amino::Object" flag="0" is_input="yes"/>
        <port name="property" type="string" flag="0" is_input="yes" default_values="voxel_signed_distance"/>
        <port name="type" type="array&lt;float&gt;" flag="4096" is_input="yes" default_values="">
            <metadatas>
                <metadata name="TypeWranglingSuggestedTypes" value="array&lt;float&gt;, array&lt;long&gt;, array&lt;uint&gt;, array&lt;bool&gt;, array&lt;string&gt;, array&lt;Math::float2&gt;, array&lt;Math::float3&gt;, array&lt;Math::float4&gt;, array&lt;Math::float3x3&gt;, array&lt;Math::float4x4&gt;"/>
            </metadatas>
        </port>
        <port name="data" type="array&lt;float&gt;" flag="4096" is_input="no"/>
        <port name="default" type="float" flag="4096" is_input="no"/>
        <port name="target" type="string" flag="4096" is_input="no"/>
    </ports>
</vnnNode>
        </node>
        <node>
            <vnnNode name="greater" type="BifrostGraph,Core::Logic,greater" flag="0">
    <metadatas>
    <metadata name="DisplayMode">
        <value>2</value>
    </metadata>
    <metadata name="LayoutPos">
        <value>-0.0309984 35.4833</value>
    </metadata>
</metadatas>
    <ports>
        <port name="first" type="array&lt;float&gt;" flag="4096" is_input="yes"/>
        <port name="second" type="float" flag="4096" is_input="yes"/>
        <port name="output" type="bool" flag="0" is_input="no"/>
    </ports>
</vnnNode>
        </node>
        <node>
            <vnnNode name="if" type="BifrostGraph,Core::Logic,if" flag="0">
    <metadatas>
    <metadata name="DisplayMode">
        <value>2</value>
    </metadata>
    <metadata name="LayoutPos">
        <value>317.467 62.4404</value>
    </metadata>
</metadatas>
    <ports>
        <port name="condition" type="bool" flag="0" is_input="yes"/>
        <port name="true_case" type="float" flag="4096" is_input="yes"/>
        <port name="false_case" type="float" flag="4096" is_input="yes" default_values="100"/>
        <port name="output" type="array&lt;float&gt;" flag="4096" is_input="no"/>
    </ports>
</vnnNode>
        </node>
        <node>
            <vnnNode name="set_geo_property" type="BifrostGraph,Geometry::Properties,set_geo_property" flag="0">
    <metadatas>
    <metadata name="DisplayMode">
        <value>2</value>
    </metadata>
    <metadata name="LayoutPos">
        <value>611.5 -107</value>
    </metadata>
</metadatas>
    <ports>
        <port name="geometry" type="Amino::Object" flag="0" is_input="yes"/>
        <port name="property" type="string" flag="0" is_input="yes" default_values="voxel_fog_density"/>
        <port name="default" type="float" flag="4096" is_input="yes"/>
        <port name="data" type="array&lt;float&gt;" flag="4096" is_input="yes"/>
        <port name="target" type="string" flag="0" is_input="yes" default_values="point_component"/>
        <port name="out_geometry" type="Amino::Object" flag="0" is_input="no"/>
    </ports>
</vnnNode>
        </node>
        <node>
            <vnnNode name="delete_level_set" type="BifrostGraph,Geometry::Converters::Internal,delete_level_set" flag="0">
    <metadatas>
    <metadata name="DisplayMode">
        <value>2</value>
    </metadata>
    <metadata name="LayoutPos">
        <value>909.5 -112</value>
    </metadata>
</metadatas>
    <ports>
        <port name="volume" type="Amino::Object" flag="0" is_input="yes"/>
        <port name="store_level_set" type="bool" flag="0" is_input="yes" default_values="0"/>
        <port name="out_volume" type="Amino::Object" flag="0" is_input="no"/>
    </ports>
</vnnNode>
        </node>
        <node>
            <vnnNode name="output" type="" flag="16">
    <metadatas>
    <metadata name="DisplayMode">
        <value>2</value>
    </metadata>
    <metadata name="LayoutPos">
        <value>1202 -112.5</value>
    </metadata>
</metadatas>
    <ports>
        <port name="first" type="Amino::Object" flag="0" is_input="no">
            <metadatas>
                <metadata name="feedbackPort" value=""/>
            </metadatas>
        </port>
    </ports>
</vnnNode>
        </node>
    </nodes>
    <connections>
        <connection output_port="convert_to_volume.volume" input_port="first_in_array.array"/>
        <connection output_port="create_mesh_sphere.sphere_mesh" input_port="convert_to_volume.geometry.sphere_mesh"/>
        <connection output_port="first_in_array.first" input_port="get_geo_property.geometry"/>
        <connection output_port="first_in_array.first" input_port="set_geo_property.geometry"/>
        <connection output_port="get_geo_property.data" input_port="greater.first"/>
        <connection output_port="get_geo_property.target" input_port="set_geo_property.target"/>
        <connection output_port="greater.output" input_port="if.condition"/>
        <connection output_port="if.output" input_port="set_geo_property.data"/>
        <connection output_port="set_geo_property.out_geometry" input_port="delete_level_set.volume"/>
    </connections>
</sub_root>
Message 3 of 5

Thank you for the reply. This is a cool way of going about it. I wasn't even aware you could do this. Unfortunately, I also want to apply it to the temperature property, so that I could also "voxelise" things like explosions and fire with it. My mistake for not putting that in the original post.

 

A 4x4x4 filter might not necessarily be needed. I was able to do it with OpenVDB in c++ in the past, by resampling the volume. But the goal is to do it fully in Bifrost. Is there a way to basically resample a volume, but then with a closest/nearest-neighbour interpolation instead of linear or cubic interpolation?

Message 4 of 5
bram0101
in reply to: bram0101

I have figured out a way to do it, that ended up being relatively simple. It would still be great to have closest interpolation available in Bifrost natively, though.

 

I took @morten.bojsen-hansen approach as a starting point, but instead of using the signed distance, I used the voxel_position property.

 

I started by resampling the original volume to create a new higher resolution volume. I got the voxel_position property from the new volume and I then used the round_to_floor node to move the positions to the nearest voxel in the original volume using the following formula (floor(pos / scale) * scale). I used these new positions to sample the original volume and the result is put in the new volume. It is essentially a resample_volume node but one that does closest interpolation.

 

Here is my node graph:

image.png

image.png

 

The same can be extended to any other voxel property.

Here is the compound node of it, for anyone that needs it. https://pastebin.com/5JpeHdyX

Its usage is simple. Connect a volume to it and then set the detail scale to something like 0.25 (for each voxel to become 4x4x4 voxels) and depending on your volume you might want to set the voxel offset to half your detail size, otherwise leave it at (0, 0, 0).

Message 5 of 5

Ah, that's a clever way of going about it. I'm happy that you found a solution.

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums