Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Arnold USD compatibility improvements #5759

Merged
merged 8 commits into from
Apr 3, 2024
10 changes: 10 additions & 0 deletions Changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,15 @@ Improvements
------------

- EditScope : Added a summary of edits in the NodeEditor, with the ability to select the affected objects and quickly navigate to the processor nodes.
- Arnold : OSL shaders with connections from multiple outputs are no longer duplicated on export to Arnold.

Fixes
-----

- Arnold :
- Fixed rendering of shaders imported from HtoA via USD.
- Fixed USD export of shaders to use `outputs:out` instead of `outputs:DEFAULT_OUTPUT`.
- Fixed rendering of `osl` shaders using the `code` parameter.
- GafferTest, GafferImageTest : Fixed import of these modules if the `Gaffer` module had not been imported previously.
- SceneAlgo : Fixed potential shutdown crashes caused by the adaptor registry [^1].
- Dispatcher : Fixed shutdown crashes caused by Python slots connected to the dispatch signals [^1].
Expand All @@ -30,6 +35,11 @@ API
- ProcessorWidget provides a base class for custom widgets, and a factory mechanism for registering them against processors.
- SimpleProcessorWidget provides a base class for widgets with a simple summary label and optional action links.

Breaking Changes
----------------

- InteractiveRenderTest : Subclasses must now return the shader output plug from creation methods such as `_createConstantShader()`.

1.4.0.0b5 (relative to 1.4.0.0b4)
=========

Expand Down
2 changes: 1 addition & 1 deletion python/GafferArnoldTest/ArnoldLightFilterTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def testShaderInputs( self ) :
self.assertEqual(
network.inputConnections( network.getOutput().shader ),
[
network.Connection( ( "Checkerboard", "" ), ( network.getOutput().shader, "shader" ) ),
network.Connection( ( "Checkerboard", "out" ), ( network.getOutput().shader, "shader" ) ),
]
)

Expand Down
6 changes: 3 additions & 3 deletions python/GafferArnoldTest/ArnoldLightTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@ def testShaderInputs( self ) :
self.assertEqual(
network.inputConnections( network.getOutput().shader ),
[
network.Connection( ( "sky", "" ), ( network.getOutput().shader, "color" ) ),
network.Connection( ( "matte", "" ), ( network.getOutput().shader, "shader" ) ),
network.Connection( ( "sky", "out" ), ( network.getOutput().shader, "color" ) ),
network.Connection( ( "matte", "out" ), ( network.getOutput().shader, "shader" ) ),
]
)

Expand All @@ -126,7 +126,7 @@ def testOSLShaderInputs( self ) :
self.assertEqual(
network.inputConnections( network.getOutput().shader ),
[
network.Connection( ( "mockOSL", "" ), ( network.getOutput().shader, "color" ) )
network.Connection( ( "mockOSL", "out" ), ( network.getOutput().shader, "color" ) )
]
)

Expand Down
56 changes: 49 additions & 7 deletions python/GafferArnoldTest/ArnoldShaderTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,8 @@ def testShaderNetwork( self ) :
self.assertEqual(
network.inputConnections( "surface" ),
[
network.Connection( ( "noise", "" ), ( "surface", "base_color" ) ),
network.Connection( ( "noise", "" ), ( "surface", "specular_color" ) ),
network.Connection( ( "noise", "out" ), ( "surface", "base_color" ) ),
network.Connection( ( "noise", "out" ), ( "surface", "specular_color" ) ),
]
)

Expand Down Expand Up @@ -830,11 +830,11 @@ def testMixAndMatchWithOSLShadersThroughSwitch( self ) :

self.assertEqual(
network1.inputConnections( "arnoldOut" ),
[ network1.Connection( ( "arnoldIn", "" ), ( "arnoldOut", "color" ) ) ]
[ network1.Connection( ( "arnoldIn", "out" ), ( "arnoldOut", "color" ) ) ]
)
self.assertEqual(
network2.inputConnections( "oslOut" ),
[ network1.Connection( ( "arnoldIn", "" ), ( "oslOut", "c" ) ) ]
[ network1.Connection( ( "arnoldIn", "out" ), ( "oslOut", "c" ) ) ]
)

else :
Expand Down Expand Up @@ -864,9 +864,9 @@ def testComponentToComponentConnections( self ) :
self.assertEqual(
network.inputConnections( "n2" ),
[
( ( "n1", "r" ), ( "n2", "color.b" ) ),
( ( "n1", "b" ), ( "n2", "color.g" ) ),
( ( "n1", "g" ), ( "n2", "color.r" ) ),
( ( "n1", "out.r" ), ( "n2", "color.b" ) ),
( ( "n1", "out.b" ), ( "n2", "color.g" ) ),
( ( "n1", "out.g" ), ( "n2", "color.r" ) ),
]
)

Expand Down Expand Up @@ -947,5 +947,47 @@ def testLoadCameraProjection( self ) :
self.assertEqual( shader["parameters"]["camera"].getValue(), "" )
self.assertEqual( shader["parameters"]["camera"].defaultValue(), "" )

def testUSDRoundTrip( self ) :

userDataRGB = GafferArnold.ArnoldShader()
userDataRGB.loadShader( "user_data_rgb" )
userDataRGB["parameters"]["attribute"].setValue( "test" )

noise = GafferArnold.ArnoldShader()
noise.loadShader( "noise" )
noise["parameters"]["distortion"].setInput( userDataRGB["out"]["r"] )

stateFloat = GafferArnold.ArnoldShader()
stateFloat.loadShader( "state_float" )

standardSurface = GafferArnold.ArnoldShader()
standardSurface.loadShader( "standard_surface" )
standardSurface["parameters"]["base_color"].setInput( noise["out"] )
standardSurface["parameters"]["coat_color"]["r"].setInput( stateFloat["out"] )

sphere = GafferScene.Sphere()

sphereFilter = GafferScene.PathFilter()
sphereFilter["paths"].setValue( IECore.StringVectorData( [ "/sphere" ] ) )

shaderAssignment = GafferScene.ShaderAssignment()
shaderAssignment["in"].setInput( sphere["out"] )
shaderAssignment["filter"].setInput( sphereFilter["out"] )
shaderAssignment["shader"].setInput( standardSurface["out"] )

sceneWriter = GafferScene.SceneWriter()
sceneWriter["in"].setInput( shaderAssignment["out"] )
sceneWriter["fileName"].setValue( self.temporaryDirectory() / "test.usda" )
sceneWriter["task"].execute()

sceneReader = GafferScene.SceneReader()
sceneReader["fileName"].setInput( sceneWriter["fileName"] )

self.assertShaderNetworksEqual(
sceneReader["out"].attributes( "/sphere" )["ai:surface"],
sceneWriter["in"].attributes( "/sphere" )["ai:surface"],
ignoreBlindData = True
)

if __name__ == "__main__":
unittest.main()
18 changes: 9 additions & 9 deletions python/GafferArnoldTest/InteractiveArnoldRenderTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,8 @@ def testLightLinkingAfterParameterUpdates( self ) :
s["ShaderAssignment"]["in"].setInput( s["s"]["out"] )
s["ShaderAssignment"]["filter"].setInput( s["PathFilter"]["out"] )

s["lambert"], _ = self._createMatteShader()
s["ShaderAssignment"]["shader"].setInput( s["lambert"]["out"] )
s["lambert"], _, lambertOut = self._createMatteShader()
s["ShaderAssignment"]["shader"].setInput( lambertOut )

s["StandardAttributes"] = GafferScene.StandardAttributes( "StandardAttributes" )
s["StandardAttributes"]["attributes"]["linkedLights"]["enabled"].setValue( True )
Expand Down Expand Up @@ -287,8 +287,8 @@ def testQuadLightTextureEdits( self ) :
s["ShaderAssignment"]["in"].setInput( s["s"]["out"] )
s["ShaderAssignment"]["filter"].setInput( s["PathFilter"]["out"] )

s["lambert"], _ = self._createMatteShader()
s["ShaderAssignment"]["shader"].setInput( s["lambert"]["out"] )
s["lambert"], _, lambertOut = self._createMatteShader()
s["ShaderAssignment"]["shader"].setInput( lambertOut )

s["Tex"] = GafferArnold.ArnoldShader( "image" )
s["Tex"].loadShader( "image" )
Expand Down Expand Up @@ -385,9 +385,9 @@ def testFlushCache( self ) :
s["Tex"]["parameters"]["filename"].setValue( tmpTextureFile )

# Create a constant shader
s["constant"], shaderColor = self._createConstantShader()
s["constant"], shaderColor, constantOut = self._createConstantShader()
shaderColor.setInput( s["Tex"]["out"] )
s["ShaderAssignment"]["shader"].setInput( s["constant"]["out"] )
s["ShaderAssignment"]["shader"].setInput( constantOut )

s["c"] = GafferScene.Camera()
s["c"]["transform"]["translate"]["z"].setValue( 2 )
Expand Down Expand Up @@ -919,14 +919,14 @@ def _createConstantShader( self ) :

shader = GafferArnold.ArnoldShader()
shader.loadShader( "flat" )
return shader, shader["parameters"]["color"]
return shader, shader["parameters"]["color"], shader["out"]

def _createMatteShader( self ) :

shader = GafferArnold.ArnoldShader()
shader.loadShader( "lambert" )
shader["parameters"]["Kd"].setValue( 1 )
return shader, shader["parameters"]["Kd_color"]
return shader, shader["parameters"]["Kd_color"], shader["out"]

def _createTraceSetShader( self ) :
# It's currently pretty ugly how we need to disable the trace set when it is left empty,
Expand Down Expand Up @@ -965,7 +965,7 @@ def _createTraceSetShader( self ) :

Gaffer.PlugAlgo.promote( switchShader["out"] )

return shaderBox, traceSetShader["parameters"]["trace_set"]
return shaderBox, traceSetShader["parameters"]["trace_set"], shaderBox["out"]

def _cameraVisibilityAttribute( self ) :

Expand Down
4 changes: 2 additions & 2 deletions python/GafferCyclesTest/InteractiveCyclesRenderTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,13 +123,13 @@ def _createConstantShader( self ) :
shader = GafferCycles.CyclesShader()
shader.loadShader( "emission" )
shader["parameters"]["strength"].setValue( 1 )
return shader, shader["parameters"]["color"]
return shader, shader["parameters"]["color"], shader["out"]["emission"]

def _createMatteShader( self ) :

shader = GafferCycles.CyclesShader()
shader.loadShader( "diffuse_bsdf" )
return shader, shader["parameters"]["color"]
return shader, shader["parameters"]["color"], shader["out"]["BSDF"]

def _createTraceSetShader( self ) :

Expand Down
6 changes: 3 additions & 3 deletions python/GafferDelightTest/InteractiveDelightRenderTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,11 @@ def _createConstantShader( self ) :

shader = GafferOSL.OSLShader()
shader.loadShader( "Surface/Constant" )
return shader, shader["parameters"]["Cs"]
return shader, shader["parameters"]["Cs"], shader["out"]["out"]

def _createTraceSetShader( self ) :

return None, None
return None, None, None

def _cameraVisibilityAttribute( self ) :

Expand All @@ -110,7 +110,7 @@ def _createMatteShader( self ) :

shader = GafferOSL.OSLShader()
shader.loadShader( "lambert" )
return shader, shader["parameters"]["i_color"]
return shader, shader["parameters"]["i_color"], shader["out"]["outColor"]

def _createPointLight( self ) :

Expand Down
4 changes: 2 additions & 2 deletions python/GafferOSLTest/OSLShaderTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ def testNetwork( self ) :

network = typesNode.attributes()["osl:surface"]
self.assertEqual( len( network ), 2 )
self.assertEqual( network.getOutput(), ( "types", "" ) )
self.assertEqual( network.getOutput(), ( "types", "out" ) )

types = network.getShader( "types" )
outputTypes = network.getShader( "outputTypes" )
Expand Down Expand Up @@ -1181,7 +1181,7 @@ def testOutputNameIncludedInNetwork( self ) :
network3 = shaderPlug.attributes()["osl:shader"]
hash3 = shaderPlug.attributesHash()

self.assertEqual( network1.getOutput(), IECoreScene.ShaderNetwork.Parameter( "globals" ) )
self.assertEqual( network1.getOutput(), IECoreScene.ShaderNetwork.Parameter( "globals", "out" ) )
self.assertEqual( network2.getOutput(), IECoreScene.ShaderNetwork.Parameter( "globals", "globalP" ) )
self.assertEqual( network3.getOutput(), IECoreScene.ShaderNetwork.Parameter( "globals", "globalN" ) )

Expand Down
Loading
Loading