Skip to content

Commit c84fabd

Browse files
author
Alex Fuller
committed
IECoreScene : Spline ramp conversions for Arnold and Renderman native shaders.
1 parent af7fe11 commit c84fabd

File tree

4 files changed

+200
-29
lines changed

4 files changed

+200
-29
lines changed

include/IECoreScene/ShaderNetworkAlgo.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,10 +149,10 @@ IECORESCENE_API void expandSplines( ShaderNetwork *network, std::string targetPr
149149

150150

151151
/// \deprecated: Use collapseSplines on the whole network, which can handle input connections
152-
IECORESCENE_API IECore::ConstCompoundDataPtr collapseSplineParameters( const IECore::ConstCompoundDataPtr& parametersData );
152+
IECORESCENE_API IECore::ConstCompoundDataPtr collapseSplineParameters( const IECore::ConstCompoundDataPtr& parametersData, const std::string shaderType = "", const std::string shaderName = "" );
153153

154154
/// \deprecated: Use expandSplines on the whole network, which can handle input connections
155-
IECORESCENE_API IECore::ConstCompoundDataPtr expandSplineParameters( const IECore::ConstCompoundDataPtr& parametersData );
155+
IECORESCENE_API IECore::ConstCompoundDataPtr expandSplineParameters( const IECore::ConstCompoundDataPtr& parametersData, const std::string shaderType = "", const std::string shaderName = "" );
156156

157157

158158
} // namespace ShaderNetworkAlgo

src/IECoreScene/ShaderNetworkAlgo.cpp

Lines changed: 127 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -811,26 +811,35 @@ std::pair< size_t, size_t > getEndPointDuplication( const T &basis )
811811
}
812812

813813
template<typename Spline>
814-
void expandSpline( const InternedString &name, const Spline &spline, CompoundDataMap &newParameters )
814+
void expandSpline( const InternedString &name, const Spline &spline, CompoundDataMap &newParameters, const std::string shaderType = "", const std::string shaderName = "" )
815815
{
816816
const char *basis = "catmull-rom";
817+
// For Renderman see https://rmanwiki-26.pixar.com/space/REN26/19661691/PxrRamp
818+
const char *riBasis = "catmull-rom";
819+
// For Arnold see https://help.autodesk.com/view/ARNOL/ENU/?guid=arnold_user_guide_ac_texture_shaders_ac_texture_ramp_html
820+
int aiBasisIdx = 2;
817821
if( spline.basis == Spline::Basis::bezier() )
818822
{
819823
basis = "bezier";
820824
}
821825
else if( spline.basis == Spline::Basis::bSpline() )
822826
{
823827
basis = "bspline";
828+
riBasis = "bspline";
824829
}
825830
else if( spline.basis == Spline::Basis::linear() )
826831
{
827832
basis = "linear";
833+
riBasis = "linear";
834+
aiBasisIdx = 1;
828835
}
829836
else if( spline.basis == Spline::Basis::constant() )
830837
{
831838
// Also, "To maintain consistency", "constant splines ignore the first and the two last
832839
// data values."
833840
basis = "constant";
841+
riBasis = "constant";
842+
aiBasisIdx = 0;
834843
}
835844
auto [ duplicateStartPoints, duplicateEndPoints ] = getEndPointDuplication( spline.basis );
836845

@@ -865,9 +874,42 @@ void expandSpline( const InternedString &name, const Spline &spline, CompoundDat
865874
}
866875
}
867876

868-
newParameters[ name.string() + "Positions" ] = positionsData;
869-
newParameters[ name.string() + "Values" ] = valuesData;
870-
newParameters[ name.string() + "Basis" ] = new StringData( basis );
877+
if( boost::starts_with( shaderType, "ai:" ) && ( shaderName == "ramp_float" || shaderName == "ramp_rgb" ) )
878+
{
879+
newParameters[ "position" ] = positionsData;
880+
if constexpr ( std::is_same_v<Spline, SplinefColor3f> )
881+
{
882+
newParameters[ "color" ] = valuesData;
883+
}
884+
else
885+
{
886+
newParameters[ "value" ] = valuesData;
887+
}
888+
std::vector<int> interp;
889+
interp.resize( spline.points.size() );
890+
std::fill( interp.begin(), interp.end(), aiBasisIdx );
891+
newParameters[ "interpolation" ] = new IntVectorData( interp );
892+
}
893+
// Intentionally OR'd here as many Renderman shaders are OSL so search for the 'Pxr' prefix.
894+
else if( boost::starts_with( shaderType, "ri:" ) || ( boost::starts_with( shaderName, "Pxr" ) ) )
895+
{
896+
newParameters[ name.string() + "_Knots" ] = positionsData;
897+
if constexpr ( std::is_same_v<Spline, SplinefColor3f> )
898+
{
899+
newParameters[ name.string() + "_Colors" ] = valuesData;
900+
}
901+
else
902+
{
903+
newParameters[ name.string() + "_Floats" ] = valuesData;
904+
}
905+
newParameters[ name.string() + "_Interpolation" ] = new StringData( riBasis );
906+
}
907+
else
908+
{
909+
newParameters[ name.string() + "Positions" ] = positionsData;
910+
newParameters[ name.string() + "Values" ] = valuesData;
911+
newParameters[ name.string() + "Basis" ] = new StringData( basis );
912+
}
871913
}
872914

873915
template<typename SplineData>
@@ -1039,7 +1081,7 @@ void ShaderNetworkAlgo::collapseSplines( ShaderNetwork *network, std::string tar
10391081
}
10401082

10411083
// For nodes which aren't spline adapters, we just need to deal with any parameters that are splines
1042-
ConstCompoundDataPtr collapsed = collapseSplineParameters( shader->parametersData() );
1084+
ConstCompoundDataPtr collapsed = collapseSplineParameters( shader->parametersData(), shader->getType(), shader->getName());
10431085
if( collapsed != shader->parametersData() )
10441086
{
10451087
// \todo - this const_cast is ugly, although safe because if the return from collapseSplineParameters
@@ -1166,13 +1208,13 @@ void ShaderNetworkAlgo::expandSplines( ShaderNetwork *network, std::string targe
11661208
{
11671209
ensureParametersCopy( origParameters, newParametersData, newParameters );
11681210
newParameters->erase( name );
1169-
expandSpline( name, colorSpline->readable(), *newParameters );
1211+
expandSpline( name, colorSpline->readable(), *newParameters, s.second->getType(), s.second->getName() );
11701212
}
11711213
else if( const SplineffData *floatSpline = runTimeCast<const SplineffData>( value.get() ) )
11721214
{
11731215
ensureParametersCopy( origParameters, newParametersData, newParameters );
11741216
newParameters->erase( name );
1175-
expandSpline( name, floatSpline->readable(), *newParameters );
1217+
expandSpline( name, floatSpline->readable(), *newParameters, s.second->getType(), s.second->getName() );
11761218
}
11771219
}
11781220

@@ -1288,27 +1330,78 @@ void ShaderNetworkAlgo::expandSplines( ShaderNetwork *network, std::string targe
12881330
}
12891331
}
12901332

1291-
IECore::ConstCompoundDataPtr ShaderNetworkAlgo::collapseSplineParameters( const IECore::ConstCompoundDataPtr &parametersData )
1333+
IECore::ConstCompoundDataPtr ShaderNetworkAlgo::collapseSplineParameters( const IECore::ConstCompoundDataPtr &parametersData, const std::string shaderType, const std::string shaderName )
12921334
{
12931335
const CompoundDataMap &parameters( parametersData->readable() );
12941336
CompoundDataPtr newParametersData;
12951337
CompoundDataMap *newParameters = nullptr;
12961338

1339+
std::string basisStr = "Basis";
1340+
std::string positionsStr = "Positions";
1341+
std::string valuesStr = "Values";
1342+
1343+
bool isRenderman = false;
1344+
if( boost::starts_with( shaderType, "ai:" ) && ( shaderName == "ramp_float" || shaderName == "ramp_rgb" ) )
1345+
{
1346+
basisStr = "interpolation";
1347+
positionsStr = "position";
1348+
if( shaderName == "ramp_rgb" )
1349+
{
1350+
valuesStr = "color";
1351+
}
1352+
else
1353+
{
1354+
valuesStr = "value";
1355+
}
1356+
}
1357+
else if( boost::starts_with( shaderType, "ri:" ) || boost::starts_with( shaderName, "Pxr" ) )
1358+
{
1359+
basisStr = "_Interpolation";
1360+
positionsStr = "_Knots";
1361+
valuesStr = "_Floats";
1362+
isRenderman = true;
1363+
}
1364+
12971365
for( const auto &maybeBasis : parameters )
12981366
{
1299-
if( !boost::ends_with( maybeBasis.first.string(), "Basis" ) )
1367+
if( !boost::ends_with( maybeBasis.first.string(), basisStr ) )
13001368
{
13011369
continue;
13021370
}
1303-
const StringData *basis = runTimeCast<const StringData>( maybeBasis.second.get() );
1371+
StringDataPtr basisPtr;
1372+
const StringData *basis = runTimeCast<StringData>( maybeBasis.second.get() );
13041373
if( !basis )
13051374
{
1306-
continue;
1375+
const IntVectorData *intBasis = runTimeCast<const IntVectorData>( maybeBasis.second.get() );
1376+
if( !intBasis )
1377+
{
1378+
continue;
1379+
}
1380+
// Do int to string conversion here, using the first value of the interpolation array
1381+
if( intBasis->readable().front() == 0 )
1382+
{
1383+
basisPtr = new StringData( "constant" );
1384+
}
1385+
else if( intBasis->readable().front() == 1 )
1386+
{
1387+
basisPtr = new StringData( "linear" );
1388+
}
1389+
else if( intBasis->readable().front() == 3 )
1390+
{
1391+
basisPtr = new StringData( "monotonecubic" );
1392+
}
1393+
else
1394+
{
1395+
basisPtr = new StringData( "catmull-rom" );
1396+
}
1397+
}
1398+
else
1399+
{
1400+
basisPtr = basis->copy();
13071401
}
13081402

1309-
1310-
std::string prefix = maybeBasis.first.string().substr( 0, maybeBasis.first.string().size() - 5 );
1311-
IECore::InternedString positionsName = prefix + "Positions";
1403+
std::string prefix = maybeBasis.first.string().substr( 0, maybeBasis.first.string().size() - basisStr.size() );
1404+
IECore::InternedString positionsName = prefix + positionsStr;
13121405
const auto positionsIter = parameters.find( positionsName );
13131406
const FloatVectorData *floatPositions = nullptr;
13141407

@@ -1322,30 +1415,41 @@ IECore::ConstCompoundDataPtr ShaderNetworkAlgo::collapseSplineParameters( const
13221415
continue;
13231416
}
13241417

1325-
IECore::InternedString valuesName = prefix + "Values";
1326-
const auto valuesIter = parameters.find( valuesName );
1418+
IECore::InternedString valuesName = prefix + valuesStr;
1419+
auto valuesIter = parameters.find( valuesName );
1420+
if( valuesIter == parameters.end() && isRenderman )
1421+
{
1422+
valuesName = prefix + "_Colors";
1423+
valuesIter = parameters.find( valuesName );
1424+
}
13271425

13281426
IECore::DataPtr foundSpline;
13291427
if( valuesIter != parameters.end() )
13301428
{
13311429
if( const FloatVectorData *floatValues = runTimeCast<const FloatVectorData>( valuesIter->second.get() ) )
13321430
{
1333-
foundSpline = loadSpline<SplineffData>( basis, floatPositions, floatValues );
1431+
foundSpline = loadSpline<SplineffData>( basisPtr.get(), floatPositions, floatValues );
13341432
}
13351433
else if( const Color3fVectorData *color3Values = runTimeCast<const Color3fVectorData>( valuesIter->second.get() ) )
13361434
{
1337-
foundSpline = loadSpline<SplinefColor3fData>( basis, floatPositions, color3Values );
1435+
foundSpline = loadSpline<SplinefColor3fData>( basisPtr.get(), floatPositions, color3Values );
13381436
}
13391437
else if( const Color4fVectorData *color4Values = runTimeCast<const Color4fVectorData>( valuesIter->second.get() ) )
13401438
{
1341-
foundSpline = loadSpline<SplinefColor4fData>( basis, floatPositions, color4Values );
1439+
foundSpline = loadSpline<SplinefColor4fData>( basisPtr.get(), floatPositions, color4Values );
13421440
}
13431441
}
13441442

13451443
if( foundSpline )
13461444
{
13471445
ensureParametersCopy( parameters, newParametersData, newParameters );
1348-
(*newParameters)[prefix] = foundSpline;
1446+
// Arnold ramp_rgb/ramp_float has no prefix so ensure we have a parameter name to set
1447+
std::string newParamName( "ramp" );
1448+
if( !prefix.empty() )
1449+
{
1450+
newParamName = prefix;
1451+
}
1452+
(*newParameters)[newParamName] = foundSpline;
13491453
newParameters->erase( maybeBasis.first );
13501454
newParameters->erase( positionsName );
13511455
newParameters->erase( valuesName );
@@ -1362,7 +1466,7 @@ IECore::ConstCompoundDataPtr ShaderNetworkAlgo::collapseSplineParameters( const
13621466
}
13631467
}
13641468

1365-
IECore::ConstCompoundDataPtr ShaderNetworkAlgo::expandSplineParameters( const IECore::ConstCompoundDataPtr &parametersData )
1469+
IECore::ConstCompoundDataPtr ShaderNetworkAlgo::expandSplineParameters( const IECore::ConstCompoundDataPtr &parametersData, const std::string shaderType, const std::string shaderName )
13661470
{
13671471
const CompoundDataMap &parameters( parametersData->readable() );
13681472

@@ -1375,13 +1479,13 @@ IECore::ConstCompoundDataPtr ShaderNetworkAlgo::expandSplineParameters( const IE
13751479
{
13761480
ensureParametersCopy( parameters, newParametersData, newParameters );
13771481
newParameters->erase( i.first );
1378-
expandSpline( i.first, colorSpline->readable(), *newParameters );
1482+
expandSpline( i.first, colorSpline->readable(), *newParameters, shaderType, shaderName );
13791483
}
13801484
else if( const SplineffData *floatSpline = runTimeCast<const SplineffData>( i.second.get() ) )
13811485
{
13821486
ensureParametersCopy( parameters, newParametersData, newParameters );
13831487
newParameters->erase( i.first );
1384-
expandSpline( i.first, floatSpline->readable(), *newParameters );
1488+
expandSpline( i.first, floatSpline->readable(), *newParameters, shaderType, shaderName );
13851489
}
13861490
}
13871491

src/IECoreScene/bindings/ShaderNetworkAlgoBinding.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,14 @@ void convertOSLComponentConnectionsWrapper( ShaderNetwork *network, int oslVersi
7070
ShaderNetworkAlgo::convertOSLComponentConnections( network, oslVersion );
7171
}
7272

73-
CompoundDataPtr collapseSplineParametersWrapper( CompoundDataPtr parameters )
73+
CompoundDataPtr collapseSplineParametersWrapper( CompoundDataPtr parameters, const std::string shaderType, const std::string shaderName )
7474
{
75-
return boost::const_pointer_cast< CompoundData >( ShaderNetworkAlgo::collapseSplineParameters( parameters ) );
75+
return boost::const_pointer_cast< CompoundData >( ShaderNetworkAlgo::collapseSplineParameters( parameters, shaderType, shaderName ) );
7676
}
7777

78-
CompoundDataPtr expandSplineParametersWrapper( CompoundDataPtr parameters )
78+
CompoundDataPtr expandSplineParametersWrapper( CompoundDataPtr parameters, const std::string shaderType, const std::string shaderName )
7979
{
80-
return boost::const_pointer_cast< CompoundData >( ShaderNetworkAlgo::expandSplineParameters( parameters ) );
80+
return boost::const_pointer_cast< CompoundData >( ShaderNetworkAlgo::expandSplineParameters( parameters, shaderType, shaderName ) );
8181
}
8282

8383
std::string componentConnectionAdapterLabelWrapper()

test/IECoreScene/ShaderNetworkAlgoTest.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,73 @@ def testSplineConversion( self ):
490490
IECoreScene.ShaderNetworkAlgo.collapseSplines( shaderNetworkInvalid )
491491
self.assertEqual( shaderNetworkInvalid, shaderNetworkInvalidOrig )
492492

493+
def __splineConversionArnold( self, shaderName, valueName, valueType, parms ):
494+
495+
shaderNetworkOrig = IECoreScene.ShaderNetwork(
496+
shaders = { "test" : IECoreScene.Shader( shaderName, "ai:surface", parms ) },
497+
output = "test"
498+
)
499+
shaderNetwork = shaderNetworkOrig.copy()
500+
IECoreScene.ShaderNetworkAlgo.expandSplines( shaderNetwork )
501+
502+
parmsExpanded = shaderNetwork.outputShader().parameters
503+
504+
self.assertEqual( type( parmsExpanded["interpolation"] ), IECore.IntVectorData )
505+
self.assertEqual( type( parmsExpanded["position"] ), IECore.FloatVectorData )
506+
self.assertEqual( type( parmsExpanded[valueName] ), valueType )
507+
508+
IECoreScene.ShaderNetworkAlgo.collapseSplines( shaderNetwork )
509+
510+
self.assertEqual( shaderNetwork, shaderNetworkOrig )
511+
512+
def testSplineConversionArnold( self ):
513+
514+
parmsRgb = IECore.CompoundData()
515+
parmsRgb["ramp"] = IECore.SplinefColor3fData( IECore.SplinefColor3f( IECore.CubicBasisf.catmullRom(),
516+
( ( 0, imath.Color3f(1) ), ( 10, imath.Color3f(2) ), ( 20, imath.Color3f(0) ), ( 30, imath.Color3f(5) ), ( 40, imath.Color3f(2) ), ( 50, imath.Color3f(6) ) ) ) )
517+
518+
self.__splineConversionArnold( "ramp_rgb", "color", IECore.Color3fVectorData, parmsRgb )
519+
520+
parmsFloat = IECore.CompoundData()
521+
parmsFloat["ramp"] = IECore.SplineffData( IECore.Splineff( IECore.CubicBasisf.constant(),
522+
( ( 0, 1 ), ( 0.2, 6 ), ( 0.3, 7 ) ) ) )
523+
524+
self.__splineConversionArnold( "ramp_float", "value", IECore.FloatVectorData, parmsFloat )
525+
526+
def __splineConversionRenderman( self, shaderType ):
527+
528+
parms = IECore.CompoundData()
529+
parms["colorRamp"] = IECore.SplinefColor3fData( IECore.SplinefColor3f( IECore.CubicBasisf.catmullRom(),
530+
( ( 0, imath.Color3f(1) ), ( 10, imath.Color3f(2) ), ( 20, imath.Color3f(0) ), ( 30, imath.Color3f(5) ), ( 40, imath.Color3f(2) ), ( 50, imath.Color3f(6) ) ) ) )
531+
parms["floatRamp"] = IECore.SplineffData( IECore.Splineff( IECore.CubicBasisf.constant(),
532+
( ( 0, 1 ), ( 0.2, 6 ), ( 0.3, 7 ) ) ) )
533+
534+
shaderNetworkOrig = IECoreScene.ShaderNetwork(
535+
shaders = { "test" : IECoreScene.Shader( "PxrSplineMap", shaderType, parms ) },
536+
output = "test"
537+
)
538+
shaderNetwork = shaderNetworkOrig.copy()
539+
IECoreScene.ShaderNetworkAlgo.expandSplines( shaderNetwork )
540+
541+
parmsExpanded = shaderNetwork.outputShader().parameters
542+
543+
self.assertEqual( type( parmsExpanded["colorRamp_Interpolation"] ), IECore.StringData )
544+
self.assertEqual( type( parmsExpanded["colorRamp_Knots"] ), IECore.FloatVectorData )
545+
self.assertEqual( type( parmsExpanded["colorRamp_Colors"] ), IECore.Color3fVectorData )
546+
547+
self.assertEqual( type( parmsExpanded["floatRamp_Interpolation"] ), IECore.StringData )
548+
self.assertEqual( type( parmsExpanded["floatRamp_Knots"] ), IECore.FloatVectorData )
549+
self.assertEqual( type( parmsExpanded["floatRamp_Floats"] ), IECore.FloatVectorData )
550+
551+
IECoreScene.ShaderNetworkAlgo.collapseSplines( shaderNetwork )
552+
553+
self.assertEqual( shaderNetwork, shaderNetworkOrig )
554+
555+
def testSplineConversionRenderman( self ):
556+
557+
self.__splineConversionRenderman( "osl:shader" )
558+
self.__splineConversionRenderman( "ri:surface" )
559+
493560
def testSplineInputs( self ):
494561

495562
fC3fcatmullRom = IECore.SplinefColor3fData( IECore.SplinefColor3f(

0 commit comments

Comments
 (0)