How does the Glow Shader work?

I have modified the Tut-Glow-Advanced.py to render one Tron with glow, and one Tron without glow. I took code from an existing forum post here: https://discourse.panda3d.org/viewtopic.php?t=3647&highlight=kglow

        #create the shader that will determime what parts of the scene will glow
        glowShader=Shader.load(MYDIR + "/glowShader.sha")

        # NEW
        render.setShaderInput('glow', Vec4(0,0,0,0))

        # load our model
        self.tron=Actor()
        self.tron.loadModel("models/tron")
        self.tron.reparentTo(render)
        # NEW
        self.tron.setShaderInput('glow', Vec4(1,0,0,0))

        self.tron2=Actor()
        self.tron2.loadModel("models/tron")
        self.tron2.reparentTo(render)
        self.tron2.setPos(10,0,0)

And the shader:

void fshader(float2 l_texcoord0 : TEXCOORD0,
       	     uniform sampler2D tex_0 : TEXUNIT0,
             uniform float4 k_glow,
	     out float4 o_color : COLOR)
{
	float4 texColor=tex2D(tex_0, l_texcoord0);
	o_color=texColor*texColor.w*k_glow.x;
}

This works great! The first Tron glows and the second does not. My question is why does it work that way? I understand the pipeline of glowBuffer->blurXBuffer->blurYBuffer->render2d, and I can see how without the setShaderInput(‘glow’, Vec4(0,0,0,0)), all non-black and non-transparent parts of the scene get blurred.
My uncertainty comes from the fact that the shader is set on a NodePath that is not in the render or render2d hierarchy, yet render and self.tron set the shader input variable and the shader knows which pixels belong to which NodePath.

        # Tell the glow camera to use the glow shader
        tempnode = NodePath(PandaNode("temp node"))
        tempnode.setShader(glowShader)
        glowCamera.node().setInitialState(tempnode.getState())

I thought that a shader applies to the NodePath that calls setShader and to all of its children, but tempnode (and glowCamera?) are not related to render, right? Does the fact that glowCamera uses base.cam.node().getLens() have something to do with it?

To your last question: the idea is to create a temporary node, apply the shader to it, then grab its render state. Now you have a render state with a shader attribute. You then use it to set the initial state of the camera, which means everything that camera renders has that shader.
– something like that.

Out of curiosity I changed

        # Tell the glow camera to use the glow shader
        tempnode = NodePath(PandaNode("temp node"))
        tempnode.setShader(glowShader)
        glowCamera.node().setInitialState(tempnode.getState())

To

        # Tell the glow camera to use the glow shader
        glowCamera.setShader(glowShader)

And that made both trons glow. I’m not sure why…

both your commands say about the same thing:

  • the first told the camera to use the same state as tempnode as it default state
  • the second told the camera to use a default state with the shader ‘glowshader’

since the only state of your tempnode was the shader, the result is the same

SylHar,
That is exactly what I thought, but the results are not the same. Applying the shader directly to the glowCamera causes the entire scene to have the glow effect, regardless of the shader input from render and tron.

Oh! sorry, I haven’t read carefully enough

In your first command you set the ‘initial state’ which means if a nodepath with another state, the nodepath state will be used.
The second command tell the camera to use the shader, no matter what ( overriding the previous state of the nodePath when using the camera)

… or so I think. I had problem with all this stuff when I was creating my shadowCam.