Skip to content

Commit 6681453

Browse files
committed
USDScene : Add basic support for reading lights
We only support this for USD 21.11 and greater, because that version introduces UsdLuxLightAPI which lets us load lights using the same UsdShadeConnectable API that we use for materials. At this point we're making no attempt to conform the lights to Gaffer's conventions for Arnold (or any other renderer), so in the short term this is mostly useful for "data smithing" - converting stuff manually after loading. An upcoming ShaderQuery node in Gaffer should provide a useful tool for doing that.
1 parent 9f86796 commit 6681453

File tree

5 files changed

+133
-7
lines changed

5 files changed

+133
-7
lines changed

SConstruct

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2996,6 +2996,7 @@ else :
29962996
usdLibs = [
29972997
"usd",
29982998
"usdGeom",
2999+
"usdLux",
29993000
"usdSkel",
30003001
"usdShade",
30013002
"sdf",

contrib/IECoreUSD/include/IECoreUSD/ShaderAlgo.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@
4242
IECORE_PUSH_DEFAULT_VISIBILITY
4343
#include "pxr/usd/usdShade/material.h"
4444
#include "pxr/usd/usdShade/output.h"
45+
#if PXR_VERSION >= 2111
46+
#include "pxr/usd/usdLux/lightAPI.h"
47+
#endif
4548
IECORE_POP_DEFAULT_VISIBILITY
4649

4750
namespace IECoreUSD
@@ -56,6 +59,10 @@ IECOREUSD_API pxr::UsdShadeOutput writeShaderNetwork( const IECoreScene::ShaderN
5659
/// Reads a ShaderNetwork from a material output, typically obtained from `UsdShadeMaterial::GetOutput()`.
5760
IECoreScene::ShaderNetworkPtr readShaderNetwork( const pxr::UsdShadeOutput &output );
5861

62+
#if PXR_VERSION >= 2111
63+
/// Reads a ShaderNetwork from a light.
64+
IECoreScene::ShaderNetworkPtr readShaderNetwork( const pxr::UsdLuxLightAPI &light );
65+
#endif
5966

6067
} // namespace ShaderAlgo
6168

contrib/IECoreUSD/src/IECoreUSD/ShaderAlgo.cpp

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,26 @@ namespace
5353

5454
pxr::TfToken g_adapterLabelToken( IECoreScene::ShaderNetworkAlgo::componentConnectionAdapterLabel().string() );
5555

56+
pxr::TfToken shaderId( const pxr::UsdShadeConnectableAPI &connectable )
57+
{
58+
pxr::TfToken result;
59+
if( auto shader = pxr::UsdShadeShader( connectable ) )
60+
{
61+
shader.GetShaderId( &result );
62+
}
63+
#if PXR_VERSION >= 2111
64+
else if( auto light = pxr::UsdLuxLightAPI( connectable ) )
65+
{
66+
light.GetShaderIdAttr().Get( &result );
67+
}
68+
#endif
69+
70+
return result;
71+
}
72+
5673
IECoreScene::ShaderNetwork::Parameter readShaderNetworkWalk( const pxr::SdfPath &anchorPath, const pxr::UsdShadeOutput &output, IECoreScene::ShaderNetwork &shaderNetwork );
5774

58-
IECore::InternedString readShaderNetworkWalk( const pxr::SdfPath &anchorPath, const pxr::UsdShadeShader &usdShader, IECoreScene::ShaderNetwork &shaderNetwork )
75+
IECore::InternedString readShaderNetworkWalk( const pxr::SdfPath &anchorPath, const pxr::UsdShadeConnectableAPI &usdShader, IECoreScene::ShaderNetwork &shaderNetwork )
5976
{
6077
IECore::InternedString handle( usdShader.GetPath().MakeRelativePath( anchorPath ).GetString() );
6178

@@ -64,10 +81,10 @@ IECore::InternedString readShaderNetworkWalk( const pxr::SdfPath &anchorPath, co
6481
return handle;
6582
}
6683

67-
pxr::TfToken id;
84+
const pxr::TfToken id = shaderId( usdShader );
6885
std::string shaderName = "defaultsurface";
6986
std::string shaderType = "surface";
70-
if( usdShader.GetShaderId( &id ) )
87+
if( id.size() )
7188
{
7289
std::string name = id.GetString();
7390
size_t colonPos = name.find( ":" );
@@ -141,7 +158,7 @@ IECore::InternedString readShaderNetworkWalk( const pxr::SdfPath &anchorPath, co
141158

142159
IECoreScene::ShaderNetwork::Parameter readShaderNetworkWalk( const pxr::SdfPath &anchorPath, const pxr::UsdShadeOutput &output, IECoreScene::ShaderNetwork &shaderNetwork )
143160
{
144-
IECore::InternedString shaderHandle = readShaderNetworkWalk( anchorPath, pxr::UsdShadeShader( output.GetPrim() ), shaderNetwork );
161+
IECore::InternedString shaderHandle = readShaderNetworkWalk( anchorPath, pxr::UsdShadeConnectableAPI( output.GetPrim() ), shaderNetwork );
145162
if( output.GetBaseName() != "DEFAULT_OUTPUT" )
146163
{
147164
return IECoreScene::ShaderNetwork::Parameter( shaderHandle, output.GetBaseName().GetString() );
@@ -291,3 +308,16 @@ IECoreScene::ShaderNetworkPtr IECoreUSD::ShaderAlgo::readShaderNetwork( const px
291308

292309
return result;
293310
}
311+
312+
#if PXR_VERSION >= 2111
313+
314+
IECoreScene::ShaderNetworkPtr IECoreUSD::ShaderAlgo::readShaderNetwork( const pxr::UsdLuxLightAPI &light )
315+
{
316+
IECoreScene::ShaderNetworkPtr result = new IECoreScene::ShaderNetwork();
317+
IECoreScene::ShaderNetwork::Parameter lightHandle = readShaderNetworkWalk( light.GetPath().GetParentPath(), pxr::UsdShadeConnectableAPI( light ), *result );
318+
result->setOutput( lightHandle );
319+
IECoreScene::ShaderNetworkAlgo::removeComponentConnectionAdapters( result.get() );
320+
return result;
321+
}
322+
323+
#endif

contrib/IECoreUSD/src/IECoreUSD/USDScene.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ IECORE_PUSH_DEFAULT_VISIBILITY
6363
#include "pxr/usd/usdGeom/scope.h"
6464
#include "pxr/usd/usdGeom/tokens.h"
6565
#include "pxr/usd/usdGeom/xform.h"
66+
#if PXR_VERSION >= 2111
67+
#include "pxr/usd/usdLux/lightAPI.h"
68+
#endif
6669
#include "pxr/usd/usdShade/material.h"
6770
#include "pxr/usd/usdShade/materialBindingAPI.h"
6871
#include "pxr/usd/usdShade/connectableAPI.h"
@@ -223,8 +226,25 @@ IECore::PathMatcher readSchemaTypeSet( const pxr::UsdPrim &prim )
223226
return result;
224227
}
225228

229+
template<typename SchemaType>
230+
IECore::PathMatcher readAPISchemaSet( const pxr::UsdPrim &prim )
231+
{
232+
IECore::PathMatcher result;
233+
for( const auto &descendant : prim.GetDescendants() )
234+
{
235+
if( descendant.HasAPI<SchemaType>() )
236+
{
237+
result.addPath( USDScene::fromUSD( descendant.GetPath() ) );
238+
}
239+
}
240+
return result;
241+
}
242+
226243
boost::container::flat_map<IECore::InternedString, IECore::PathMatcher (*)( const pxr::UsdPrim & )> g_schemaTypeSetReaders = {
227244
{ "__cameras", readSchemaTypeSet<pxr::UsdGeomCamera> },
245+
#if PXR_VERSION >= 2111
246+
{ "__lights", readAPISchemaSet<pxr::UsdLuxLightAPI> },
247+
#endif
228248
{ "usd:pointInstancers", readSchemaTypeSet<pxr::UsdGeomPointInstancer> }
229249
};
230250

@@ -775,6 +795,7 @@ namespace
775795

776796
const IECore::InternedString g_purposeAttributeName( "usd:purpose" );
777797
const IECore::InternedString g_kindAttributeName( "usd:kind" );
798+
const IECore::InternedString g_lightAttributeName( "light" );
778799

779800
} // namespace
780801

@@ -800,6 +821,12 @@ bool USDScene::hasAttribute( const SceneInterface::Name &name ) const
800821
pxr::TfToken kind;
801822
return model.GetKind( &kind );
802823
}
824+
#if PXR_VERSION >= 2111
825+
else if( name == g_lightAttributeName )
826+
{
827+
return m_location->prim.HasAPI<pxr::UsdLuxLightAPI>();
828+
}
829+
#endif
803830
else if( auto attribute = AttributeAlgo::findUSDAttribute( m_location->prim, name.string() ) )
804831
{
805832
return attribute.HasAuthoredValue();
@@ -848,6 +875,13 @@ void USDScene::attributeNames( SceneInterface::NameList &attrs ) const
848875
attrs.push_back( g_kindAttributeName );
849876
}
850877

878+
#if PXR_VERSION >= 2111
879+
if( m_location->prim.HasAPI<pxr::UsdLuxLightAPI>() )
880+
{
881+
attrs.push_back( g_lightAttributeName );
882+
}
883+
#endif
884+
851885
std::vector<pxr::UsdAttribute> attributes = m_location->prim.GetAuthoredAttributes();
852886
for( const auto &attribute : attributes )
853887
{
@@ -924,6 +958,12 @@ ConstObjectPtr USDScene::readAttribute( const SceneInterface::Name &name, double
924958
pxr::TfToken value; attr.Get( &value );
925959
return new StringData( value.GetString() );
926960
}
961+
#if PXR_VERSION >= 2111
962+
else if( name == g_lightAttributeName )
963+
{
964+
return ShaderAlgo::readShaderNetwork( pxr::UsdLuxLightAPI( m_location->prim ) );
965+
}
966+
#endif
927967
else if( name == g_kindAttributeName )
928968
{
929969
pxr::TfToken kind;

contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1890,6 +1890,13 @@ def testCanReferenceTags( self ) :
18901890
grandChild = child.child( "grandChild" )
18911891
self.assertSetNamesEqual( grandChild.readTags(), [ "tagB", "tagC" ] )
18921892

1893+
def __expectedLightSets( self ) :
1894+
1895+
if pxr.Usd.GetVersion() >= ( 0, 21, 11 ) :
1896+
return [ "__lights" ]
1897+
else :
1898+
return []
1899+
18931900
def testTagSetEquivalence( self ) :
18941901

18951902
# Location Tags Sets
@@ -1955,7 +1962,7 @@ def checkHasTag( scene ) :
19551962

19561963
self.assertSetNamesEqual( root.readTags( root.AncestorTag ), [] )
19571964
self.assertSetNamesEqual( root.readTags( root.LocalTag ), [] )
1958-
self.assertSetNamesEqual( root.readTags( root.DescendantTag ), allTags + [ "__cameras", "usd:pointInstancers" ] )
1965+
self.assertSetNamesEqual( root.readTags( root.DescendantTag ), allTags + [ "__cameras", "usd:pointInstancers" ] + self.__expectedLightSets() )
19591966
checkHasTag( root )
19601967

19611968
a = root.child( "a" )
@@ -2003,7 +2010,7 @@ def testSchemaTypeSetsAndTags( self ) :
20032010
instancerGroup = group.child( "instancerGroup" )
20042011
instancer = instancerGroup.child( "instancer" )
20052012

2006-
self.assertSetNamesEqual( root.setNames(), [ "__cameras", "usd:pointInstancers" ] )
2013+
self.assertSetNamesEqual( root.setNames(), [ "__cameras", "usd:pointInstancers" ] + self.__expectedLightSets() )
20072014
self.assertSetNamesEqual( group.setNames(), [] )
20082015
self.assertSetNamesEqual( camera.setNames(), [] )
20092016
self.assertSetNamesEqual( instancerGroup.setNames(), [] )
@@ -2025,7 +2032,7 @@ def testSchemaTypeSetsAndTags( self ) :
20252032

20262033
self.assertSetNamesEqual( root.readTags( root.AncestorTag ), [] )
20272034
self.assertSetNamesEqual( root.readTags( root.LocalTag ), [] )
2028-
self.assertSetNamesEqual( root.readTags( root.DescendantTag ), [ "__cameras", "usd:pointInstancers" ] )
2035+
self.assertSetNamesEqual( root.readTags( root.DescendantTag ), [ "__cameras", "usd:pointInstancers" ] + self.__expectedLightSets() )
20292036

20302037
self.assertSetNamesEqual( group.readTags( root.AncestorTag ), [] )
20312038
self.assertSetNamesEqual( group.readTags( root.LocalTag ), [] )
@@ -2967,5 +2974,46 @@ def testExposedShaderInput( self ) :
29672974
self.assertEqual( network.getOutput(), "surface" )
29682975
self.assertEqual( network.getShader( "surface" ).parameters["diffuse_roughness"].value, 0.75 )
29692976

2977+
@unittest.skipIf( pxr.Usd.GetVersion() < ( 0, 21, 11 ), "UsdLuxLightAPI not available" )
2978+
def testLightsSet( self ) :
2979+
2980+
scene = IECoreScene.SceneInterface.create(
2981+
os.path.join( os.path.dirname( __file__ ), "data", "sphereLight.usda" ),
2982+
IECore.IndexedIO.OpenMode.Read
2983+
)
2984+
2985+
self.assertIn( "__lights", scene.setNames() )
2986+
self.assertEqual( scene.readSet( "__lights" ), IECore.PathMatcher( [ "/SpotLight23" ] ) )
2987+
2988+
@unittest.skipIf( pxr.Usd.GetVersion() < ( 0, 21, 11 ), "UsdLuxLightAPI not available" )
2989+
def testLightAttribute( self ) :
2990+
2991+
scene = IECoreScene.SceneInterface.create(
2992+
os.path.join( os.path.dirname( __file__ ), "data", "sphereLight.usda" ),
2993+
IECore.IndexedIO.OpenMode.Read
2994+
)
2995+
light = scene.child( "SpotLight23" )
2996+
self.assertIn( "light", light.attributeNames() )
2997+
self.assertTrue( light.hasAttribute( "light" ) )
2998+
2999+
shader = light.readAttribute( "light", 0 )
3000+
self.assertIsInstance( shader, IECoreScene.ShaderNetwork )
3001+
self.assertEqual( shader.size(), 1 )
3002+
self.assertEqual( shader.getOutput(), "SpotLight23" )
3003+
3004+
self.assertEqual(
3005+
shader.getShader( "SpotLight23" ).parameters,
3006+
IECore.CompoundData( {
3007+
"color" : imath.Color3f( 1, 1, 1 ),
3008+
"colorTemperature" : 6500.0,
3009+
"enableColorTemperature" : False,
3010+
"exposure" : 0.0,
3011+
"intensity" : 30000.0,
3012+
"radius" : 0.0,
3013+
"shaping:cone:angle" : 66.0,
3014+
"shaping:cone:softness" : 1.0
3015+
} )
3016+
)
3017+
29703018
if __name__ == "__main__":
29713019
unittest.main()

0 commit comments

Comments
 (0)