Understanding Render Layers


#1

I’m trying to understand the structure under the hood of maya for a little project.

Where is the information stored for render layers??

Each node has attributes that you can get via getAttr but when this attribute changes depending on the render layer how is it accessed? If an object is on 4 render layers does it have 4 attributes that are in a list and only the active attribute is return?

Is that information stored on the node or is it stored in the render layer?

Is there a limit to what can be stored in a render layer?


#2

It is possible, however is not easy to get the value of an attribute from a render layer, without actually being in that current render layer. Normally you would have to switch to a render layer to query proper values.

With this method below, you can get the attribute value without having to switch to the render layer you need to get the value from- maybe this will also help u understand how render layer adjustment plugs work.

Each RenderLayer has a node. Each attribute with an override on that layer, is on the node connected to *.adjustment, which is a multi attribute type that has compound or sibling attributes plug and value. These attributes hold the override plug attr and value on that layer.

Using Pymel, you can say renderLayer.adjustmentPlug(attributeName).siblings() to get both plug and value in a list. The plug is the override attr, which when you do overrideAttr.get(), will return the proper value on that layer.

To Add, layer nodes don’t show up in the outliner unless you have only show dag objects turned checked off.

If you view them in the node editor, with auxiliary nodes turned on, you can see they are connected to 2 diff nodes. One is called renderLayerManager and the other is defaultRenderingList. With these connections, is how it gets its ID and also how it shows up in the render layer tab.

Hope this helps you understand render layers.


#3

Thanks Dan, that’s really interesting.

I’m surprised it’s so hard to access… setting attributes per render layer looks like it’s going to be more complicated than I imagine, or I guess I just set the active render layer and then just set the attribute then change render layer and repeat… which I don’t really like, I’d prefer to be able to reference directly the render layers attribute values… I’ll play with it and have a think. We have an insanely powerful tool for managing our render layers in 3dsmax but transfering it over to Maya I’m trying to work out whether I should build it on top of the Render layers feature or work independently.


#4

The easiest way, is this method “just set the active render layer and then just set the attribute then change render layer and repeat”. However, we didn’t like doing this in our production pipeline… so we created a getLayerAttr(layer, attr) method that uses the method i explained in my previous post… To get the actual override attribute from the layer node. And then we can get or set values as simply as we want too.

I would def recommend PyMel, as it makes the entire maya pipeline object based.

Let me know if you need any assistance setting this up.


#5

Are you Freelance?


#6

I can do Freelance, yes.


#7

You could also create a set for the ‘renderLayer’ node type. Then its easily visible in the outliner. Here is a mel script so you can create a set for every node type you like:

 // creator : sciloop
   //
   // Create for the input nodeTypes a set.
   //
   // second parameter : 'includeDerivedNodes', 'NOTIncludeDerivedNodes'.
   //
   // example :
   //
   // sciCreateSetForNodeType( {"renderLayer"}, "includeDerivedNodes" );
   //
   global proc sciCreateSetForNodeType(	string $nodeTypes[],
   										string $includeDerivedNodeTypes )
   {
   	string $sn = " // sciloop message : mel :"+
   					" 'sciCreateSetForNodeType' :";
   
   	if( size($nodeTypes)==0 )
   	{
   		print( $sn+" input string array is empty."+
   					" Select a node, please.
" );
   		return;
   	}
   
   	// For every nodeType in the input list.
   	//
   	while( size($nodeTypes)!=0 )
   	{
   		string $type = $nodeTypes[0];
   
   		// If we want to put also all derived
   		// nodeTypes of the current nodeType
   		// in the set, do it here.
   		//
   		string $derivedNodeTypes[] = {};
   		string $derivedString = "";
   
   		if( $includeDerivedNodeTypes=="includeDerivedNodes" )
   		{
   			$derivedString = "derived_";
   
   			if( catchQuiet($derivedNodeTypes = nodeType(	"-derived",
   															"-isTypeName",
   															$type)) )
   			{
   				print( $sn+" could not get derived node types"+
   				"		 for a nodeType named : '"+$type+"'.
" );
   			}
   		}
   		else
   		{$derivedNodeTypes[0] = $type;}
   
   		string $allConcreteNodes[] = {};
   		string $setNode = "";
   
   		// For every nodeType that derives from the current nodeType.
   		//
   		for( $derivedType in $derivedNodeTypes )
   		{
   			string $objects[] = {};
   
   			if( catchQuiet($objects = lsType($derivedType)) )
   			{
   				print( $sn+" could not get objects for a"+
   						" nodeType named : '"+$derivedType+"'.
" );
   				stringArrayRemove( {$derivedType}, $derivedNodeTypes );
   
   				continue;
   			}
   
   			// Remove the last element : <done>
   			//
   			$objects = stringArrayRemove( {"<done>"}, $objects );
   
   			if( $derivedType=="objectSet" )
   			{
   				print(	$sn+" do not create sets for nodeType :"+
   						" 'objectSet'.!
" );
   
   				$derivedNodeTypes = stringArrayRemove(	{$derivedType},
   														$derivedNodeTypes );
   
   				continue;
   			}
   
   			if( !objExists("set_"+$type+"_"+$derivedString) )
   			{
   				$setNode = createNode(	"-skipSelect",
   										"-n", "set_"+$type+"_"+$derivedString,
   										"objectSet" );
   			}
   
   			if( catchQuiet(sets("-include", $setNode, $objects)) )
   			{
   				print( $sn+" could not add current object"+
   						" array to the set : '"+$setNode+"'.
" );
   			}
   		}
   
   		string $set_master = "set_master";
   
   		if( objExists($set_master) )
   		{catchQuiet( sets("-include", $set_master, $setNode) );}
   
   		// Delete all occurences of the current nodeType from the array.
   		//
   		$nodeTypes = stringArrayRemove( {$type}, $nodeTypes );
   	}
   
   	print( $sn+" done!
" );
   }

#8

It’s the thing I find weird about RenderLayers is knowing which attributes have been changed.


#9

What if I wanted to return an object on a Render Layer to it’s initial state, but I didn’t want to just re-apply the settings…

i.e. If I change the material of an object on a render layer , then re-apply the original object’s material, if I then switch to the Master Layer and change the material of this object, in the other render layer sticks with the assigned material rather than changing to the masterLayer’s material.

Looking for both the UI and script solution to this…