Skip to content

Commit 87bd62d

Browse files
committed
USDScene : Support round-tripping of non-UsdLux lights
In Cortex/Gaffer, a light is a location which has a `light` or `*:light` attribute containing a suitable ShaderNetwork and which also appears in the `__lights` set. When round-tripping a non-UsdLux light through USD we were losing the membership of the set because on loading we were synthesizing the set from all locations with `UsdLuxLightAPI` applied, rather than loading the `__lights` set that had been written explicitly. By loading both `UsdLuxLightAPI` locations _and_ members of the `__lights` collection, we can support both UsdLuxLights from other DCCs (where the `__lights` collection won't have been written) and UsdLux and non-UsdLux lights from Gaffer (where the `__lights` collection will have been written). There are a couple of elephants in the room here : 1. We are still not writing the light's material in a USD-conformant way. It ends up being written as a material assignment just because that's what it is in Cortex/Gaffer, but really it should be written as an ArnoldDistantLight prim. But doing that wouldn't have helped with the `__lights` set : ArnoldDistantLight is not a UsdLuxLight, so it _still_ wouldn't have been found by the old set reading code. 2. We arguably should be writing the `__lights` set not as a regular collection, but via UsdLuxLightList, for maximum compatibility with other USD consumers. But then we'd be including non-UsdLux lights in the light list (see 1) which isn't ideal either - they wouldn't be included by `UsdLuxLightListAPI::ComputeLightList()`, which is the canonical way of generating such a list. For now we're just making the simplest possible change to unlock a short term Gaffer->Gaffer workflow involving Arnold-specific lights. > Note : As a byproduct we are also doing the same merging of the predicate-based and collection based sets for the `__cameras` and `usd:pointInstancers` sets. Is this something we should be concerned about?
1 parent ca90f15 commit 87bd62d

File tree

3 files changed

+34
-2
lines changed

3 files changed

+34
-2
lines changed

Changes

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
11
10.5.x.x (relative to 10.5.6.0)
22
========
33

4-
54
Improvements
65
------------
76

87
- DisplayDriverServer : Fixed delays connecting to the server on Windows.
98

9+
Fixes
10+
-----
11+
12+
- USDScene : Fixed round-tripping of `__lights` set membership for non-UsdLux lights.
13+
1014
Build
1115
-----
1216

1317
- SConstruct : Support detection of OpenEXR versions with a patch version containing multiple digits.
1418

19+
1520
10.5.6.0 (relative to 10.5.5.0)
1621
========
1722

contrib/IECoreUSD/src/IECoreUSD/USDScene.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,6 @@ IECore::PathMatcher localSet( const pxr::UsdPrim &prim, const pxr::TfToken &name
247247
{
248248
result.addPath( std::vector<IECore::InternedString>() );
249249
}
250-
return result;
251250
}
252251

253252
const size_t prefixSize = prim.GetPath().GetPathElementCount();

contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3973,5 +3973,33 @@ def testReadFromStageCache( self ) :
39733973
self.assertEqual( root.childNames(), [ "sphere" ] )
39743974
self.assertIsInstance( root.child( "sphere" ).readObject( 0 ), IECoreScene.SpherePrimitive )
39753975

3976+
def testRoundTripArnoldLight( self ) :
3977+
3978+
lightShader = IECoreScene.ShaderNetwork(
3979+
shaders = {
3980+
"light" : IECoreScene.Shader( "distant_light", parameters = { "exposure" : 2.0 } )
3981+
},
3982+
output = "light",
3983+
)
3984+
3985+
root = IECoreScene.SceneInterface.create(
3986+
os.path.join( self.temporaryDirectory(), "test.usda" ),
3987+
IECore.IndexedIO.OpenMode.Write
3988+
)
3989+
light = root.createChild( "light" )
3990+
light.writeAttribute( "ai:light", lightShader, 0 )
3991+
root.writeSet( "__lights", IECore.PathMatcher( [ "/light" ] ) )
3992+
del root, light
3993+
3994+
root = IECoreScene.SceneInterface.create(
3995+
os.path.join( self.temporaryDirectory(), "test.usda" ),
3996+
IECore.IndexedIO.OpenMode.Read
3997+
)
3998+
light = root.child( "light" )
3999+
self.assertIn( "ai:light", light.attributeNames() )
4000+
self.assertEqual( light.readAttribute( "ai:light", 0 ), lightShader )
4001+
self.assertIn( "__lights", root.setNames() )
4002+
self.assertEqual( root.readSet( "__lights" ), IECore.PathMatcher( [ "/light" ] ) )
4003+
39764004
if __name__ == "__main__":
39774005
unittest.main()

0 commit comments

Comments
 (0)