Shaders and different camera views

I’m sorta stumped on how to arrange my scene graph so I can achieve a post-processing effect along with custom per-node shaders.

Here’s how it’s organized now:

  • On base.cam, I have an initial state which contains my primary material shader (shadows, normal mapping, cube mapping, etc)

  • On some objects in my scene graph, I am overriding the initial state by attaching a custom shader. (Some objects need different material effects, or specialized ones, such as a terrain shader.)

  • A post-process effect pass. (Based on the glow shader.) It creates a camera of its own that has a shader applied to the camera as an initial state.

Now, my question is – Since I have assigned customized shaders specifically to some members of the scene graph, these shaders are showing up under the post-process camera. The post-process camera’s initial state is overriding what is found in base.render, which is what I would expect and want, but I don’t know how to turn off the custom shaders for nodes that are rendered under this camera.

Is what I want possible, or do I need to organize things in a different manner?

What you want is possible, but it’s a klunky interface. There are two approaches.

(1) Use a high override on the ShaderAttrib you assign to the post-process camera’s initial state, so that it overrides the ShaderAttribs on the child nodes. You can do this most easily if you use a temporary NodePath to build up this initial state, like this:

temp = NodePath('')
temp.setShader(..., 100)
cam.node().setInitialState(temp.getState())

(2) Use per-camera tag states. This allows you to set a different state for each camera on any given node. The idea is you define a tag state key on the camera:

cam.node().setTagStateKey('cam')

And a pre-canned set of different states you might want to apply:

cam.node().setTagState('avatar', avatarState)
cam.node().setTagState('tree', treeState)

Then, on your nodes, you simply set the appropriate state type with the tag interface:

myAvatar.setTag('cam', 'avatar')
tree1.setTag('cam', tree')

For each camera, you can have a different set of setTagState() calls, defining a different meaning of ‘avatar’ or ‘tree’ for your different cameras.

David

Thanks! Exactly what I was looking for.

#1 is a short-term solution that lets me proceed, but #2 will be a lot more useful.

I should have realized that render states would have priorities, just like everything else.