Skip to content

Commit

Permalink
Cycles : Refactored the VDB Volume code, it now defers voxel creation…
Browse files Browse the repository at this point in the history
… into the scene lock.
  • Loading branch information
boberfly committed Jul 3, 2023
1 parent fcd8922 commit 27de35d
Show file tree
Hide file tree
Showing 15 changed files with 367 additions and 163 deletions.
1 change: 1 addition & 0 deletions Changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ Fixes
- Window : Fixed handling of `**kw` constructor arguments. These were being passed to the `QWidget` constructor where they caused errors, instead of being passed to the ContainerWidget base class.
- PresetsPlugValueWidget : Fixed label update for context-sensitive presets.
- PlugValueWidget : Fixed value update when auxiliary plugs depend on the context but the primary plugs do not.
- Cycles : OpenVDBs will now render and allow shader updates in a live render.

API
---
Expand Down
9 changes: 9 additions & 0 deletions SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -1300,6 +1300,10 @@ libraries = {
( "CCL_NAMESPACE_END", "}" ),
( "WITH_OSL", "1" ),
( "WITH_CYCLES_PATH_GUIDING", "1" ),
( "WITH_OCIO", "1"),
( "WITH_OPENSUBDIV", "1"),
( "WITH_OPENVDB", "1"),
( "WITH_NANOVDB", "1")
],
"FRAMEWORKS" : [ "Foundation", "Metal", "IOKit" ],
},
Expand All @@ -1316,7 +1320,12 @@ libraries = {
"CPPDEFINES" : [
( "CCL_NAMESPACE_BEGIN", "namespace ccl {" ),
( "CCL_NAMESPACE_END", "}" ),
( "WITH_OSL", "1" ),
( "WITH_CYCLES_PATH_GUIDING", "1" ),
( "WITH_OCIO", "1"),
( "WITH_OPENSUBDIV", "1"),
( "WITH_OPENVDB", "1"),
( "WITH_NANOVDB", "1")
],
},
"requiredOptions" : [ "CYCLES_ROOT" ],
Expand Down
2 changes: 1 addition & 1 deletion include/GafferCycles/IECoreCyclesPreview/CameraAlgo.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ namespace CameraAlgo
{

/// Converts the specified IECoreScene::Camera into a ccl::Camera.
IECORECYCLES_API ccl::Camera *convert( const IECoreScene::Camera *camera, const std::string &nodeName, ccl::Scene *scene = nullptr );
IECORECYCLES_API ccl::Camera *convert( const IECoreScene::Camera *camera, const std::string &nodeName );

} // namespace CameraAlgo

Expand Down
18 changes: 12 additions & 6 deletions include/GafferCycles/IECoreCyclesPreview/GeometryAlgo.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,14 @@

#include "IECore/Object.h"

#include "IECoreVDB/VDBObject.h"

#include <vector>

// Cycles
IECORE_PUSH_DEFAULT_VISIBILITY
#include "scene/geometry.h"
#include "scene/volume.h"
// Currently only VDBs need scene to get to the image manager
#include "scene/scene.h"
IECORE_POP_DEFAULT_VISIBILITY
Expand All @@ -56,22 +59,25 @@ namespace GeometryAlgo
{

/// Converts the specified `IECore::Object` into `ccl::Geometry`.
IECORECYCLES_API ccl::Geometry *convert( const IECore::Object *object, const std::string &nodeName, ccl::Scene *scene = nullptr );
IECORECYCLES_API ccl::Geometry *convert( const IECore::Object *object, const std::string &nodeName );
/// As above, but converting a moving object. If no motion converter
/// is available, the first sample is converted instead.
IECORECYCLES_API ccl::Geometry *convert( const std::vector<const IECore::Object *> &samples, const std::vector<float> &times, const int frame, const std::string &nodeName, ccl::Scene *scene = nullptr );
IECORECYCLES_API ccl::Geometry *convert( const std::vector<const IECore::Object *> &samples, const std::vector<float> &times, const int frame, const std::string &nodeName );

/// Converts a primitive variable to a `ccl::Attribute` inside of a `ccl::AttributeSet`.
IECORECYCLES_API void convertPrimitiveVariable( const std::string &name, const IECoreScene::PrimitiveVariable &primitiveVariable, ccl::AttributeSet &attributes, ccl::AttributeElement attributeElement );

/// Converts voxel grids from a VDB object.
IECORECYCLES_API void convertVoxelGrids( const IECoreVDB::VDBObject *vdbObject, ccl::Volume *geometry, ccl::Scene *scene, const float frame = 0.0f, const int precision_ = 0 );

/// Signature of a function which can convert to `ccl:Geometry`.
/// \todo There's really no need to pass the node name here, because it's not a unique handle that
/// needs to be provided when creating the Geometry (like it is in Arnold). The caller can just set the name
/// afterwards if they want to.
using Converter = ccl::Geometry *(*)( const IECore::Object *, const std::string &, ccl::Scene * );
using Converter = ccl::Geometry *(*)( const IECore::Object *, const std::string & );
/// Signature of a function which can convert a series of IECore::Object
/// samples into a moving `ccl:Geometry` object.
using MotionConverter = ccl::Geometry *(*)( const std::vector<const IECore::Object *> &, const std::vector<float> &, const int, const std::string &, ccl::Scene * );
using MotionConverter = ccl::Geometry *(*)( const std::vector<const IECore::Object *> &, const std::vector<float> &, const int, const std::string & );

/// Registers a converter for a specific type.
/// Use the ConverterDescription utility class in preference to
Expand All @@ -87,8 +93,8 @@ class ConverterDescription
public :

/// Type-specific conversion functions.
using Converter = ccl::Geometry *(*)( const T *, const std::string &, ccl::Scene * );
using MotionConverter = ccl::Geometry *(*)( const std::vector<const T *> &, const std::vector<float> &, const int, const std::string &, ccl::Scene * );
using Converter = ccl::Geometry *(*)( const T *, const std::string & );
using MotionConverter = ccl::Geometry *(*)( const std::vector<const T *> &, const std::vector<float> &, const int, const std::string & );

ConverterDescription( Converter converter, MotionConverter motionConverter = nullptr )
{
Expand Down
75 changes: 75 additions & 0 deletions python/GafferCyclesTest/IECoreCyclesPreviewTest/RendererTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#
##########################################################################

import pathlib
import math
import time
import unittest
Expand All @@ -43,6 +44,7 @@
import IECore
import IECoreScene
import IECoreImage
import IECoreVDB

import GafferScene
import GafferCycles
Expand Down Expand Up @@ -1823,5 +1825,78 @@ def testUnsupportedShaderParameters( self ) :
"Unsupported socket type `transform` for socket `ob_tfm` on node .*"
)

def testVDB( self ) :

renderer = GafferScene.Private.IECoreScenePreview.Renderer.create(
"Cycles",
GafferScene.Private.IECoreScenePreview.Renderer.RenderType.Interactive,
)

camera = renderer.camera(
"testCamera",
IECoreScene.Camera(
parameters = {
"resolution" : imath.V2i( 64, 64 ),
}
),
renderer.attributes( IECore.CompoundObject() )
)
camera.transform( imath.M44f().translate( imath.V3f( 0, 45, 150 ) ) )

renderer.option( "camera", IECore.StringData( "testCamera" ) )

renderer.output(
"testOutput",
IECoreScene.Output(
"test",
"ieDisplay",
"rgba",
{
"driverType" : "ImageDisplayDriver",
"handle" : "testVDB",
}
)
)

renderer.object(
"/vdb",
IECoreVDB.VDBObject( pathlib.Path( __file__ ).parent / ".." / ".." / "GafferVDBTest" / "data" / "smoke.vdb" ), # todo - can't figure out how to load in a vdb...
renderer.attributes( IECore.CompoundObject ( {
"cycles:volume" : IECoreScene.ShaderNetwork(
shaders = {
"output" : IECoreScene.Shader( "principled_volume", "cycles:volume", { "density_attribute" : "density" } )
},
output = "output",
)
} ) )
)

renderer.light(
"/light",
None,
renderer.attributes( IECore.CompoundObject ( {
"cycles:light" : IECoreScene.ShaderNetwork(
shaders = {
"output" : IECoreScene.Shader( "background_light", "cycles:light", { "color" : imath.Color3f( 1, 1, 1 ) } ),
},
output = "output",
),
} ) )
)

renderer.render()
time.sleep( 2 )

image = IECoreImage.ImageDisplayDriver.storedImage( "testVDB" )
self.assertIsInstance( image, IECoreImage.ImagePrimitive )

testPixel = self.__colorAtUV( image, imath.V2f( 0.5 ) )
self.assertGreater( testPixel.r, 0 )
self.assertGreater( testPixel.g, 0 )
self.assertGreater( testPixel.b, 0 )

del camera
del v

if __name__ == "__main__":
unittest.main()
36 changes: 35 additions & 1 deletion python/GafferCyclesUI/CyclesAttributesUI.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def __subdivisionSummary( plug ) :
def __volumeSummary( plug ) :

info = []
for childName in ( "volumeClipping", "volumeStepSize", "volumeObjectSpace" ) :
for childName in ( "volumeClipping", "volumeStepSize", "volumeObjectSpace", "volumeVelocityScale", "volumePrecision" ) :
if plug[childName]["enabled"].getValue() :
info.append( IECore.CamelCase.toSpaced( childName ) + ( " On" if plug[childName]["value"].getValue() else " Off" ) )

Expand Down Expand Up @@ -341,6 +341,40 @@ def __shaderSummary( plug ) :

],

"attributes.volumeVelocityScale" : [

"description",
"""
Volume velocity scale to multiply with an existing velocity.
""",

"layout:section", "Volume",

],

"attributes.volumePrecision" : [

"description",
"""
Specifies volume data precision, lower values reduce
memory consumption at the cost of detail.
""",

"layout:section", "Volume",

],

"attributes.volumePrecision.value" : [

"preset:Full", "full",
"preset:Half", "half",

"plugValueWidget:type", "GafferUI.PresetsPlugValueWidget",

],

# Object

"attributes.assetName" : [

"description",
Expand Down
4 changes: 3 additions & 1 deletion src/GafferCycles/CyclesAttributes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,9 @@ CyclesAttributes::CyclesAttributes( const std::string &name )
// Volume
attributes->addChild( new Gaffer::NameValuePlug( "cycles:volume_clipping", new IECore::FloatData( 0.001f ), false, "volumeClipping" ) );
attributes->addChild( new Gaffer::NameValuePlug( "cycles:volume_step_size", new IECore::FloatData( 0.0f ), false, "volumeStepSize" ) );
attributes->addChild( new Gaffer::NameValuePlug( "cycles:volume_object_space", new IECore::BoolData( true ), false, "volumeObjectSpace" ) );
attributes->addChild( new Gaffer::NameValuePlug( "cycles:volume_object_space", new IECore::BoolData( false ), false, "volumeObjectSpace" ) );
attributes->addChild( new Gaffer::NameValuePlug( "cycles:volume_velocity_scale", new IECore::FloatData( 1.0f ), false, "volumeVelocityScale" ) );
attributes->addChild( new Gaffer::NameValuePlug( "cycles:volume_precision", new IECore::StringData( "full" ), false, "volumePrecision" ) );

// Per-object parameters
attributes->addChild( new Gaffer::NameValuePlug( "cycles:dupli_generated", new IECore::V3fData( Imath::V3f( 0.0f ) ), false, "dupliGenerated" ) );
Expand Down
2 changes: 1 addition & 1 deletion src/GafferCycles/IECoreCyclesPreview/CameraAlgo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ namespace CameraAlgo

{

ccl::Camera *convert( const IECoreScene::Camera *camera, const std::string &nodeName, ccl::Scene *scene )
ccl::Camera *convert( const IECoreScene::Camera *camera, const std::string &nodeName )
{
return convertCommon( camera, nodeName );
}
Expand Down
4 changes: 2 additions & 2 deletions src/GafferCycles/IECoreCyclesPreview/CurvesAlgo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,14 +133,14 @@ ccl::Hair *convertCommon( const IECoreScene::CurvesPrimitive *curve )
return hair;
}

ccl::Geometry *convert( const IECoreScene::CurvesPrimitive *curve, const std::string &nodeName, ccl::Scene *scene )
ccl::Geometry *convert( const IECoreScene::CurvesPrimitive *curve, const std::string &nodeName )
{
ccl::Hair *hair = convertCommon( curve );
hair->name = ccl::ustring( nodeName.c_str() );
return hair;
}

ccl::Geometry *convert( const vector<const IECoreScene::CurvesPrimitive *> &curves, const std::vector<float> &times, const int frameIdx, const std::string &nodeName, ccl::Scene *scene )
ccl::Geometry *convert( const vector<const IECoreScene::CurvesPrimitive *> &curves, const std::vector<float> &times, const int frameIdx, const std::string &nodeName )
{
const int numSamples = curves.size();

Expand Down
Loading

0 comments on commit 27de35d

Please sign in to comment.