All GPU backends now support NanoVDB, using our own kernel side code that is easily portable. This simplifies kernel and device code. Volume bounds are now built from the NanoVDB grid instead of OpenVDB, to avoid having to keep around the OpenVDB grid after loading. While this reduces memory usage, it does have a performance impact, particularly for the Cubic filter. That will be addressed by another commit. Pull Request: https://projects.blender.org/blender/blender/pulls/132908
94 lines
2.8 KiB
C++
94 lines
2.8 KiB
C++
/* SPDX-FileCopyrightText: 2022 NVIDIA Corporation
|
|
* SPDX-FileCopyrightText: 2022 Blender Foundation
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0 */
|
|
|
|
#include "hydra/volume.h"
|
|
#include "hydra/field.h"
|
|
#include "hydra/geometry.inl"
|
|
#include "scene/volume.h"
|
|
|
|
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
|
|
|
// clang-format off
|
|
TF_DEFINE_PRIVATE_TOKENS(_tokens,
|
|
(openvdbAsset)
|
|
);
|
|
// clang-format on
|
|
|
|
HdCyclesVolume::HdCyclesVolume(const SdfPath &rprimId
|
|
#if PXR_VERSION < 2102
|
|
,
|
|
const SdfPath &instancerId
|
|
#endif
|
|
)
|
|
: HdCyclesGeometry(rprimId
|
|
#if PXR_VERSION < 2102
|
|
,
|
|
instancerId
|
|
#endif
|
|
)
|
|
{
|
|
}
|
|
|
|
HdCyclesVolume::~HdCyclesVolume() = default;
|
|
|
|
HdDirtyBits HdCyclesVolume::GetInitialDirtyBitsMask() const
|
|
{
|
|
HdDirtyBits bits = HdCyclesGeometry::GetInitialDirtyBitsMask();
|
|
bits |= HdChangeTracker::DirtyVolumeField;
|
|
return bits;
|
|
}
|
|
|
|
void HdCyclesVolume::Populate(HdSceneDelegate *sceneDelegate, HdDirtyBits dirtyBits, bool &rebuild)
|
|
{
|
|
Scene *const scene = (Scene *)_geom->get_owner();
|
|
|
|
if (dirtyBits & HdChangeTracker::DirtyVolumeField) {
|
|
for (const HdVolumeFieldDescriptor &field : sceneDelegate->GetVolumeFieldDescriptors(GetId()))
|
|
{
|
|
if (auto *const openvdbAsset = static_cast<HdCyclesField *>(
|
|
sceneDelegate->GetRenderIndex().GetBprim(_tokens->openvdbAsset, field.fieldId)))
|
|
{
|
|
const ustring name(field.fieldName.GetString());
|
|
|
|
AttributeStandard std = ATTR_STD_NONE;
|
|
if (name == Attribute::standard_name(ATTR_STD_VOLUME_DENSITY)) {
|
|
std = ATTR_STD_VOLUME_DENSITY;
|
|
}
|
|
else if (name == Attribute::standard_name(ATTR_STD_VOLUME_COLOR)) {
|
|
std = ATTR_STD_VOLUME_COLOR;
|
|
}
|
|
else if (name == Attribute::standard_name(ATTR_STD_VOLUME_FLAME)) {
|
|
std = ATTR_STD_VOLUME_FLAME;
|
|
}
|
|
else if (name == Attribute::standard_name(ATTR_STD_VOLUME_HEAT)) {
|
|
std = ATTR_STD_VOLUME_HEAT;
|
|
}
|
|
else if (name == Attribute::standard_name(ATTR_STD_VOLUME_TEMPERATURE)) {
|
|
std = ATTR_STD_VOLUME_TEMPERATURE;
|
|
}
|
|
else if (name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY)) {
|
|
std = ATTR_STD_VOLUME_VELOCITY;
|
|
}
|
|
|
|
// Skip attributes that are not needed
|
|
if ((std != ATTR_STD_NONE && _geom->need_attribute(scene, std)) ||
|
|
_geom->need_attribute(scene, name))
|
|
{
|
|
Attribute *const attr = (std != ATTR_STD_NONE) ?
|
|
_geom->attributes.add(std) :
|
|
_geom->attributes.add(name, TypeFloat, ATTR_ELEMENT_VOXEL);
|
|
attr->data_voxel() = openvdbAsset->GetImageHandle();
|
|
}
|
|
}
|
|
}
|
|
|
|
_geom->merge_grids(scene);
|
|
|
|
rebuild = true;
|
|
}
|
|
}
|
|
|
|
HDCYCLES_NAMESPACE_CLOSE_SCOPE
|