Skip to content

Commit 3e85a27

Browse files
authored
Merge pull request #1343 from danieldresser-ie/rampInputs
Support Inputs To Splines
2 parents f4f4d86 + db60740 commit 3e85a27

File tree

13 files changed

+827
-93
lines changed

13 files changed

+827
-93
lines changed

contrib/IECoreAppleseed/src/IECoreAppleseed/ShaderNetworkAlgo.cpp

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,9 @@ namespace ShaderNetworkAlgo
6565

6666
renderer::ShaderGroup *convert( const IECoreScene::ShaderNetwork *shaderNetwork )
6767
{
68-
ShaderNetworkPtr networkCopy;
69-
if( true ) // todo : make conditional on OSL < 1.10
70-
{
71-
networkCopy = shaderNetwork->copy();
72-
IECoreScene::ShaderNetworkAlgo::convertOSLComponentConnections( networkCopy.get() );
73-
shaderNetwork = networkCopy.get();
74-
}
68+
ShaderNetworkPtr networkCopy = shaderNetwork->copy();
69+
IECoreScene::ShaderNetworkAlgo::convertToOSLConventions( networkCopy.get(), 10900 );
70+
shaderNetwork = networkCopy.get();
7571

7672
asf::auto_release_ptr<asr::ShaderGroup> shaderGroup;
7773
shaderGroup = asr::ShaderGroupFactory::create( "shader_group" );
@@ -89,11 +85,7 @@ renderer::ShaderGroup *convert( const IECoreScene::ShaderNetwork *shaderNetwork
8985
shaderType += 4;
9086
}
9187

92-
IECore::ConstCompoundDataPtr expandedParameters = IECoreScene::ShaderNetworkAlgo::expandSplineParameters(
93-
shader->parametersData()
94-
);
95-
96-
asr::ParamArray params( ParameterAlgo::convertShaderParameters( expandedParameters->readable() ) );
88+
asr::ParamArray params( ParameterAlgo::convertShaderParameters( shader->parametersData()->readable() ) );
9789
shaderGroup->add_shader( shaderType, shader->getName().c_str(), handle.c_str(), params );
9890

9991
for( const auto &c : shaderNetwork->inputConnections( handle ) )

contrib/IECoreAppleseed/test/IECoreAppleseed/ShaderNetworkAlgoTest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ def testSplines( self ) :
4848

4949
n = IECoreScene.ShaderNetwork(
5050
shaders = {
51-
"test" : IECoreScene.Shader( "test", "test",
51+
"test" : IECoreScene.Shader( "test", "osl:shader",
5252
IECore.CompoundData(
5353
{
5454
"testColorSpline" : IECore.SplinefColor3fData( IECore.SplinefColor3f( IECore.CubicBasisf.linear(), ( ( 0, imath.Color3f(1) ), ( 10, imath.Color3f(2) ), ( 20, imath.Color3f(0) ) ) ) ),

contrib/IECoreUSD/src/IECoreUSD/ShaderAlgo.cpp

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -187,8 +187,6 @@ IECore::InternedString readShaderNetworkWalk( const pxr::SdfPath &anchorPath, co
187187

188188
readAdditionalLightParameters( usdShader.GetPrim(), parameters );
189189

190-
parametersData = boost::const_pointer_cast< IECore::CompoundData >( IECoreScene::ShaderNetworkAlgo::collapseSplineParameters( parametersData ) );
191-
192190
IECoreScene::ShaderPtr newShader = new IECoreScene::Shader( shaderName, shaderType, parametersData );
193191
pxr::VtValue metadataValue;
194192
if( usdShader.GetPrim().GetMetadata( g_adapterLabelToken, &metadataValue ) && metadataValue.Get<bool>() )
@@ -224,6 +222,7 @@ IECoreScene::ShaderNetwork::Parameter readShaderNetworkWalk( const pxr::SdfPath
224222
pxr::UsdShadeOutput IECoreUSD::ShaderAlgo::writeShaderNetwork( const IECoreScene::ShaderNetwork *shaderNetwork, pxr::UsdPrim shaderContainer )
225223
{
226224
IECoreScene::ShaderNetworkPtr shaderNetworkWithAdapters = shaderNetwork->copy();
225+
IECoreScene::ShaderNetworkAlgo::expandSplines( shaderNetworkWithAdapters.get() );
227226
IECoreScene::ShaderNetworkAlgo::addComponentConnectionAdapters( shaderNetworkWithAdapters.get() );
228227

229228
IECoreScene::ShaderNetwork::Parameter networkOutput = shaderNetworkWithAdapters->getOutput();
@@ -258,11 +257,7 @@ pxr::UsdShadeOutput IECoreUSD::ShaderAlgo::writeShaderNetwork( const IECoreScene
258257
}
259258
usdShader.SetShaderId( pxr::TfToken( typePrefix + shader.second->getName() ) );
260259

261-
262-
IECore::ConstCompoundDataPtr expandedParameters = IECoreScene::ShaderNetworkAlgo::expandSplineParameters(
263-
shader.second->parametersData()
264-
);
265-
for( const auto &p : expandedParameters->readable() )
260+
for( const auto &p : shader.second->parametersData()->readable() )
266261
{
267262
pxr::UsdShadeInput input = usdShader.CreateInput(
268263
toUSDParameterName( p.first ),
@@ -355,6 +350,7 @@ IECoreScene::ShaderNetworkPtr IECoreUSD::ShaderAlgo::readShaderNetwork( const px
355350
result->setOutput( outputHandle );
356351

357352
IECoreScene::ShaderNetworkAlgo::removeComponentConnectionAdapters( result.get() );
353+
IECoreScene::ShaderNetworkAlgo::collapseSplines( result.get() );
358354

359355
return result;
360356
}

contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2632,6 +2632,12 @@ def testShaders( self ) :
26322632
dest.parameters["a"] = IECore.Color3fData( imath.Color3f( 0.0 ) )
26332633
dest.parameters["b"] = IECore.Color3fData( imath.Color3f( 0.0 ) )
26342634
dest.parameters["c"] = IECore.FloatData( 0.0 )
2635+
dest.parameters["sf"] = IECore.SplineffData( IECore.Splineff( IECore.CubicBasisf.catmullRom(),
2636+
( ( 0, 1 ), ( 10, 2 ), ( 20, 0 ), ( 30, 1 ) )
2637+
) )
2638+
dest.parameters["sc"] = IECore.SplinefColor3fData( IECore.SplinefColor3f( IECore.CubicBasisf.linear(),
2639+
( ( 0, imath.Color3f(1) ), ( 10, imath.Color3f(2) ), ( 20, imath.Color3f(0) ) )
2640+
) )
26352641

26362642
componentConnectionNetwork = IECoreScene.ShaderNetwork()
26372643
componentConnectionNetwork.addShader( "source1", add1 )
@@ -2664,6 +2670,24 @@ def testShaders( self ) :
26642670
) )
26652671
componentConnectionNetwork.setOutput( IECoreScene.ShaderNetwork.Parameter( "dest", "" ) )
26662672

2673+
# Float to spline element connection
2674+
componentConnectionNetwork.addConnection( IECoreScene.ShaderNetwork.Connection(
2675+
IECoreScene.ShaderNetwork.Parameter( "source1", "out" ),
2676+
IECoreScene.ShaderNetwork.Parameter( "dest", "sf[3].y" )
2677+
) )
2678+
2679+
# Color to spline element connection
2680+
componentConnectionNetwork.addConnection( IECoreScene.ShaderNetwork.Connection(
2681+
IECoreScene.ShaderNetwork.Parameter( "source3", "out" ),
2682+
IECoreScene.ShaderNetwork.Parameter( "dest", "sc[2].y" )
2683+
) )
2684+
2685+
# Float to spline element component connection
2686+
componentConnectionNetwork.addConnection( IECoreScene.ShaderNetwork.Connection(
2687+
IECoreScene.ShaderNetwork.Parameter( "source1", "out" ),
2688+
IECoreScene.ShaderNetwork.Parameter( "dest", "sc[0].y.g" )
2689+
) )
2690+
26672691
# If we manually create the shaders that are used as adapters for component connections,
26682692
# they should not be automatically removed on import. ( This is implemented using
26692693
# a label for automatically created adapters, stored as blindData in Cortex that is

include/IECore/InternedString.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ class IECORE_API InternedString
6868
inline InternedString( const std::string &value );
6969
inline InternedString( const char *value );
7070
inline InternedString( const char *value, size_t length );
71+
inline InternedString( const std::string_view &value );
7172

7273
InternedString( const InternedString &other ) = default;
7374
InternedString &operator= ( const InternedString &rhs ) = default;

include/IECore/InternedString.inl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ inline InternedString::InternedString( const char *value, size_t length )
5858
{
5959
}
6060

61+
inline InternedString::InternedString( const std::string_view &value )
62+
: m_value( internedString( value.data(), value.size() ) )
63+
{
64+
}
65+
6166
#if BOOST_VERSION > 105500
6267

6368
inline InternedString::InternedString( const boost::string_view &value )

include/IECore/StringAlgo.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,15 @@ bool isUpperCase( const String &s );
180180
template<class String>
181181
bool isLowerCase( const String &s );
182182

183+
/// Convert a sequence of characters given as a string_view to an integer.
184+
/// Throws an exception if the characters do not form a valid integer.
185+
int toInt( const std::string_view &s );
186+
187+
/// Concatenate any mixture of strings, string_views, and string literals, efficiently into a new string.
188+
/// Similar to the std::concat proposed for the standard by P1228, but not yet adopted.
189+
template<typename ... StringsFoldType >
190+
std::string concat( StringsFoldType const& ... strs);
191+
183192
} // namespace StringAlgo
184193

185194
} // namespace IECore

include/IECore/StringAlgo.inl

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@
3535
#ifndef IECORE_STRINGALGO_INL
3636
#define IECORE_STRINGALGO_INL
3737

38+
#include "IECore/Exception.h"
39+
40+
#include <charconv>
3841
#include <string.h>
3942

4043
namespace IECore
@@ -171,6 +174,40 @@ inline bool matchInternal( const char *s, const char *&pattern, bool spaceTermin
171174
}
172175
}
173176

177+
template<class String>
178+
constexpr auto stringData( const String& str )
179+
{
180+
if constexpr( std::is_array_v< String > )
181+
{
182+
return str;
183+
}
184+
else if constexpr( std::is_pointer_v<String> )
185+
{
186+
return str;
187+
}
188+
else
189+
{
190+
return std::data( str );
191+
}
192+
}
193+
194+
template<class String>
195+
constexpr size_t stringSize( const String & str )
196+
{
197+
if constexpr( std::is_array_v< String > )
198+
{
199+
return std::char_traits< typename std::remove_all_extents< String >::type >::length( str );
200+
}
201+
else if constexpr( std::is_pointer_v<String> )
202+
{
203+
return std::char_traits<std::remove_pointer_t<String>>::length( str );
204+
}
205+
else
206+
{
207+
return std::size( str );
208+
}
209+
}
210+
174211
} // namespace Detail
175212

176213
namespace StringAlgo
@@ -282,6 +319,47 @@ bool isLowerCase( const String &s )
282319
return haveAlpha;
283320
}
284321

322+
inline int toInt( const std::string_view &s )
323+
{
324+
int result = 0;
325+
326+
auto elementIdResult = std::from_chars( s.data(), s.data() + s.size(), result );
327+
if( elementIdResult.ec == std::errc::invalid_argument || elementIdResult.ptr != s.data() + s.size() )
328+
{
329+
throw IECore::Exception( StringAlgo::concat( "Invalid integer ", s ) );
330+
}
331+
332+
return result;
333+
}
334+
335+
template<typename ... StringsFoldType >
336+
std::string concat( StringsFoldType const& ... strs )
337+
{
338+
// Adapted from various posts on Stackoverflow linking to Godbolt links ... it's been passed
339+
// around a bunch, not clear who first wrote it
340+
341+
std::string result;
342+
343+
// C++17 fold for summation
344+
result.resize( ( 0 + ... + Detail::stringSize( strs ) ) );
345+
346+
size_t pos = 0;
347+
348+
// C++17 fold for function calls.
349+
(
350+
(
351+
std::copy(
352+
Detail::stringData( strs ),
353+
Detail::stringData( strs ) + Detail::stringSize( strs ),
354+
result.data() + pos
355+
),
356+
pos += Detail::stringSize(strs)
357+
), ...
358+
);
359+
360+
return result;
361+
}
362+
285363
} // namespace StringAlgo
286364

287365
} // namespace IECore

include/IECoreScene/ShaderNetworkAlgo.h

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -76,38 +76,66 @@ IECORESCENE_API void removeComponentConnectionAdapters( ShaderNetwork *network )
7676
/// The name of the boolean blindData label used by add/removeComponentConnectionAdapters
7777
IECORESCENE_API const IECore::InternedString &componentConnectionAdapterLabel();
7878

79+
/// Converts various aspects of how shaders are stored to be ready to pass directly to OSL.
80+
/// The `oslVersion` argument is used to determine how conversion is performed, and should be passed a
81+
/// value of `OSL_VERSION`. Conversions include:
82+
///
83+
/// - Connections involving the individual components of point/color parameters.
84+
/// For OSL prior to 1.10, intermediate shaders are inserted to emulate connections between components.
85+
/// For later versions, no new shaders are inserted, but components are renamed from our `.x, .y, .z`
86+
/// suffixes to OSL's `[0], [1], [2]` suffixes.
87+
/// - Splines
88+
/// We support SplineData as a parameter type. For OSL, these must be converted to 3 parameters named
89+
/// `<splineName>Positions`, `<splineName>Values` and `<splineName>Basis`. We also support input
90+
/// connections to spline Y values, specified as `<splineName>[N].y`, which currently must be implemented
91+
/// using an adapter shader.
92+
IECORESCENE_API void convertToOSLConventions( ShaderNetwork *network, int oslVersion );
93+
7994
/// Finds connections involving the individual components of point/color parameters, and converts them
8095
/// for use with OSL. The `oslVersion` argument is used to determine how conversion is performed,
8196
/// and should be passed a value of `OSL_VERSION`. For OSL prior to 1.10, intermediate shaders are
8297
/// inserted to emulate connections between components. For later versions, no new shaders are inserted, but
8398
/// components are renamed from our `.x, .y, .z` suffixes to OSL's `[0], [1], [2]` suffixes.
84-
/// \todo Remove the version without the `oslVersion` argument.
99+
/// \deprecated: Use convertToOSLConventions instead
85100
IECORESCENE_API void convertOSLComponentConnections( ShaderNetwork *network );
86101
IECORESCENE_API void convertOSLComponentConnections( ShaderNetwork *network, int oslVersion );
87102

88103
/// Converts from the legacy ObjectVector format previously used to represent shader networks.
89104
IECORESCENE_API ShaderNetworkPtr convertObjectVector( const IECore::ObjectVector *network );
90105

91106
/// We use a convention where ramps are represented by a single SplineData in Cortex, but must be expanded
92-
/// out into basic types when being passed to a renderer. We need two functions to convert back and forth.
107+
/// out into basic types when being passed to a renderer. We need two functions to convert back and forth.
108+
93109

94-
/// Look for parameters matching our spline convention, for any possible <prefix> :
110+
/// Look throughout the network for parameters matching our spline convention, for any possible <prefix> :
95111
/// <prefix>Positions, a float vector parameter
96112
/// <prefix>Values, a vector of a value type, such as float or color
97113
/// <prefix>Basis, a string parameter
98114
/// For each set of parameters found matching this convention, the 3 parameters will be replaced with one
99-
/// spline parameter named <prefix>. If none are found, the input is passed through unchanged.
100-
IECORESCENE_API IECore::ConstCompoundDataPtr collapseSplineParameters( const IECore::ConstCompoundDataPtr& parameters );
115+
/// spline parameter named <prefix>. If input connections are represented using an adapter shader, they
116+
/// will be converted to direct connections to the spline using our support for spline element
117+
/// connections.
118+
/// If `targetPrefix` is given, only translates connections to shaders with a type starting with this string
119+
IECORESCENE_API void collapseSplines( ShaderNetwork *network, std::string targetPrefix = "" );
120+
121+
/// Look throughout the network for spline parameters. If any are found, they will be expanded out into
122+
/// 3 parameters named <name>Positions, <name>Values and <name>Basis.
123+
/// We also support input connections to spline Y values, specified as `<splineName>[N].y`, which currently
124+
/// must be implemented by inserting an adapter shader.
125+
/// If `targetPrefix` is given, only translates connections to shaders with a type starting with this string
126+
IECORESCENE_API void expandSplines( ShaderNetwork *network, std::string targetPrefix = "" );
127+
101128

102-
/// Look for spline parameters. If any are found, they will be expanded out into 3 parameters named
103-
/// <name>Positions, <name>Values and <name>Basis. If none are found, the input is passed through unchanged.
104-
IECORESCENE_API IECore::ConstCompoundDataPtr expandSplineParameters( const IECore::ConstCompoundDataPtr& parameters );
129+
/// \deprecated: Use collapseSplines on the whole network, which can handle input connections
130+
IECORESCENE_API IECore::ConstCompoundDataPtr collapseSplineParameters( const IECore::ConstCompoundDataPtr& parametersData );
131+
132+
/// \deprecated: Use expandSplines on the whole network, which can handle input connections
133+
IECORESCENE_API IECore::ConstCompoundDataPtr expandSplineParameters( const IECore::ConstCompoundDataPtr& parametersData );
105134

106135

107136
} // namespace ShaderNetworkAlgo
108137

109138
} // namespace IECoreScene
110139

111140
#include "IECoreScene/ShaderNetworkAlgo.inl"
112-
113141
#endif // IECORESCENE_SHADERNETWORKALGO_H

src/IECore/StringAlgo.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,7 @@ int numericSuffix( const std::string &s, std::string *stem )
421421
{
422422
*stem = match[1];
423423
}
424-
return boost::lexical_cast<int>( match[2] );
424+
return StringAlgo::toInt( std::string_view( s.data() + match.position(2), match.length( 2 ) ) );
425425
}
426426
if( stem )
427427
{

0 commit comments

Comments
 (0)