Skip to content

Commit

Permalink
Merge pull request ImageEngine#1256 from johnhaddon/usdLights
Browse files Browse the repository at this point in the history
Basic UsdLux read support
  • Loading branch information
johnhaddon authored Apr 21, 2022
2 parents 0c7939c + 5d233ba commit 3bb0325
Show file tree
Hide file tree
Showing 9 changed files with 203 additions and 105 deletions.
1 change: 1 addition & 0 deletions SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -2999,6 +2999,7 @@ else :
usdLibs = [
"usd",
"usdGeom",
"usdLux",
"usdSkel",
"usdShade",
"sdf",
Expand Down
15 changes: 9 additions & 6 deletions contrib/IECoreUSD/include/IECoreUSD/ShaderAlgo.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@
IECORE_PUSH_DEFAULT_VISIBILITY
#include "pxr/usd/usdShade/material.h"
#include "pxr/usd/usdShade/output.h"
#if PXR_VERSION >= 2111
#include "pxr/usd/usdLux/lightAPI.h"
#endif
IECORE_POP_DEFAULT_VISIBILITY

namespace IECoreUSD
Expand All @@ -53,13 +56,13 @@ namespace ShaderAlgo
/// Write ShaderNetwork to USD, placing the shaders under the Prim `shaderContainer`
IECOREUSD_API pxr::UsdShadeOutput writeShaderNetwork( const IECoreScene::ShaderNetwork *shaderNetwork, pxr::UsdPrim shaderContainer );

/// Read ShaderNetwork from a USD node ( and its connected inputs )
/// `anchorPath` is the ancestor path that shaders will be named relative to
/// `outputHandle` specifies which output of the USD node is being used ( the ShaderNetwork must have
/// a corresponding output set )
IECoreScene::ShaderNetworkPtr readShaderNetwork( const pxr::SdfPath &anchorPath, const pxr::UsdShadeShader &outputShader, const pxr::TfToken &outputHandle );

/// Reads a ShaderNetwork from a material output, typically obtained from `UsdShadeMaterial::GetOutput()`.
IECoreScene::ShaderNetworkPtr readShaderNetwork( const pxr::UsdShadeOutput &output );

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

} // namespace ShaderAlgo

Expand Down
4 changes: 0 additions & 4 deletions contrib/IECoreUSD/src/IECoreUSD/PointInstancerAlgo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,11 @@ IECore::ObjectPtr readPointInstancer( pxr::UsdGeomPointInstancer &pointInstancer
newPoints->variables["velocity"] = IECoreScene::PrimitiveVariable( IECoreScene::PrimitiveVariable::Vertex, velocityData );
}

#if USD_VERSION >= 1911
if( auto accelerationData = DataAlgo::fromUSD( pointInstancer.GetAccelerationsAttr(), time ) )
{
Canceller::check( canceller );
newPoints->variables["acceleration"] = IECoreScene::PrimitiveVariable( IECoreScene::PrimitiveVariable::Vertex, accelerationData );
}
#endif

if( auto angularVelocityData = DataAlgo::fromUSD( pointInstancer.GetAngularVelocitiesAttr(), time ) )
{
Expand Down Expand Up @@ -137,9 +135,7 @@ bool pointInstancerMightBeTimeVarying( pxr::UsdGeomPointInstancer &instancer )
instancer.GetOrientationsAttr().ValueMightBeTimeVarying() ||
instancer.GetScalesAttr().ValueMightBeTimeVarying() ||
instancer.GetVelocitiesAttr().ValueMightBeTimeVarying() ||
#if USD_VERSION >= 1911
instancer.GetAccelerationsAttr().ValueMightBeTimeVarying() ||
#endif
instancer.GetAngularVelocitiesAttr().ValueMightBeTimeVarying()
;
}
Expand Down
14 changes: 1 addition & 13 deletions contrib/IECoreUSD/src/IECoreUSD/PrimitiveAlgo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,6 @@ IECORE_PUSH_DEFAULT_VISIBILITY
#include "pxr/usd/usdSkel/root.h"
IECORE_POP_DEFAULT_VISIBILITY


/// \todo Use the standard PXR_VERSION instead. We can't do that until
/// everyone is using USD 19.11 though, because prior to that PXR_VERSION
/// was malformed (octal, and not comparable in any way).
#define USD_VERSION ( PXR_MAJOR_VERSION * 10000 + PXR_MINOR_VERSION * 100 + PXR_PATCH_VERSION )

using namespace std;
using namespace pxr;
using namespace IECore;
Expand Down Expand Up @@ -136,12 +130,10 @@ void IECoreUSD::PrimitiveAlgo::writePrimitiveVariable( const std::string &name,
{
pointBased.CreateVelocitiesAttr().Set( PrimitiveAlgo::toUSDExpanded( value ), time );
}
#if USD_VERSION >= 1911
else if( name == "acceleration" )
{
pointBased.CreateAccelerationsAttr().Set( PrimitiveAlgo::toUSDExpanded( value ), time );
}
#endif
else
{
writePrimitiveVariable( name, value, static_cast<pxr::UsdGeomGprim &>( pointBased ), time );
Expand Down Expand Up @@ -329,7 +321,7 @@ bool readPrimitiveVariables( const pxr::UsdSkelRoot &skelRoot, const pxr::UsdGeo
}

Canceller::check( canceller );
#if USD_VERSION < 2011
#if PXR_VERSION < 2011
::skelCache()->Populate( skelRoot );
#else
::skelCache()->Populate( skelRoot, pxr::UsdTraverseInstanceProxies() );
Expand Down Expand Up @@ -498,12 +490,10 @@ void IECoreUSD::PrimitiveAlgo::readPrimitiveVariables( const pxr::UsdGeomPointBa
primitive->variables["velocity"] = IECoreScene::PrimitiveVariable( IECoreScene::PrimitiveVariable::Vertex, v );
}

#if USD_VERSION >= 1911
if( auto a = boost::static_pointer_cast<V3fVectorData>( DataAlgo::fromUSD( pointBased.GetAccelerationsAttr(), time ) ) )
{
primitive->variables["acceleration"] = IECoreScene::PrimitiveVariable( IECoreScene::PrimitiveVariable::Vertex, a );
}
#endif
}

bool IECoreUSD::PrimitiveAlgo::primitiveVariablesMightBeTimeVarying( const pxr::UsdGeomPrimvarsAPI &primvarsAPI )
Expand All @@ -524,9 +514,7 @@ bool IECoreUSD::PrimitiveAlgo::primitiveVariablesMightBeTimeVarying( const pxr::
pointBased.GetPointsAttr().ValueMightBeTimeVarying() ||
pointBased.GetNormalsAttr().ValueMightBeTimeVarying() ||
pointBased.GetVelocitiesAttr().ValueMightBeTimeVarying() ||
#if USD_VERSION >= 1911
pointBased.GetAccelerationsAttr().ValueMightBeTimeVarying() ||
#endif
primitiveVariablesMightBeTimeVarying( pxr::UsdGeomPrimvarsAPI( pointBased.GetPrim() ) ) ||
skelAnimMightBeTimeVarying( pointBased.GetPrim() )
;
Expand Down
4 changes: 0 additions & 4 deletions contrib/IECoreUSD/src/IECoreUSD/SceneCacheFileFormat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -237,11 +237,7 @@ void UsdSceneCacheFileFormat::writeLocation(
inChild->path( currentPath );
SdfPath primPath = USDScene::toUSD(currentPath);

#if PXR_VERSION < 2007
if( primPath.AbsoluteRootPath() != SdfPath( "/" ) )
#else
if( !primPath.IsAbsoluteRootPath() )
#endif
{
if( const auto linkedOutScene = runTimeCast<LinkedScene>( outChild.get() ) )
{
Expand Down
117 changes: 76 additions & 41 deletions contrib/IECoreUSD/src/IECoreUSD/ShaderAlgo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,26 @@ namespace

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

IECore::InternedString readShaderNetworkWalk( const pxr::SdfPath &anchorPath, const pxr::UsdShadeShader &usdShader, IECoreScene::ShaderNetwork &shaderNetwork )
pxr::TfToken shaderId( const pxr::UsdShadeConnectableAPI &connectable )
{
pxr::TfToken result;
if( auto shader = pxr::UsdShadeShader( connectable ) )
{
shader.GetShaderId( &result );
}
#if PXR_VERSION >= 2111
else if( auto light = pxr::UsdLuxLightAPI( connectable ) )
{
light.GetShaderIdAttr().Get( &result );
}
#endif

return result;
}

IECoreScene::ShaderNetwork::Parameter readShaderNetworkWalk( const pxr::SdfPath &anchorPath, const pxr::UsdShadeOutput &output, IECoreScene::ShaderNetwork &shaderNetwork );

IECore::InternedString readShaderNetworkWalk( const pxr::SdfPath &anchorPath, const pxr::UsdShadeConnectableAPI &usdShader, IECoreScene::ShaderNetwork &shaderNetwork )
{
IECore::InternedString handle( usdShader.GetPath().MakeRelativePath( anchorPath ).GetString() );

Expand All @@ -62,10 +81,10 @@ IECore::InternedString readShaderNetworkWalk( const pxr::SdfPath &anchorPath, co
return handle;
}

pxr::TfToken id;
const pxr::TfToken id = shaderId( usdShader );
std::string shaderName = "defaultsurface";
std::string shaderType = "surface";
if( usdShader.GetShaderId( &id ) )
if( id.size() )
{
std::string name = id.GetString();
size_t colonPos = name.find( ":" );
Expand All @@ -84,8 +103,7 @@ IECore::InternedString readShaderNetworkWalk( const pxr::SdfPath &anchorPath, co

IECore::CompoundDataPtr parametersData = new IECore::CompoundData();
IECore::CompoundDataMap &parameters = parametersData->writable();
std::vector< std::tuple< IECore::InternedString, pxr::UsdShadeConnectableAPI, IECore::InternedString > > connections;
std::vector< pxr::UsdShadeInput > inputs = usdShader.GetInputs();
std::vector<IECoreScene::ShaderNetwork::Connection> connections;
for( pxr::UsdShadeInput &i : usdShader.GetInputs() )
{
pxr::UsdShadeConnectableAPI usdSource;
Expand All @@ -95,9 +113,14 @@ IECore::InternedString readShaderNetworkWalk( const pxr::SdfPath &anchorPath, co
pxr::UsdAttribute valueAttribute = i;
if( i.GetConnectedSource( &usdSource, &usdSourceName, &usdSourceType ) )
{
if( !usdSource.IsContainer() )
if( usdSourceType == pxr::UsdShadeAttributeType::Output )
{
connections.push_back( { i.GetBaseName().GetString(), usdSource, usdSourceName.GetString() } );
const IECoreScene::ShaderNetwork::Parameter sourceHandle = readShaderNetworkWalk(
anchorPath, usdSource.GetOutput( usdSourceName ), shaderNetwork
);
connections.push_back( {
sourceHandle, { handle, IECore::InternedString( i.GetBaseName().GetString() ) }
} );
}
else
{
Expand All @@ -124,33 +147,28 @@ IECore::InternedString readShaderNetworkWalk( const pxr::SdfPath &anchorPath, co
}
shaderNetwork.addShader( handle, std::move( newShader ) );

// Can only add connections after we've added the shader.
for( const auto &c : connections )
{
IECore::InternedString attributeName;
pxr::UsdShadeConnectableAPI usdSource;
IECore::InternedString sourceAttributeName;
std::tie( attributeName, usdSource, sourceAttributeName ) = c;
IECore::InternedString sourceHandle = readShaderNetworkWalk( anchorPath, pxr::UsdShadeShader( usdSource.GetPrim() ), shaderNetwork );

if( sourceAttributeName == "DEFAULT_OUTPUT" )
{
shaderNetwork.addConnection( IECoreScene::ShaderNetwork::Connection(
{ sourceHandle, "" },
{ handle, attributeName }
) );
}
else
{
shaderNetwork.addConnection( IECoreScene::ShaderNetwork::Connection(
{ sourceHandle, sourceAttributeName },
{ handle, attributeName }
) );
}
shaderNetwork.addConnection( c );
}

return handle;
}

IECoreScene::ShaderNetwork::Parameter readShaderNetworkWalk( const pxr::SdfPath &anchorPath, const pxr::UsdShadeOutput &output, IECoreScene::ShaderNetwork &shaderNetwork )
{
IECore::InternedString shaderHandle = readShaderNetworkWalk( anchorPath, pxr::UsdShadeConnectableAPI( output.GetPrim() ), shaderNetwork );
if( output.GetBaseName() != "DEFAULT_OUTPUT" )
{
return IECoreScene::ShaderNetwork::Parameter( shaderHandle, output.GetBaseName().GetString() );
}
else
{
return IECoreScene::ShaderNetwork::Parameter( shaderHandle );
}
}

} // namespace

pxr::UsdShadeOutput IECoreUSD::ShaderAlgo::writeShaderNetwork( const IECoreScene::ShaderNetwork *shaderNetwork, pxr::UsdPrim shaderContainer )
Expand Down Expand Up @@ -249,10 +267,21 @@ pxr::UsdShadeOutput IECoreUSD::ShaderAlgo::writeShaderNetwork( const IECoreScene
return networkOutUsd;
}

IECoreScene::ShaderNetworkPtr IECoreUSD::ShaderAlgo::readShaderNetwork( const pxr::SdfPath &anchorPath, const pxr::UsdShadeShader &outputShader, const pxr::TfToken &outputParameter )
IECoreScene::ShaderNetworkPtr IECoreUSD::ShaderAlgo::readShaderNetwork( const pxr::UsdShadeOutput &output )
{
pxr::UsdShadeConnectableAPI usdSource;
pxr::TfToken usdSourceName;
pxr::UsdShadeAttributeType usdSourceType;
if(
!output.GetConnectedSource( &usdSource, &usdSourceName, &usdSourceType ) ||
usdSourceType != pxr::UsdShadeAttributeType::Output
)
{
return new IECoreScene::ShaderNetwork();
}

IECoreScene::ShaderNetworkPtr result = new IECoreScene::ShaderNetwork();
IECore::InternedString outputHandle = readShaderNetworkWalk( anchorPath, outputShader, *result );
IECoreScene::ShaderNetwork::Parameter outputHandle = readShaderNetworkWalk( usdSource.GetPrim().GetParent().GetPath(), usdSource.GetOutput( usdSourceName ), *result );

// For the output shader, set the type to "ai:surface" if it is "ai:shader".
// This is complete nonsense - there is nothing to suggest that this shader is
Expand All @@ -265,24 +294,30 @@ IECoreScene::ShaderNetworkPtr IECoreUSD::ShaderAlgo::readShaderNetwork( const px
// don't use the suffix of the shader type for anything, and we should just set
// everything to prefix:shader ( aside from lights, which are a bit of a
// different question )
if( result->getShader( outputHandle )->getType() == "ai:shader" )
const IECoreScene::Shader *outputShader = result->getShader( outputHandle.shader );
if( outputShader->getType() == "ai:shader" )
{
IECoreScene::ShaderPtr o = result->getShader( outputHandle )->copy();
IECoreScene::ShaderPtr o = outputShader->copy();
o->setType( "ai:surface" );
result->setShader( outputHandle, std::move( o ) );
result->setShader( outputHandle.shader, std::move( o ) );
}

// handles[0] is the handle of the first shader added, which is always the output shader
if( outputParameter.GetString() != "DEFAULT_OUTPUT" )
{
result->setOutput( IECoreScene::ShaderNetwork::Parameter( outputHandle, outputParameter.GetString() ) );
}
else
{
result->setOutput( IECoreScene::ShaderNetwork::Parameter( outputHandle ) );
}
result->setOutput( outputHandle );

IECoreScene::ShaderNetworkAlgo::removeComponentConnectionAdapters( result.get() );

return result;
}

#if PXR_VERSION >= 2111

IECoreScene::ShaderNetworkPtr IECoreUSD::ShaderAlgo::readShaderNetwork( const pxr::UsdLuxLightAPI &light )
{
IECoreScene::ShaderNetworkPtr result = new IECoreScene::ShaderNetwork();
IECoreScene::ShaderNetwork::Parameter lightHandle = readShaderNetworkWalk( light.GetPath().GetParentPath(), pxr::UsdShadeConnectableAPI( light ), *result );
result->setOutput( lightHandle );
IECoreScene::ShaderNetworkAlgo::removeComponentConnectionAdapters( result.get() );
return result;
}

#endif
Loading

0 comments on commit 3bb0325

Please sign in to comment.