Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 4 additions & 12 deletions contrib/IECoreAppleseed/src/IECoreAppleseed/ShaderNetworkAlgo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,9 @@ namespace ShaderNetworkAlgo

renderer::ShaderGroup *convert( const IECoreScene::ShaderNetwork *shaderNetwork )
{
ShaderNetworkPtr networkCopy;
if( true ) // todo : make conditional on OSL < 1.10
{
networkCopy = shaderNetwork->copy();
IECoreScene::ShaderNetworkAlgo::convertOSLComponentConnections( networkCopy.get() );
shaderNetwork = networkCopy.get();
}
ShaderNetworkPtr networkCopy = shaderNetwork->copy();
IECoreScene::ShaderNetworkAlgo::convertToOSLConventions( networkCopy.get(), 10900 );
shaderNetwork = networkCopy.get();

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

IECore::ConstCompoundDataPtr expandedParameters = IECoreScene::ShaderNetworkAlgo::expandSplineParameters(
shader->parametersData()
);

asr::ParamArray params( ParameterAlgo::convertShaderParameters( expandedParameters->readable() ) );
asr::ParamArray params( ParameterAlgo::convertShaderParameters( shader->parametersData()->readable() ) );
shaderGroup->add_shader( shaderType, shader->getName().c_str(), handle.c_str(), params );

for( const auto &c : shaderNetwork->inputConnections( handle ) )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def testSplines( self ) :

n = IECoreScene.ShaderNetwork(
shaders = {
"test" : IECoreScene.Shader( "test", "test",
"test" : IECoreScene.Shader( "test", "osl:shader",
IECore.CompoundData(
{
"testColorSpline" : IECore.SplinefColor3fData( IECore.SplinefColor3f( IECore.CubicBasisf.linear(), ( ( 0, imath.Color3f(1) ), ( 10, imath.Color3f(2) ), ( 20, imath.Color3f(0) ) ) ) ),
Expand Down
10 changes: 3 additions & 7 deletions contrib/IECoreUSD/src/IECoreUSD/ShaderAlgo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,6 @@ IECore::InternedString readShaderNetworkWalk( const pxr::SdfPath &anchorPath, co

readAdditionalLightParameters( usdShader.GetPrim(), parameters );

parametersData = boost::const_pointer_cast< IECore::CompoundData >( IECoreScene::ShaderNetworkAlgo::collapseSplineParameters( parametersData ) );

IECoreScene::ShaderPtr newShader = new IECoreScene::Shader( shaderName, shaderType, parametersData );
pxr::VtValue metadataValue;
if( usdShader.GetPrim().GetMetadata( g_adapterLabelToken, &metadataValue ) && metadataValue.Get<bool>() )
Expand Down Expand Up @@ -224,6 +222,7 @@ IECoreScene::ShaderNetwork::Parameter readShaderNetworkWalk( const pxr::SdfPath
pxr::UsdShadeOutput IECoreUSD::ShaderAlgo::writeShaderNetwork( const IECoreScene::ShaderNetwork *shaderNetwork, pxr::UsdPrim shaderContainer )
{
IECoreScene::ShaderNetworkPtr shaderNetworkWithAdapters = shaderNetwork->copy();
IECoreScene::ShaderNetworkAlgo::expandSplines( shaderNetworkWithAdapters.get() );
IECoreScene::ShaderNetworkAlgo::addComponentConnectionAdapters( shaderNetworkWithAdapters.get() );

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


IECore::ConstCompoundDataPtr expandedParameters = IECoreScene::ShaderNetworkAlgo::expandSplineParameters(
shader.second->parametersData()
);
for( const auto &p : expandedParameters->readable() )
for( const auto &p : shader.second->parametersData()->readable() )
{
pxr::UsdShadeInput input = usdShader.CreateInput(
toUSDParameterName( p.first ),
Expand Down Expand Up @@ -355,6 +350,7 @@ IECoreScene::ShaderNetworkPtr IECoreUSD::ShaderAlgo::readShaderNetwork( const px
result->setOutput( outputHandle );

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

return result;
}
Expand Down
24 changes: 24 additions & 0 deletions contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2632,6 +2632,12 @@ def testShaders( self ) :
dest.parameters["a"] = IECore.Color3fData( imath.Color3f( 0.0 ) )
dest.parameters["b"] = IECore.Color3fData( imath.Color3f( 0.0 ) )
dest.parameters["c"] = IECore.FloatData( 0.0 )
dest.parameters["sf"] = IECore.SplineffData( IECore.Splineff( IECore.CubicBasisf.catmullRom(),
( ( 0, 1 ), ( 10, 2 ), ( 20, 0 ), ( 30, 1 ) )
) )
dest.parameters["sc"] = IECore.SplinefColor3fData( IECore.SplinefColor3f( IECore.CubicBasisf.linear(),
( ( 0, imath.Color3f(1) ), ( 10, imath.Color3f(2) ), ( 20, imath.Color3f(0) ) )
) )

componentConnectionNetwork = IECoreScene.ShaderNetwork()
componentConnectionNetwork.addShader( "source1", add1 )
Expand Down Expand Up @@ -2664,6 +2670,24 @@ def testShaders( self ) :
) )
componentConnectionNetwork.setOutput( IECoreScene.ShaderNetwork.Parameter( "dest", "" ) )

# Float to spline element connection
componentConnectionNetwork.addConnection( IECoreScene.ShaderNetwork.Connection(
IECoreScene.ShaderNetwork.Parameter( "source1", "out" ),
IECoreScene.ShaderNetwork.Parameter( "dest", "sf[3].y" )
) )

# Color to spline element connection
componentConnectionNetwork.addConnection( IECoreScene.ShaderNetwork.Connection(
IECoreScene.ShaderNetwork.Parameter( "source3", "out" ),
IECoreScene.ShaderNetwork.Parameter( "dest", "sc[2].y" )
) )

# Float to spline element component connection
componentConnectionNetwork.addConnection( IECoreScene.ShaderNetwork.Connection(
IECoreScene.ShaderNetwork.Parameter( "source1", "out" ),
IECoreScene.ShaderNetwork.Parameter( "dest", "sc[0].y.g" )
) )

# If we manually create the shaders that are used as adapters for component connections,
# they should not be automatically removed on import. ( This is implemented using
# a label for automatically created adapters, stored as blindData in Cortex that is
Expand Down
1 change: 1 addition & 0 deletions include/IECore/InternedString.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ class IECORE_API InternedString
inline InternedString( const std::string &value );
inline InternedString( const char *value );
inline InternedString( const char *value, size_t length );
inline InternedString( const std::string_view &value );

InternedString( const InternedString &other ) = default;
InternedString &operator= ( const InternedString &rhs ) = default;
Expand Down
5 changes: 5 additions & 0 deletions include/IECore/InternedString.inl
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ inline InternedString::InternedString( const char *value, size_t length )
{
}

inline InternedString::InternedString( const std::string_view &value )
: m_value( internedString( value.data(), value.size() ) )
{
}

#if BOOST_VERSION > 105500

inline InternedString::InternedString( const boost::string_view &value )
Expand Down
9 changes: 9 additions & 0 deletions include/IECore/StringAlgo.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,15 @@ bool isUpperCase( const String &s );
template<class String>
bool isLowerCase( const String &s );

/// Convert a sequence of characters given as a string_view to an integer.
/// Throws an exception if the characters do not form a valid integer.
int toInt( const std::string_view &s );

/// Concatenate any mixture of strings, string_views, and string literals, efficiently into a new string.
/// Similar to the std::concat proposed for the standard by P1228, but not yet adopted.
template<typename ... StringsFoldType >
std::string concat( StringsFoldType const& ... strs);

} // namespace StringAlgo

} // namespace IECore
Expand Down
78 changes: 78 additions & 0 deletions include/IECore/StringAlgo.inl
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@
#ifndef IECORE_STRINGALGO_INL
#define IECORE_STRINGALGO_INL

#include "IECore/Exception.h"

#include <charconv>
#include <string.h>

namespace IECore
Expand Down Expand Up @@ -171,6 +174,40 @@ inline bool matchInternal( const char *s, const char *&pattern, bool spaceTermin
}
}

template<class String>
constexpr auto stringData( const String& str )
{
if constexpr( std::is_array_v< String > )
{
return str;
}
else if constexpr( std::is_pointer_v<String> )
{
return str;
}
else
{
return std::data( str );
}
}

template<class String>
constexpr size_t stringSize( const String & str )
{
if constexpr( std::is_array_v< String > )
{
return std::char_traits< typename std::remove_all_extents< String >::type >::length( str );
}
else if constexpr( std::is_pointer_v<String> )
{
return std::char_traits<std::remove_pointer_t<String>>::length( str );
}
else
{
return std::size( str );
}
}

} // namespace Detail

namespace StringAlgo
Expand Down Expand Up @@ -282,6 +319,47 @@ bool isLowerCase( const String &s )
return haveAlpha;
}

inline int toInt( const std::string_view &s )
{
int result = 0;

auto elementIdResult = std::from_chars( s.data(), s.data() + s.size(), result );
if( elementIdResult.ec == std::errc::invalid_argument || elementIdResult.ptr != s.data() + s.size() )
{
throw IECore::Exception( StringAlgo::concat( "Invalid integer ", s ) );
}

return result;
}

template<typename ... StringsFoldType >
std::string concat( StringsFoldType const& ... strs )
{
// Adapted from various posts on Stackoverflow linking to Godbolt links ... it's been passed
// around a bunch, not clear who first wrote it

std::string result;

// C++17 fold for summation
result.resize( ( 0 + ... + Detail::stringSize( strs ) ) );

size_t pos = 0;

// C++17 fold for function calls.
(
(
std::copy(
Detail::stringData( strs ),
Detail::stringData( strs ) + Detail::stringSize( strs ),
result.data() + pos
),
pos += Detail::stringSize(strs)
), ...
);

return result;
}

} // namespace StringAlgo

} // namespace IECore
Expand Down
46 changes: 37 additions & 9 deletions include/IECoreScene/ShaderNetworkAlgo.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,38 +76,66 @@ IECORESCENE_API void removeComponentConnectionAdapters( ShaderNetwork *network )
/// The name of the boolean blindData label used by add/removeComponentConnectionAdapters
IECORESCENE_API const IECore::InternedString &componentConnectionAdapterLabel();

/// Converts various aspects of how shaders are stored to be ready to pass directly to OSL.
/// The `oslVersion` argument is used to determine how conversion is performed, and should be passed a
/// value of `OSL_VERSION`. Conversions include:
///
/// - Connections involving the individual components of point/color parameters.
/// For OSL prior to 1.10, intermediate shaders are inserted to emulate connections between components.
/// For later versions, no new shaders are inserted, but components are renamed from our `.x, .y, .z`
/// suffixes to OSL's `[0], [1], [2]` suffixes.
/// - Splines
/// We support SplineData as a parameter type. For OSL, these must be converted to 3 parameters named
/// `<splineName>Positions`, `<splineName>Values` and `<splineName>Basis`. We also support input
/// connections to spline Y values, specified as `<splineName>[N].y`, which currently must be implemented
/// using an adapter shader.
IECORESCENE_API void convertToOSLConventions( ShaderNetwork *network, int oslVersion );

/// Finds connections involving the individual components of point/color parameters, and converts them
/// for use with OSL. The `oslVersion` argument is used to determine how conversion is performed,
/// and should be passed a value of `OSL_VERSION`. For OSL prior to 1.10, intermediate shaders are
/// inserted to emulate connections between components. For later versions, no new shaders are inserted, but
/// components are renamed from our `.x, .y, .z` suffixes to OSL's `[0], [1], [2]` suffixes.
/// \todo Remove the version without the `oslVersion` argument.
/// \deprecated: Use convertToOSLConventions instead
IECORESCENE_API void convertOSLComponentConnections( ShaderNetwork *network );
IECORESCENE_API void convertOSLComponentConnections( ShaderNetwork *network, int oslVersion );

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

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


/// Look for parameters matching our spline convention, for any possible <prefix> :
/// Look throughout the network for parameters matching our spline convention, for any possible <prefix> :
/// <prefix>Positions, a float vector parameter
/// <prefix>Values, a vector of a value type, such as float or color
/// <prefix>Basis, a string parameter
/// For each set of parameters found matching this convention, the 3 parameters will be replaced with one
/// spline parameter named <prefix>. If none are found, the input is passed through unchanged.
IECORESCENE_API IECore::ConstCompoundDataPtr collapseSplineParameters( const IECore::ConstCompoundDataPtr& parameters );
/// spline parameter named <prefix>. If input connections are represented using an adapter shader, they
/// will be converted to direct connections to the spline using our support for spline element
/// connections.
/// If `targetPrefix` is given, only translates connections to shaders with a type starting with this string
IECORESCENE_API void collapseSplines( ShaderNetwork *network, std::string targetPrefix = "" );

/// Look throughout the network for spline parameters. If any are found, they will be expanded out into
/// 3 parameters named <name>Positions, <name>Values and <name>Basis.
/// We also support input connections to spline Y values, specified as `<splineName>[N].y`, which currently
/// must be implemented by inserting an adapter shader.
/// If `targetPrefix` is given, only translates connections to shaders with a type starting with this string
IECORESCENE_API void expandSplines( ShaderNetwork *network, std::string targetPrefix = "" );


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

/// \deprecated: Use expandSplines on the whole network, which can handle input connections
IECORESCENE_API IECore::ConstCompoundDataPtr expandSplineParameters( const IECore::ConstCompoundDataPtr& parametersData );


} // namespace ShaderNetworkAlgo

} // namespace IECoreScene

#include "IECoreScene/ShaderNetworkAlgo.inl"

#endif // IECORESCENE_SHADERNETWORKALGO_H
2 changes: 1 addition & 1 deletion src/IECore/StringAlgo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ int numericSuffix( const std::string &s, std::string *stem )
{
*stem = match[1];
}
return boost::lexical_cast<int>( match[2] );
return StringAlgo::toInt( std::string_view( s.data() + match.position(2), match.length( 2 ) ) );
}
if( stem )
{
Expand Down
Loading