Installing aaOcean


Install for mental ray

  1. Extract the aaOcean download package.
  2. Create a new workgroup (or use the Softimage User location).
  3. Copy the aaOceanDataShader.dll and aaOceanShaderDefinition.dll from here:


  4. Copy aaOceanDeformer.dll from here:



$MY_WORKGROUP is just my workgroup location. For example:

Did you notice that the mental ray version of aaOcean doesn’t have a SPDL file? That’s because it has a shader definition plugin instead.

Install for Arnold

  1. Copy


  2. Copy


  3. Copy



$MY_WORKGROUP is just my workgroup location. For example:

[SItoA] Installing the alShaders in Softimage

Cross-posted from the Arnold Support Corner.

Here’s how to install third-party, SPDL-based shaders, like alShaders, so that you can use them with SItoA.


In these instructions, $AL_SHADERS is the location where you extracted the alShaders download. For example, C:\solidangle\alShaders\alShaders-win-0.4.0b18-ai4.2.0.6.

$SITOA_WORKGROUP is the SItoA workgroup location. For example, C:\Users\StephenBlair\softimage\workgroups\sita-3.3.0-2014.

  1. Copy the alShader DLLs from

  2. Create a spdl folder in your Addons\SItoA\Application folder:

  3. Copy the alShader spdl files from

  4. Restart Softimage. The alShaders should show up in the Render Tree preset manager, and assuming that your version of alShaders is compatible with your SItoA, they’ll work in a render too.

Tip Don’t create an alShader from the Arnold > DLL Shaders menu; it won’t pick up the SPDL and you’ll get a raw PPG (and a raw render tree node too).

Getting all shaders under a light

Given something like this:
light_disconnected shaders
Here’s how you get all shaders under a light, even the disconnected ones:

from sipyutils import si		# win32com.client.Dispatch('XSI.Application')
from sipyutils import log		# LogMessage
from sipyutils import C			# win32com.client.constants
from sipyutils import disp		# win32com.client.Dispatch

si = si()

def dispFix( badDispatch ):
    import win32com.client.dynamic
    # Re-Wraps a bad dispatch into a working one:
    return win32com.client.dynamic.Dispatch(badDispatch)

oLight = si.Selection(0)

#import win32com.client
oDisconnected = disp( "XSI.Collection" )

if oLight.IsClassOf( C.siLightID ):
	for oShader in oLight.GetAllShaders():
		oOut = dispFix( oShader.Parameters( "out" ) )
		if oOut.Targets.Count == 0:
			oDisconnected.Add( oShader )
log( oDisconnected.GetAsText() )

Hat tip: Matt Lind, who provided the GetAllShaders answer to the question “how to get all shaders in a light, even the disconnected ones”

Scripting: Finding all materials that contain a specific shader

Given a shader, it’s not too hard to find all materials that use (aka “own”) an instance of that shader. Here’s a Python snippet that does just that.

Note that I don’t check whether or not the shader is actually used. This snippet finds all instances, whether they are used or not (last week I posted another snippet for checking whether a shader instances was ultimately connected to the material).

from sipyutils import si			# win32com.client.Dispatch('XSI.Application')
from sipyutils import disp		# win32com.client.Dispatch
from sipyutils import C			# win32com.client.constants
si = si()

def get_materials_that_use_shader( s ):	
	mats = disp( "XSI.Collection" )	
	oShaderDef = si.GetShaderDef( s.ProgID )
	for i in oShaderDef.ShaderInstances:
			mats.Add( i.Owners(0) )
		except Exception:

	mats.Unique = True
	return mats

# Find all materials that use a specific shader
s = si.Selection(0)
if s.IsClassOf( C.siShaderID ):
	mats = get_materials_that_use_shader( s )
	for m in mats:
		print( "%s in %s" % (m.Name, m.Owners(0)) )
	si.LogMessage( "Cannot find shader instances. Please select a shader." )

# Material in Sources.Materials.DefaultLib
# Material1 in Sources.Materials.DefaultLib
# Material2 in Sources.Materials.DefaultLib
# Material3 in Sources.Materials.DefaultLib
# Material7 in Sources.Materials.DefaultLib
# Material6 in Sources.Materials.DefaultLib
# Material5 in Sources.Materials.DefaultLib
# Material4 in Sources.Materials.DefaultLib

Finding shader nodes with no connections

Here’s a JScript snippet that finds render tree nodes that are not connected to anything in the render tree.

LogMessage( isConnected( Selection(0) ) );

function isConnected( o )
	var oDR = XSIUtils.DataRepository ;

	var strOpInfo = oDR.GetConnectionStackInfo( o )
//	LogMessage( strOpInfo );
	var oTopNode = ParseXML( strOpInfo ) ;

	var oConnections = oTopNode.childNodes ;
	if ( oConnections.length == 0 )
		return false;
	return true;

function ParseXML( strXML )
	var oXMLParser = new ActiveXObject("Microsoft.XMLDOM") 
	oXMLParser.async = false	
	oXMLParser.loadXML( strXML ) ;

	if (oXMLParser.parseError.errorCode != 0) 
		logmessage( "Invalid XML " + oXMLParser.parseError.reason , siError ) ;	
		return null ;

	// the xsi_file node
	// If this is NULL we must have failed to load the XML
	var oTopNode = oXMLParser.documentElement ;

	return oTopNode ;

Most of this JScript came from the SDK Explorer code in $XSI_HOME\Addons\sdkui\Application\Plugins\SDKExplorer.js, because I noticed that disconnected shaders would have an empty connection stack, and I didn’t want to go through all the parameters individually looking for connections.

Here’s a Python version that does a little more: it follows the output connections to check whether or not the shader is ultimately connected the material.

# Python Code
import xml.etree.ElementTree as etree

def is_connected( o ):
	if not o.IsClassOf( 52 ):
		print "Input is not a shader"
		return False
	sXML = XSIUtils.DataRepository.GetConnectionStackInfo( o )
	root = etree.fromstring( sXML )
	for connection in root:
		if connection.find('type').text == 'out':
			x = Application.Dictionary.GetObject( connection.find('object').text )
			return True if x.IsClassOf( 64 ) else is_connected( x )
	return False

print is_connected( Application.Selection(0) )

Getting a list of all shaders in a render tree

Here’s a Python snippet that gets all the shaders in the render tree for a specific material. As usual, I always feel that my Python snippet could be made more pythonic; for now, this will have to do…

PS The Shader reference page has a VBScript example, but that doesn’t work anymore because it was written before ShaderParameters were introduced.

from sipyutils import si		# win32com.client.Dispatch('XSI.Application')

import win32com.client
coll = win32com.client.Dispatch( "XSI.Collection" )

def doit( s, coll ):

	for p in s.Parameters:
		if p.Source and p.Source.IsClassOf( C.siShaderParameterID ):
			print p.Source.Parent.Name
			coll.Add( p.Source.Parent )
			doit( p.Source.Parent, coll )
	for l in s.TextureLayers:
		for y in l.Parameters:
			if y.Source and y.Source.IsClassOf( C.siShaderParameterID ):
				print y.Source.Parent.Name
				coll.Add( y.Source.Parent )
				doit( y.Source.Parent, coll )

# Get a material or shader to use as a starting point
mat = si.Dictionary.GetObject("Sources.Materials.DefaultLib.Architectural")
doit( mat, coll )

coll.Unique = True
coll.Add( mat.AllImageClips.GetAsText() )

This snippet worked for this [nonsensical test] render tree:

Overriding SPDL defaults

In the old days, if you didn’t like some default shader parameter setting, you had to edit a SPDL file and generate a new preset. As of 2011, you can use the ObjectModel (OM) to dynamically update the shader definition.

For example, if you run this Python snippet in the script editor, then the next time you create an Environment shader, it will have some different defaults:

  • Environment Mode will default to Cylinder
  • Transformation will have a connection icon
  • Background Intensity will default to 0.5
from siutils import si		# Application
from siutils import log		# LogMessage
from siutils import disp	# win32com.client.Dispatch
from siutils import C		# win32com.client.constants

# Get ShaderDef for the Environment shader
sProgID = "Softimage.sib_environment.1.0"
oDef = si.GetShaderDef( "Softimage.sib_environment.1.0" )

# Get ShaderParamDef for the Tranformation parameter
oTransform = oDef.InputParamDefs.GetParamDefByName( "transform" )

# Make it texturable so it has a connection icon
oTransform.Texturable = True

# Make Cylinder the default Environment mode
oParam = oDef.InputParamDefs.GetParamDefByName( "mode" )
oParam.DefaultValue = 1

# Change the default background intensity to 0.5
oParam = oDef.InputParamDefs.GetParamDefByName( "background_intensity" )
oParam.DefaultValue = 0.5

So, that’s how you update a shader definition. Now, all you have to do is stick that code into a siOnCreateShaderDef event plugin, and every time you create an Environment shader, it will have the defaults you want

import win32com.client
from win32com.client import constants

null = None
false = 0
true = 1

def XSILoadPlugin( in_reg ):
	in_reg.Author = "blairs"
	in_reg.Name = "ShaderDef Plug-in"
	in_reg.Major = 1
	in_reg.Minor = 0


	return true

def XSIUnloadPlugin( in_reg ):
	strPluginName = in_reg.Name
	return true

# Callback for the CreateShaderDef event.
def CreateShaderDef_OnEvent( in_ctxt ):
	oDef = in_ctxt.GetAttribute("ShaderDef")
	sProgID = str(in_ctxt.GetAttribute("ProgID"))
	if "Softimage.sib_environment.1.0" in sProgID:
		oDef.InputParamDefs.GetParamDefByName( "transform" ).Texturable = True

# 	Return value is ignored as this event can not be aborted.
	return true

Tip: Use the SDK Explorer (CTRL+SHIFT+4) to get the ProgID of a shader.