Skip to content
Open
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
1 change: 1 addition & 0 deletions Changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Improvements
------------

- StandardLightVisualiser : Added surface texture visualisation for inputs to the `color` parameter of USD lights when GafferArnold is used (#6651).
- Cycles : Added support for USDPreviewSurface's `opacityMode` which allows transmission surfaces.

Fixes
-----
Expand Down
154 changes: 101 additions & 53 deletions python/GafferCyclesTest/IECoreCyclesPreviewTest/ShaderNetworkAlgoTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -504,75 +504,123 @@ def testConvertUSDOpacity( self ) :

for opacity in ( 0.25, 1.0, None ) :
for opacityThreshold in ( 0.0, 0.5, None ) :
for opacityMode in ( "transparent", "presence", None ) :

parameters = {}
if opacity is not None :
parameters["opacity"] = IECore.FloatData( opacity )
if opacityThreshold is not None :
parameters["opacityThreshold"] = IECore.FloatData( opacityThreshold )
parameters = {}
if opacity is not None :
parameters["opacity"] = IECore.FloatData( opacity )
if opacityMode is not None :
parameters["opacityMode"] = IECore.StringData( opacityMode )
if opacityThreshold is not None :
parameters["opacityThreshold"] = IECore.FloatData( opacityThreshold )

network = IECoreScene.ShaderNetwork(
shaders = {
"previewSurface" : IECoreScene.Shader(
"UsdPreviewSurface", "surface", parameters
network = IECoreScene.ShaderNetwork(
shaders = {
"previewSurface" : IECoreScene.Shader(
"UsdPreviewSurface", "surface", parameters
)
},
output = "previewSurface",
)

convertedNetwork = network.copy()
IECoreCycles.ShaderNetworkAlgo.convertUSDShaders( convertedNetwork )

convertedShader = convertedNetwork.getShader( "previewSurface" )
expectedOpacity = opacity if opacity is not None else 1.0
if opacityThreshold is not None :
expectedOpacity = expectedOpacity if expectedOpacity > opacityThreshold else 0

if opacityMode == "presence" :
self.assertEqual(
convertedShader.parameters["alpha"].value,
expectedOpacity
)
},
output = "previewSurface",
)
self.assertNotIn( "transmission_weight", convertedShader.parameters )
elif opacityMode == "transparent" or opacityMode == None :
expectedOpacity = opacity if opacity is not None else 1.0
self.assertEqual(
convertedShader.parameters["transmission_weight"].value,
1.0 - expectedOpacity
)
# If there isn't any opacityThreshold, alpha should not be authored.
if opacityThreshold == 0.0 or opacityThreshold is None :
self.assertNotIn( "alpha", convertedShader.parameters )

# Repeat, but with an input connection as well as the parameter value

convertedNetwork = network.copy()
IECoreCycles.ShaderNetworkAlgo.convertUSDShaders( convertedNetwork )
network.addShader( "texture", IECoreScene.Shader( "UsdUVTexture" ) )
network.addConnection( ( ( "texture", "a" ), ( "previewSurface", "opacity" ) ) )

convertedShader = convertedNetwork.getShader( "previewSurface" )
expectedOpacity = opacity if opacity is not None else 1.0
if opacityThreshold is not None :
expectedOpacity = expectedOpacity if expectedOpacity > opacityThreshold else 0
convertedNetwork = network.copy()
IECoreCycles.ShaderNetworkAlgo.convertUSDShaders( convertedNetwork )

self.assertEqual(
convertedShader.parameters["alpha"].value,
expectedOpacity
)
if opacityThreshold :

# Repeat, but with an input connection as well as the parameter value
if opacityMode == "presence" :
self.assertEqual( len( convertedNetwork ), 4 )
else :
self.assertEqual( len( convertedNetwork ), 5 )
opacityInput = convertedNetwork.input( ( "previewSurface", "alpha" ) )
self.assertEqual( opacityInput, ( "previewSurfaceOpacityMultiply", "value" ) )
self.assertEqual( convertedNetwork.getShader( opacityInput.shader ).name, "math" )
self.assertEqual(
convertedNetwork.input( ( "previewSurfaceOpacityMultiply", "value1" ) ),
( "texture", "alpha" )
)

network.addShader( "texture", IECoreScene.Shader( "UsdUVTexture" ) )
network.addConnection( ( ( "texture", "a" ), ( "previewSurface", "opacity" ) ) )
self.assertEqual(
convertedNetwork.input( ( "previewSurfaceOpacityMultiply", "value2" ) ),
( "previewSurfaceOpacityCompare", "value" )
)

convertedNetwork = network.copy()
IECoreCycles.ShaderNetworkAlgo.convertUSDShaders( convertedNetwork )
self.assertEqual(
convertedNetwork.input( ( "previewSurfaceOpacityCompare", "value1" ) ),
( "texture", "alpha" )
)

if opacityThreshold :
compareShader = convertedNetwork.getShader( "previewSurfaceOpacityCompare" )
self.assertEqual( compareShader.parameters["math_type"].value, "greater_than" )
self.assertEqual( compareShader.parameters["value2"].value, opacityThreshold )

self.assertEqual( len( convertedNetwork ), 4 )
opacityInput = convertedNetwork.input( ( "previewSurface", "alpha" ) )
self.assertEqual( opacityInput, ( "previewSurfaceOpacityMultiply", "value" ) )
self.assertEqual( convertedNetwork.getShader( opacityInput.shader ).name, "math" )
self.assertEqual(
convertedNetwork.input( ( "previewSurfaceOpacityMultiply", "value1" ) ),
( "texture", "alpha" )
)
if opacityMode == "transparency" or opacityMode == None :

self.assertEqual(
convertedNetwork.input( ( "previewSurfaceOpacityMultiply", "value2" ) ),
( "previewSurfaceOpacityCompare", "value" )
)
invertShader = convertedNetwork.getShader( "previewSurfaceOpacityInvert" )
self.assertEqual( invertShader.parameters["math_type"].value, "subtract" )
self.assertEqual( invertShader.parameters["value1"].value, 1.0 )
self.assertEqual( invertShader.parameters["use_clamp"].value, True )
self.assertEqual(
convertedNetwork.input( ( "previewSurface", "transmission_weight" ) ),
( "previewSurfaceOpacityInvert", "value" )
)
self.assertEqual(
convertedNetwork.input( ( "previewSurfaceOpacityInvert", "value2" ) ),
( "texture", "alpha" )
)

self.assertEqual(
convertedNetwork.input( ( "previewSurfaceOpacityCompare", "value1" ) ),
( "texture", "alpha" )
)
elif opacityMode == "presence" :

compareShader = convertedNetwork.getShader( "previewSurfaceOpacityCompare" )
self.assertEqual( compareShader.parameters["math_type"].value, "greater_than" )
self.assertEqual( compareShader.parameters["value2"].value, opacityThreshold )
self.assertEqual( len( convertedNetwork ), 2 )
self.assertEqual(
convertedNetwork.input( ( "previewSurface", "alpha" ) ),
( "texture", "alpha" )
)

else :
elif opacityMode == "transparency" or opacityMode == None :

self.assertEqual( len( convertedNetwork ), 2 )
self.assertEqual(
convertedNetwork.input( ( "previewSurface", "alpha" ) ),
( "texture", "alpha" )
)
self.assertEqual( len( convertedNetwork ), 3 )
invertShader = convertedNetwork.getShader( "previewSurfaceOpacityInvert" )
self.assertEqual( invertShader.parameters["math_type"].value, "subtract" )
self.assertEqual( invertShader.parameters["value1"].value, 1.0 )
self.assertEqual( invertShader.parameters["use_clamp"].value, True )
self.assertEqual(
convertedNetwork.input( ( "previewSurface", "transmission_weight" ) ),
( "previewSurfaceOpacityInvert", "value" )
)
self.assertEqual(
convertedNetwork.input( ( "previewSurfaceOpacityInvert", "value2" ) ),
( "texture", "alpha" )
)

def testConvertUSDSpecular( self ) :

Expand Down
28 changes: 25 additions & 3 deletions src/GafferCycles/IECoreCyclesPreview/ShaderNetworkAlgo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -875,6 +875,7 @@ const InternedString g_normalParameter( "normal" );
const InternedString g_normalizeParameter( "normalize" );
const InternedString g_occlusionParameter( "occlusion" );
const InternedString g_opacityParameter( "opacity" );
const InternedString g_opacityModeParameter( "opacityMode" );
const InternedString g_opacityThresholdParameter( "opacityThreshold" );
const InternedString g_parametricParameter( "parametric" );
const InternedString g_positionParameter( "position");
Expand Down Expand Up @@ -905,9 +906,11 @@ const InternedString g_texMappingScaleParameter( "tex_mapping__scale" );
const InternedString g_texMappingYMappingParameter( "tex_mapping__y_mapping" );
const InternedString g_texMappingZMappingParameter( "tex_mapping__z_mapping" );
const InternedString g_translationParameter( "translation" );
const InternedString g_transmissionWeightParameter( "transmission_weight" );
const InternedString g_treatAsPointParameter( "treatAsPoint" );
const InternedString g_useDiffuseParameter( "use_diffuse" );
const InternedString g_useGlossyParameter( "use_glossy" );
const InternedString g_useClampParameter( "use_clamp" );
const InternedString g_useMISParameter( "use_mis" );
const InternedString g_useSpecularWorkflowParameter( "useSpecularWorkflow" );
const InternedString g_UVParameter( "UV" );
Expand Down Expand Up @@ -1291,6 +1294,7 @@ void IECoreCycles::ShaderNetworkAlgo::convertUSDShaders( ShaderNetwork *shaderNe
// with a little compare/multiply network.

float opacity = parameterValue( shader.get(), g_opacityParameter, 1.0f );
const string opacityMode = parameterValue( shader.get(), g_opacityModeParameter, string( "transparent" ) );
const float opacityThreshold = parameterValue( shader.get(), g_opacityThresholdParameter, 0.0f );
if( const ShaderNetwork::Parameter opacityInput = shaderNetwork->input( { handle, g_opacityParameter } ) )
{
Expand All @@ -1309,18 +1313,36 @@ void IECoreCycles::ShaderNetworkAlgo::convertUSDShaders( ShaderNetwork *shaderNe
shaderNetwork->removeConnection( ShaderNetwork::Connection( opacityInput, { handle, g_opacityParameter } ) );
shaderNetwork->addConnection( ShaderNetwork::Connection( { multiplyHandle, g_valueParameter }, { handle, g_alphaParameter } ) );
}
else
else if( opacityMode == string( "presence" ) )
{
transferUSDParameter( shaderNetwork, handle, shader.get(), g_opacityParameter, newShader.get(), g_alphaParameter, 1.0f );
}
else
{
shaderNetwork->removeConnection( ShaderNetwork::Connection( opacityInput, { handle, g_opacityParameter } ) );
}

if( opacityMode == string( "transparent" ) )
{
ShaderPtr invertShader = new Shader( "math", "cycles:shader" );
invertShader->parameters()[g_value1Parameter] = new FloatData( 1.0f );
invertShader->parameters()[g_mathTypeParameter] = new StringData( "subtract" );
invertShader->parameters()[g_useClampParameter] = new BoolData( true );
const InternedString invertHandle = shaderNetwork->addShader( handle.string() + "OpacityInvert", std::move( invertShader ) );
shaderNetwork->addConnection( ShaderNetwork::Connection( opacityInput, { invertHandle, g_value2Parameter } ) );
shaderNetwork->addConnection( ShaderNetwork::Connection( { invertHandle, g_valueParameter }, { handle, g_transmissionWeightParameter } ) );
}
}
else if( opacityMode == string( "transparent" ) )
{
newShader->parameters()[g_transmissionWeightParameter] = new FloatData( 1.0f - opacity );
}
else
{
opacity = opacity > opacityThreshold ? opacity : 0.0f;
newShader->parameters()[g_alphaParameter] = new FloatData( opacity );
}

newShader->parameters()[g_alphaParameter] = new FloatData( opacity );

// Normal.
/// \todo Convert normal parameters once we have a solution for Cycles'
/// need for tangents to be provided for the correct use of normal maps.
Expand Down
Loading