Skip to content

Commit bddc80f

Browse files
committed
USDShader : Shader type namespacing and assignment improvements
1 parent 2726082 commit bddc80f

File tree

4 files changed

+127
-1
lines changed

4 files changed

+127
-1
lines changed

Changes.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ Improvements
55
------------
66

77
- Arnold : Added support for Int64Data and UInt64Data custom attributes, allowing USD's `instanceId` to be used as a custom attribute in the Instancer node. Warnings are emitted if values are out of range for Arnold's 32 bit ints.
8+
- USDShader :
9+
- A namespace prefix is now set for the shader type from the USD source type, except for `USD` and `glslfx` built-ins which correspond to USDLux lights and USDPreviewSurface built-ins
10+
- Added a way to register namespace overrides from USD shader source types if the resulting USD source type is undesirable
11+
- The correct shader assignment for displacement and volume shaders are now set for shaders which have a context of `displacement` or `volume` set
812

913
Fixes
1014
-----

include/GafferUSD/USDShader.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ class GAFFERUSD_API USDShader : public GafferScene::Shader
5656

5757
void loadShader( const std::string &shaderName, bool keepExistingValues = false ) override;
5858

59+
/// Set a namespace remap based on the sourceType of the registered USD shader
60+
/// eg. `USD` remaps to no namespace or `arnold` into `ai`.
61+
static bool registerShaderNameSpace( const IECore::InternedString sourceType, const IECore::InternedString nameSpace );
62+
5963
protected :
6064

6165
IECore::ConstCompoundObjectPtr attributes( const Gaffer::Plug *output ) const override;

python/GafferUSDTest/USDShaderTest.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,5 +258,59 @@ def testUsdPreviewSurfaceAssignment( self ) :
258258
self.assertEqual( shaderAssignment["out"].attributes( "/sphere" ).keys(), [ "displacement" ] )
259259
self.assertIsInstance( shaderAssignment["out"].attributes( "/sphere" )["displacement"], IECoreScene.ShaderNetwork )
260260

261+
def testMtlxSurfaceAssignment( self ) :
262+
263+
sphere = GafferScene.Sphere()
264+
265+
shader = GafferUSD.USDShader()
266+
shader.loadShader( "ND_surface" )
267+
268+
sphereFilter = GafferScene.PathFilter()
269+
sphereFilter["paths"].setValue( IECore.StringVectorData( [ "/sphere" ] ) )
270+
271+
shaderAssignment = GafferScene.ShaderAssignment()
272+
shaderAssignment["in"].setInput( sphere["out"] )
273+
shaderAssignment["filter"].setInput( sphereFilter["out"] )
274+
shaderAssignment["shader"].setInput( shader["out"]["out"] )
275+
276+
self.assertEqual( shaderAssignment["out"].attributes( "/sphere" ).keys(), [ "mtlx:surface" ] )
277+
self.assertIsInstance( shaderAssignment["out"].attributes( "/sphere" )["mtlx:surface"], IECoreScene.ShaderNetwork )
278+
279+
def testMtlxDisplacementAssignment( self ) :
280+
281+
sphere = GafferScene.Sphere()
282+
283+
shader = GafferUSD.USDShader()
284+
shader.loadShader( "ND_displacement_float" )
285+
286+
sphereFilter = GafferScene.PathFilter()
287+
sphereFilter["paths"].setValue( IECore.StringVectorData( [ "/sphere" ] ) )
288+
289+
shaderAssignment = GafferScene.ShaderAssignment()
290+
shaderAssignment["in"].setInput( sphere["out"] )
291+
shaderAssignment["filter"].setInput( sphereFilter["out"] )
292+
shaderAssignment["shader"].setInput( shader["out"]["out"] )
293+
294+
self.assertEqual( shaderAssignment["out"].attributes( "/sphere" ).keys(), [ "mtlx:displacement" ] )
295+
self.assertIsInstance( shaderAssignment["out"].attributes( "/sphere" )["mtlx:displacement"], IECoreScene.ShaderNetwork )
296+
297+
def testMtlxVolumeAssignment( self ) :
298+
299+
sphere = GafferScene.Sphere()
300+
301+
shader = GafferUSD.USDShader()
302+
shader.loadShader( "ND_volume" )
303+
304+
sphereFilter = GafferScene.PathFilter()
305+
sphereFilter["paths"].setValue( IECore.StringVectorData( [ "/sphere" ] ) )
306+
307+
shaderAssignment = GafferScene.ShaderAssignment()
308+
shaderAssignment["in"].setInput( sphere["out"] )
309+
shaderAssignment["filter"].setInput( sphereFilter["out"] )
310+
shaderAssignment["shader"].setInput( shader["out"]["out"] )
311+
312+
self.assertEqual( shaderAssignment["out"].attributes( "/sphere" ).keys(), [ "mtlx:volume" ] )
313+
self.assertIsInstance( shaderAssignment["out"].attributes( "/sphere" )["mtlx:volume"], IECoreScene.ShaderNetwork )
314+
261315
if __name__ == "__main__":
262316
unittest.main()

src/GafferUSD/USDShader.cpp

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
#include "pxr/usd/usdLux/nonboundableLightBase.h"
6060

6161
#include "boost/algorithm/string/predicate.hpp"
62+
#include "boost/container/flat_map.hpp"
6263

6364
#include "fmt/format.h"
6465

@@ -319,6 +320,63 @@ Plug *loadPrimDefinitionAttribute( const UsdPrimDefinition::Attribute &attribute
319320

320321
const IECore::InternedString g_surface( "surface" );
321322
const IECore::InternedString g_displacement( "displacement" );
323+
const IECore::InternedString g_volume( "volume" );
324+
325+
using ShaderRemap = boost::container::flat_map<IECore::InternedString, IECore::InternedString>;
326+
327+
ShaderRemap &shaderNameSpace()
328+
{
329+
static ShaderRemap g_shaderNameSpace;
330+
return g_shaderNameSpace;
331+
}
332+
333+
const std::string remapShaderType( const TfToken sourceType, const TfToken context )
334+
{
335+
const IECore::InternedString stype( sourceType.GetString() );
336+
const IECore::InternedString ctx( context.GetString() );
337+
std::string nameSpace = stype.string();
338+
std::string outputType = g_surface.string();
339+
340+
const ShaderRemap &shaderNS = shaderNameSpace();
341+
ShaderRemap::const_iterator it = shaderNS.find( stype );
342+
if( it != shaderNS.end() )
343+
{
344+
nameSpace = it->second.string();
345+
}
346+
347+
if( ctx == g_displacement )
348+
{
349+
outputType = g_displacement.string();
350+
}
351+
else if( ctx == g_volume )
352+
{
353+
outputType = g_volume.string();
354+
}
355+
356+
if( nameSpace.empty() )
357+
{
358+
return outputType;
359+
}
360+
361+
return nameSpace + ":" + outputType;
362+
}
363+
364+
// USD Lux types seem to be set to USD for sourceType, remove the namespace.
365+
const bool g_usdShaderNameSpaceRegistration = USDShader::registerShaderNameSpace( "USD", "" );
366+
// Ideally this one should translate to `gl` however USDPreviewSurface and friends
367+
// have their sourceType set to `glslfx` so we leave these without a namespace.
368+
const bool g_glslfxShaderNameSpaceRegistration = USDShader::registerShaderNameSpace( "glslfx", "" );
369+
// Prman tends to register their built-in OSL shaders as `OSL` sourceType, which might
370+
// need to be re-looked at if we don't want Prman built-in shaders to be used in
371+
// other OSL-compatible renderers or in other GafferOSL functionality.
372+
const bool g_oslShaderNameSpaceRegistration = USDShader::registerShaderNameSpace( "OSL", "osl" );
373+
374+
// TODO: Put these registers into their respective plugins maybe?
375+
376+
// We shouldn't use Arnold shaders as USD shaders anyways as they're already available in Gaffer from Arnold itself.
377+
const bool g_arnoldShaderNameSpaceRegistration = USDShader::registerShaderNameSpace( "arnold", "ai" );
378+
const bool g_prmanShaderNameSpaceRegistration = USDShader::registerShaderNameSpace( "RmanCpp", "ri" );
379+
322380

323381
} // namespace
324382

@@ -386,7 +444,7 @@ void USDShader::loadShader( const std::string &shaderName, bool keepExistingValu
386444
// Set name and type and delete old parameters if necessary.
387445

388446
namePlug()->setValue( shaderName );
389-
typePlug()->setValue( "surface" );
447+
typePlug()->setValue( remapShaderType( shader->GetSourceType(), shader->GetContext() ) );
390448

391449
Plug *parametersPlug = this->parametersPlug()->source();
392450
Plug *outPlug = this->outPlug();
@@ -474,3 +532,9 @@ IECore::ConstCompoundObjectPtr USDShader::attributes( const Gaffer::Plug *output
474532
}
475533
return result;
476534
}
535+
536+
bool USDShader::registerShaderNameSpace( const IECore::InternedString sourceType, const IECore::InternedString nameSpace )
537+
{
538+
ShaderRemap &shaderNS = shaderNameSpace();
539+
return shaderNS.insert( { sourceType, nameSpace } ).second;
540+
}

0 commit comments

Comments
 (0)