Skip to content

Commit ad90eac

Browse files
IECoreUSD::ShaderAlgo : Omit shaderType prefix for some shaders in Rman
1 parent 356ed76 commit ad90eac

File tree

3 files changed

+59
-6
lines changed

3 files changed

+59
-6
lines changed

Changes

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ Fixes
66

77
- ConfigLoader : Fixed UnicodeDecodeErrors in non-UTF8 locales.
88

9+
Breaking Changes
10+
----------------
11+
12+
- IECoreUSD::ShaderAlgo::writeShaderNetwork : RenderMan specific shaders are now exported to USD without ri: type prefixes, making them compatible with other applications that store shaders in USD for use with RenderMan.
13+
914
10.6.0.2 (relative to 10.6.0.1)
1015
========
1116

contrib/IECoreUSD/src/IECoreUSD/ShaderAlgo.cpp

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -309,15 +309,33 @@ pxr::UsdShadeConnectableAPI createShaderPrim( const IECoreScene::Shader *shader,
309309
{
310310
throw IECore::Exception( "Could not create shader at " + path.GetAsString() );
311311
}
312+
312313
const std::string type = shader->getType();
314+
313315
std::string typePrefix;
314-
size_t typeColonPos = type.find( ":" );
315-
if( typeColonPos != std::string::npos )
316+
if( boost::starts_with( shader->getName(), "Pxr" ) || boost::starts_with( shader->getName(), "Lama" ) )
316317
{
317-
typePrefix = type.substr( 0, typeColonPos ) + ":";
318-
if( typePrefix == "ai:" )
318+
// Leave the type prefix empty. This should be the default, but we are currently only doing this
319+
// for a small number of shaders that we can be completely confident require it, in order to
320+
// preserve backwards compatibility.
321+
}
322+
else
323+
{
324+
size_t typeColonPos = type.find( ":" );
325+
if( typeColonPos != std::string::npos )
319326
{
320-
typePrefix = "arnold:";
327+
// According to our current understanding, this is almost completely wrong. Renderer's like
328+
// PRMan won't accept shaders with type prefixes, and Arnold apparently requires all shaders
329+
// to be prefixed with "arnold:", including OSL. This code prefixes OSL shaders with "osl:",
330+
// which fails in all renderers we're aware of - we're keeping this behaviour for now for
331+
// backwards compatibility reasons.
332+
typePrefix = type.substr( 0, typeColonPos ) + ":";
333+
334+
// This is the one case that actually works
335+
if( typePrefix == "ai:" )
336+
{
337+
typePrefix = "arnold:";
338+
}
321339
}
322340
}
323341
usdShader.SetShaderId( pxr::TfToken( typePrefix + shader->getName() ) );

contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3055,6 +3055,13 @@ def testShaders( self ) :
30553055
) )
30563056
manualComponentNetwork.setOutput( IECoreScene.ShaderNetwork.Parameter( "dest", "" ) )
30573057

3058+
3059+
rmanSurface = IECoreScene.Shader( "PxrFoo", "osl:surface", surface.parameters )
3060+
rmanNetwork = IECoreScene.ShaderNetwork()
3061+
rmanNetwork.addShader( "out", rmanSurface )
3062+
rmanNetwork.setOutput( IECoreScene.ShaderNetwork.Parameter( "out", "" ) )
3063+
3064+
30583065
writerRoot = IECoreScene.SceneInterface.create( fileName, IECore.IndexedIO.OpenMode.Write )
30593066
shaderLocation = writerRoot.createChild( "shaderLocation" )
30603067
shaderLocation.writeAttribute( "ai:surface", oneShaderNetwork, 0 )
@@ -3063,6 +3070,7 @@ def testShaders( self ) :
30633070
shaderLocation.writeAttribute( "complex:surface", complexNetwork, 0 )
30643071
shaderLocation.writeAttribute( "componentConnection:surface", componentConnectionNetwork, 0 )
30653072
shaderLocation.writeAttribute( "manualComponent:surface", manualComponentNetwork, 0 )
3073+
shaderLocation.writeAttribute( "ri:surface", rmanNetwork, 0 )
30663074

30673075
shaderLocation.writeAttribute( "volume", oneShaderNetwork, 0 ) # USD supports shaders without a prefix
30683076

@@ -3121,11 +3129,26 @@ def testShaders( self ) :
31213129
self.assertEqual( textureUsd.GetInput( "filename" ).Get(), "sometexture.tx" )
31223130

31233131

3132+
3133+
3134+
riShaderSource = mat.GetOutput( "ri:surface" ).GetConnectedSource()
3135+
self.assertEqual( riShaderSource[1], "DEFAULT_OUTPUT" )
3136+
riShaderUsd = pxr.UsdShade.Shader( riShaderSource[0].GetPrim() )
3137+
self.assertEqual( riShaderUsd.GetShaderId(), "PxrFoo" )
3138+
self.assertEqual( riShaderUsd.GetInput( "c" ).Get(), "42" )
3139+
self.assertEqual( riShaderUsd.GetInput( "a" ).Get(), 42.0 )
3140+
self.assertEqual( riShaderUsd.GetInput( "g" ).Get(), 5 )
3141+
self.assertEqual( riShaderUsd.GetInput( "g_Knots" ).Get(), pxr.Vt.FloatArray( [0, 0, 10, 20, 20] ) )
3142+
self.assertEqual( riShaderUsd.GetInput( "g_Colors" ).Get(), pxr.Vt.Vec3fArray(
3143+
[pxr.Gf.Vec3f( 1 ), pxr.Gf.Vec3f( 1 ), pxr.Gf.Vec3f( 2 ), pxr.Gf.Vec3f( 0 ), pxr.Gf.Vec3f( 0 )]
3144+
) )
3145+
self.assertEqual( riShaderUsd.GetInput( "g_Interpolation" ).Get(), 'linear' )
3146+
31243147
# Read via SceneInterface, and check that we've round-tripped successfully.
31253148

31263149
root = IECoreScene.SceneInterface.create( fileName, IECore.IndexedIO.OpenMode.Read )
31273150

3128-
self.assertEqual( set( root.child( "shaderLocation" ).attributeNames() ), set( ['ai:disp_map', 'ai:surface', 'complex:surface', 'volume', 'componentConnection:surface', 'manualComponent:surface' ] ) )
3151+
self.assertEqual( set( root.child( "shaderLocation" ).attributeNames() ), set( ['ai:disp_map', 'ai:surface', 'complex:surface', 'volume', 'componentConnection:surface', 'manualComponent:surface', "ri:surface" ] ) )
31293152

31303153
self.assertEqual( root.child( "shaderLocation" ).readAttribute( "ai:surface", 0 ).outputShader().parameters, oneShaderNetwork.outputShader().parameters )
31313154
self.assertEqual( root.child( "shaderLocation" ).readAttribute( "ai:surface", 0 ).outputShader(), oneShaderNetwork.outputShader() )
@@ -3150,6 +3173,13 @@ def testShaders( self ) :
31503173
self.assertEqual( root.child( "shaderLocation" ).readAttribute( "componentConnection:surface", 0 ), componentConnectionNetwork )
31513174
self.assertEqual( root.child( "shaderLocation" ).readAttribute( "manualComponent:surface", 0 ), manualComponentNetwork )
31523175

3176+
rmanSurfaceWithoutTypePrefix = IECoreScene.Shader( "PxrFoo", "surface", surface.parameters )
3177+
rmanNetworkWithoutTypePrefix = IECoreScene.ShaderNetwork()
3178+
rmanNetworkWithoutTypePrefix.addShader( "out", rmanSurfaceWithoutTypePrefix )
3179+
rmanNetworkWithoutTypePrefix.setOutput( IECoreScene.ShaderNetwork.Parameter( "out", "" ) )
3180+
3181+
self.assertEqual( root.child( "shaderLocation" ).readAttribute( "ri:surface", 0 ), rmanNetworkWithoutTypePrefix )
3182+
31533183
def testManyShaders( self ) :
31543184

31553185
# Write shaders

0 commit comments

Comments
 (0)