Skip to content

Commit

Permalink
Merge pull request #5759 from johnhaddon/arnoldUSDConnections
Browse files Browse the repository at this point in the history
Arnold USD compatibility improvements
  • Loading branch information
johnhaddon authored Apr 3, 2024
2 parents 9f520f2 + 8c6fa4b commit dc38ddd
Show file tree
Hide file tree
Showing 17 changed files with 456 additions and 215 deletions.
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

0 comments on commit dc38ddd

Please sign in to comment.