Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Changes
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
10.6.x.x (relative to 10.6.3.0)
========

Fixes
-----

- USDScene : Fixed handling of connections involving UsdShadeNodeGraph interface parameters.

10.6.3.0 (relative to 10.6.2.2)
========
Expand Down
51 changes: 29 additions & 22 deletions contrib/IECoreUSD/src/IECoreUSD/ShaderAlgo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
#endif

#include "pxr/usd/usdGeom/primvarsAPI.h"
#include "pxr/usd/usdShade/utils.h"

#include "boost/algorithm/string/predicate.hpp"
#include "boost/algorithm/string/replace.hpp"
Expand Down Expand Up @@ -255,34 +256,40 @@ IECore::InternedString readShaderNetworkWalk( const pxr::SdfPath &anchorPath, co
std::vector<IECoreScene::ShaderNetwork::Connection> connections;
for( pxr::UsdShadeInput &i : usdShader.GetInputs() )
{
pxr::UsdShadeConnectableAPI usdSource;
pxr::TfToken usdSourceName;
pxr::UsdShadeAttributeType usdSourceType;
auto sourceAttributes = i.GetValueProducingAttributes();
if( sourceAttributes.size() == 0 )
{
continue;
}
else if( sourceAttributes.size() > 1 )
{
IECore::msg(
IECore::Msg::Warning, "ShaderAlgo",
boost::format( "Input `%1%` has multiple inputs" )
% i.GetAttr().GetPath()
);
}

pxr::UsdAttribute valueAttribute = i;
if( i.GetConnectedSource( &usdSource, &usdSourceName, &usdSourceType ) )
const pxr::UsdShadeAttributeType type = pxr::UsdShadeUtils::GetType( sourceAttributes[0].GetName() );
if( type == pxr::UsdShadeAttributeType::Output )
{
if( usdSourceType == pxr::UsdShadeAttributeType::Output )
const IECoreScene::ShaderNetwork::Parameter sourceHandle = readShaderNetworkWalk(
anchorPath, pxr::UsdShadeOutput( sourceAttributes[0] ), timeCode, shaderNetwork
);
connections.push_back( {
sourceHandle, { handle, fromUSDParameterName( i.GetBaseName() ) }
} );
if( IECore::DataPtr d = IECoreUSD::DataAlgo::fromUSD( pxr::UsdAttribute( i ), timeCode ) )
{
const IECoreScene::ShaderNetwork::Parameter sourceHandle = readShaderNetworkWalk(
anchorPath, usdSource.GetOutput( usdSourceName ), timeCode, shaderNetwork
);
connections.push_back( {
sourceHandle, { handle, fromUSDParameterName( i.GetBaseName() ) }
} );
}
else
{
// Connected to an exposed input on the material container. We don't
// have an equivalent in IECoreScene::ShaderNetwork yet, so just take
// the parameter value from the exposed input.
valueAttribute = usdSource.GetInput( usdSourceName );
parameters[fromUSDParameterName( i.GetBaseName() )] = d;
}
}

if( IECore::DataPtr d = IECoreUSD::DataAlgo::fromUSD( pxr::UsdAttribute( valueAttribute ), timeCode ) )
else if( type == pxr::UsdShadeAttributeType::Input )
{
parameters[fromUSDParameterName( i.GetBaseName() )] = d;
if( IECore::DataPtr d = IECoreUSD::DataAlgo::fromUSD( sourceAttributes[0], timeCode ) )
{
parameters[fromUSDParameterName( i.GetBaseName() )] = d;
}
}
}

Expand Down
34 changes: 34 additions & 0 deletions contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -4733,5 +4733,39 @@ def testAnimatedLight( self ) :
self.assertNotEqual( shaderNetworks[frame], shaderNetworks[0] )
self.assertEqual( shaderNetworks[frame].outputShader().parameters["exposure"].value, frame / 2.0 )

def testMaterialSubgraph( self ) :

scene = IECoreScene.SceneInterface.create( os.path.dirname( __file__ ) + "/data/materialSubgraph.usda", IECore.IndexedIO.OpenMode.Read )
sphere = scene.child( "sphere" )
shaderNetwork = sphere.readAttribute( "ri:surface", 0.0 )

# We don't currently have the concept of a subgraph in a ShaderNetwork,
# so we only load the leaf nodes, and we "flatten" the connections and
# values.

self.assertEqual( set( shaderNetwork.shaders().keys() ), { "lamaSurface", "pxrVary", "nodeGraph/lamaAdd", "nodeGraph/lamaDiffuse1", "nodeGraph/lamaDiffuse2" } )

self.assertEqual( shaderNetwork.getOutput(), ( "lamaSurface", "bxdf_out" ) )
self.assertEqual( shaderNetwork.shaders()["lamaSurface"].parameters, IECore.CompoundData() )
self.assertEqual( shaderNetwork.input( ( "lamaSurface", "materialFront" ) ), ( "nodeGraph/lamaAdd", "bxdf_out" ) )

self.assertEqual( shaderNetwork.shaders()["nodeGraph/lamaAdd"].parameters, IECore.CompoundData() )
self.assertEqual( shaderNetwork.input( ( "nodeGraph/lamaAdd", "material1" ) ), ( "nodeGraph/lamaDiffuse1", "bxdf_out" ) )
self.assertEqual( shaderNetwork.input( ( "nodeGraph/lamaAdd", "material2" ) ), ( "nodeGraph/lamaDiffuse2", "bxdf_out" ) )

self.assertEqual( shaderNetwork.shaders()["nodeGraph/lamaDiffuse1"].parameters, IECore.CompoundData( { "diffuseColor" : imath.Color3f( 2 ) } ) )
self.assertEqual( shaderNetwork.inputConnections( "nodeGraph/lamaDiffuse1" ), [] )

self.assertEqual( shaderNetwork.shaders()["nodeGraph/lamaDiffuse2"].parameters, IECore.CompoundData() )
self.assertEqual( shaderNetwork.input( ( "nodeGraph/lamaDiffuse2", "diffuseColor" ) ), ( "pxrVary", "resultRGB" ) )

def testMaterialTerminalFromSubgraph( self ) :

scene = IECoreScene.SceneInterface.create( os.path.dirname( __file__ ) + "/data/materialSubgraph.usda", IECore.IndexedIO.OpenMode.Read )
sphere = scene.child( "sphere" )
shaderNetwork = sphere.readAttribute( "ri:surface", 0.0 )

self.assertEqual( shaderNetwork.outputShader().name, "LamaSurface" )

if __name__ == "__main__":
unittest.main()
59 changes: 59 additions & 0 deletions contrib/IECoreUSD/test/IECoreUSD/data/materialSubgraph.usda
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#usda 1.0

def Sphere "sphere" (
prepend apiSchemas = ["MaterialBindingAPI"]
)
{
rel material:binding = </material>
}

def Material "material"
{
token outputs:ri:surface.connect = </material/lamaSurface.outputs:bxdf_out>

def Shader "lamaSurface"
{
uniform token info:id = "LamaSurface"
token inputs:materialFront.connect = </material/nodeGraph.outputs:bxdf_out>
token outputs:bxdf_out
}

def NodeGraph "nodeGraph"
{
color3f inputs:diffuseColorA = ( 2, 2, 2 )

color3f inputs:diffuseColorB = (1, 1, 1)
color3f inputs:diffuseColorB.connect = </material/pxrVary.outputs:resultRGB>

token outputs:bxdf_out.connect = </material/nodeGraph/lamaAdd.outputs:bxdf_out>

def Shader "lamaAdd"
{
uniform token info:id = "LamaAdd"
token inputs:material1.connect = </material/nodeGraph/lamaDiffuse1.outputs:bxdf_out>
token inputs:material2.connect = </material/nodeGraph/lamaDiffuse2.outputs:bxdf_out>
token outputs:bxdf_out
}

def Shader "lamaDiffuse1"
{
uniform token info:id = "LamaDiffuse"
color3f inputs:diffuseColor.connect = </material/nodeGraph.inputs:diffuseColorA>
token outputs:bxdf_out
}

def Shader "lamaDiffuse2"
{
uniform token info:id = "LamaDiffuse"
color3f inputs:diffuseColor.connect = </material/nodeGraph.inputs:diffuseColorB>
token outputs:bxdf_out
}

}

def Shader "pxrVary"
{
uniform token info:id = "PxrVary"
color3f outputs:resultRGB
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#usda 1.0

def Sphere "sphere" (
prepend apiSchemas = ["MaterialBindingAPI"]
)
{
rel material:binding = </material>
}

def Material "material"
{
token outputs:ri:surface.connect = </material/nodeGraph.outputs:bxdf_out>

def NodeGraph "nodeGraph"
{

token outputs:bxdf_out.connect = </material/nodeGraph/lamaSurface.outputs:bxdf_out>

def Shader "lamaSurface"
{
uniform token info:id = "LamaSurface"
token outputs:bxdf_out
}

}
}