Multi-pass rendering configure

Thanks to rdb and its iron patience. I was able to set up multi-pass rendering. A simple and useless example of how to configure it.

from direct.showbase.ShowBase import ShowBase
from panda3d.core import NodePath
from panda3d.core import Shader, BitMask32, LVector4

def green():
    
    vertex = """
            #version 330
            
            uniform mat4 p3d_ModelViewProjectionMatrix;
            in vec4 p3d_Vertex;
            in vec2 p3d_MultiTexCoord0;
            out vec2 texcoord;

            void main() {
                gl_Position = p3d_ModelViewProjectionMatrix * p3d_Vertex;
                texcoord = p3d_MultiTexCoord0;
            }
            """

    fragment = """
            #version 330

            uniform sampler2D p3d_Texture0;

            in vec2 texcoord;
            out vec4 color;

            void main() {
              color = vec4(0, 1, 0, 1)*texture(p3d_Texture0, texcoord);
            }
            """

    return Shader.make(Shader.SL_GLSL, vertex, fragment)



def blue():
    
    vertex = """
            #version 330
            
            uniform mat4 p3d_ModelViewProjectionMatrix;
            in vec4 p3d_Vertex;
            in vec2 p3d_MultiTexCoord0;
            out vec2 texcoord;

            void main() {
                gl_Position = p3d_ModelViewProjectionMatrix * p3d_Vertex;
                texcoord = p3d_MultiTexCoord0;
            }
            """

    fragment = """
            #version 330

            uniform sampler2D p3d_Texture0;

            in vec2 texcoord;
            out vec4 color;

            void main() {
              color = vec4(0, 0, 1, 1)*texture(p3d_Texture0, texcoord);
            }
            """

    return Shader.make(Shader.SL_GLSL, vertex, fragment)
    
    
def red():
    
    vertex = """
            #version 330
            
            uniform mat4 p3d_ModelViewProjectionMatrix;
            in vec4 p3d_Vertex;
            in vec2 p3d_MultiTexCoord0;
            out vec2 texcoord;

            void main() {
                gl_Position = p3d_ModelViewProjectionMatrix * p3d_Vertex;
                texcoord = p3d_MultiTexCoord0;
            }
            """

    fragment = """
            #version 330

            uniform sampler2D p3d_Texture0;

            in vec2 texcoord;
            out vec4 color;

            void main() {
              color = vec4(1, 0, 0, 1)*texture(p3d_Texture0, texcoord);
            }
            """

    return Shader.make(Shader.SL_GLSL, vertex, fragment)


class Demo(ShowBase):

    def __init__(self):
        ShowBase.__init__(self)
        
        #self.cam.node().setCameraMask(BitMask32.bit(0))

        Buffer0 = base.win.makeTextureBuffer("stage4", 512, 512)
        Buffer0.setSort(0)
        Buffer0.setClearColor(LVector4(0, 0, 0, 1))
        # Creating a camera for the buffer.
        self.camera4 = base.makeCamera(Buffer0, lens=base.cam.node().getLens())
        
        Buffer1 = base.win.makeTextureBuffer("stage5", 512, 512)
        Buffer1.setSort(1)
        Buffer1.setClearColor(LVector4(0, 0, 0, 1))
        # Creating a camera for the buffer.
        self.camera5 = base.makeCamera(Buffer1, lens=base.cam.node().getLens())
        
        Buffer2= base.win.makeTextureBuffer("stage6", 512, 512)
        Buffer2.setSort(2)
        Buffer2.setClearColor(LVector4(0, 0, 0, 1))
        # Creating a camera for the buffer.
        self.camera6 = base.makeCamera(Buffer2, lens=base.cam.node().getLens())

        # Create a new scene.
        room = loader.load_model("box")
        room.setTag("Green", "True")
        room.setTag("Blue", "True")
        room.setTag("Red", "True")
        #room.hide(BitMask32.bit(0))
        room.reparent_to(render)
        
        green_render = NodePath("green_render")
        green_render.setShader(green())
        
        self.camera4.node().setTagStateKey("Green")
        self.camera4.node().setTagState("True", green_render.getState())

        blue_render = NodePath("blue_render")
        blue_render.setShader(blue())

        self.camera5.node().setTagStateKey("Blue")
        self.camera5.node().setTagState("True", blue_render.getState())

        red_render = NodePath("red_render")
        red_render.setShader(red())

        self.camera6.node().setTagStateKey("Red")
        self.camera6.node().setTagState("True", red_render.getState())

        # Your render-to-texture operations.  This code configures the viewer.
        self.accept("v", base.bufferViewer.toggleEnable)
        base.bufferViewer.setPosition("llcorner")
        base.bufferViewer.setCardSize(0.5, 0)

demo = Demo()
demo.run()
1 Like

How to set shader input on each stage? Only texture shader inputs work on my machine using this code, but not uniform inputs.

Is it too late to ask?

It should work.

green_render.setShaderInput("tint", (1.0, 0.5, 0.5, 1.0))
blue_render.setShaderInput("tint", (1.0, 0.1, 0.5, 1.0))
red_render.setShaderInput("tint", (0.3, 0.52, 0.5, 1.0))

https://docs.panda3d.org/1.10/python/programming/shaders/shader-basics#supplying-data-to-the-shader-manually

While researching this issue, I found that the data transfer to the shader is functioning normally at the initialization stage. But after starting the python loop, the data is no longer updated. Here is a test example.

from direct.showbase.ShowBase import ShowBase
from panda3d.core import NodePath
from panda3d.core import Shader, BitMask32, LVector4

def green():
    
    vertex = """
            #version 330
            
            uniform mat4 p3d_ModelViewProjectionMatrix;
            in vec4 p3d_Vertex;
            in vec2 p3d_MultiTexCoord0;
            out vec2 texcoord;

            void main() {
                gl_Position = p3d_ModelViewProjectionMatrix * p3d_Vertex;
                texcoord = p3d_MultiTexCoord0;
            }
            """

    fragment = """
            #version 330

            uniform sampler2D p3d_Texture0;

            in vec2 texcoord;
            out vec4 color;

            void main() {
              color = vec4(0, 1, 0, 1)*texture(p3d_Texture0, texcoord);
            }
            """

    return Shader.make(Shader.SL_GLSL, vertex, fragment)



def blue():
    
    vertex = """
            #version 330
            
            uniform mat4 p3d_ModelViewProjectionMatrix;
            in vec4 p3d_Vertex;
            in vec2 p3d_MultiTexCoord0;
            out vec2 texcoord;

            void main() {
                gl_Position = p3d_ModelViewProjectionMatrix * p3d_Vertex;
                texcoord = p3d_MultiTexCoord0;
            }
            """

    fragment = """
            #version 330

            uniform sampler2D p3d_Texture0;

            in vec2 texcoord;
            out vec4 color;

            void main() {
              color = vec4(0, 0, 1, 1)*texture(p3d_Texture0, texcoord);
            }
            """

    return Shader.make(Shader.SL_GLSL, vertex, fragment)
    
    
def red():
    
    vertex = """
            #version 330
            
            uniform mat4 p3d_ModelViewProjectionMatrix;
            in vec4 p3d_Vertex;
            in vec2 p3d_MultiTexCoord0;
            out vec2 texcoord;

            void main() {
                gl_Position = p3d_ModelViewProjectionMatrix * p3d_Vertex;
                texcoord = p3d_MultiTexCoord0;
            }
            """

    fragment = """
            #version 330

            uniform sampler2D p3d_Texture0;

            uniform int flag;

            in vec2 texcoord;
            out vec4 color;

            void main() {

              if (flag == 1){ color = vec4(1, 0, 0, 1)*texture(p3d_Texture0, texcoord);}
              else { color = vec4(1, 1, 0, 1);}
            }
            """

    return Shader.make(Shader.SL_GLSL, vertex, fragment)


class Demo(ShowBase):

    def __init__(self):
        ShowBase.__init__(self)
        
        #self.cam.node().setCameraMask(BitMask32.bit(0))

        Buffer0 = base.win.makeTextureBuffer("stage4", 512, 512)
        Buffer0.setSort(0)
        Buffer0.setClearColor(LVector4(0, 0, 0, 1))
        # Creating a camera for the buffer.
        self.camera4 = base.makeCamera(Buffer0, lens=base.cam.node().getLens())
        
        Buffer1 = base.win.makeTextureBuffer("stage5", 512, 512)
        Buffer1.setSort(1)
        Buffer1.setClearColor(LVector4(0, 0, 0, 1))
        # Creating a camera for the buffer.
        self.camera5 = base.makeCamera(Buffer1, lens=base.cam.node().getLens())
        
        Buffer2= base.win.makeTextureBuffer("stage6", 512, 512)
        Buffer2.setSort(2)
        Buffer2.setClearColor(LVector4(0, 0, 0, 1))
        # Creating a camera for the buffer.
        self.camera6 = base.makeCamera(Buffer2, lens=base.cam.node().getLens())

        # Create a new scene.
        room = loader.load_model("box")
        room.setTag("Green", "True")
        room.setTag("Blue", "True")
        room.setTag("Red", "True")
        #room.hide(BitMask32.bit(0))
        room.reparent_to(render)
        
        green_render = NodePath("green_render")
        green_render.setShader(green())
        
        self.camera4.node().setTagStateKey("Green")
        self.camera4.node().setTagState("True", green_render.getState())

        blue_render = NodePath("blue_render")
        blue_render.setShader(blue())

        self.camera5.node().setTagStateKey("Blue")
        self.camera5.node().setTagState("True", blue_render.getState())

        self.flag = 0
        self.red_render = NodePath("red_render")
        self.red_render.setShaderInput("flag", self.flag)
        self.red_render.setShader(red())

        self.camera6.node().setTagStateKey("Red")
        self.camera6.node().setTagState("True", self.red_render.getState())

        # Your render-to-texture operations.  This code configures the viewer.
        self.accept("v", base.bufferViewer.toggleEnable)
        base.bufferViewer.setPosition("llcorner")
        base.bufferViewer.setCardSize(0.5, 0)
        
        base.accept("1", self.set_flag, extraArgs = [0])
        base.accept("2", self.set_flag, extraArgs = [1])

        taskMgr.add(self.update, "update")

    def set_flag(self, args):
        self.flag = args

    def update (self, task):
        print(self.flag)
        self.red_render.set_shader_input("flag", self.flag)
        return task.cont


demo = Demo()
demo.run()

Change the variable flag 1 - 0, and press the V key to view the result, however, at the time of program execution, keyboard keys 1 - 2 have no effect.

wow, thanks for the fast reply.
I stayed up last night, just realized asked the wrong question, but you already answered.
I found that setShaderInput can not change uniform inputs in this tagstate setting. Maybe should use shaderattrib, and trying to find out how to do it.
Or it’s possible altering texture in cpu would be faster.

@sbxzy
I figured it out, you need to set a similar rendering stage in parallel for the camera that renders the buffer.

from direct.showbase.ShowBase import ShowBase
from panda3d.core import NodePath
from panda3d.core import Shader, BitMask32, LVector4

def green():
    
    vertex = """
            #version 330
            
            uniform mat4 p3d_ModelViewProjectionMatrix;
            in vec4 p3d_Vertex;
            in vec2 p3d_MultiTexCoord0;
            out vec2 texcoord;

            void main() {
                gl_Position = p3d_ModelViewProjectionMatrix * p3d_Vertex;
                texcoord = p3d_MultiTexCoord0;
            }
            """

    fragment = """
            #version 330

            uniform sampler2D p3d_Texture0;

            in vec2 texcoord;
            out vec4 color;

            void main() {
              color = vec4(0, 1, 0, 1)*texture(p3d_Texture0, texcoord);
            }
            """

    return Shader.make(Shader.SL_GLSL, vertex, fragment)



def blue():
    
    vertex = """
            #version 330
            
            uniform mat4 p3d_ModelViewProjectionMatrix;
            in vec4 p3d_Vertex;
            in vec2 p3d_MultiTexCoord0;
            out vec2 texcoord;

            void main() {
                gl_Position = p3d_ModelViewProjectionMatrix * p3d_Vertex;
                texcoord = p3d_MultiTexCoord0;
            }
            """

    fragment = """
            #version 330

            uniform sampler2D p3d_Texture0;

            in vec2 texcoord;
            out vec4 color;

            void main() {
              color = vec4(0, 0, 1, 1)*texture(p3d_Texture0, texcoord);
            }
            """

    return Shader.make(Shader.SL_GLSL, vertex, fragment)
    
    
def red():
    
    vertex = """
            #version 330
            
            uniform mat4 p3d_ModelViewProjectionMatrix;
            in vec4 p3d_Vertex;
            in vec2 p3d_MultiTexCoord0;
            out vec2 texcoord;

            void main() {
                gl_Position = p3d_ModelViewProjectionMatrix * p3d_Vertex;
                texcoord = p3d_MultiTexCoord0;
            }
            """

    fragment = """
            #version 330

            uniform sampler2D p3d_Texture0;

            uniform int flag;

            in vec2 texcoord;
            out vec4 color;

            void main() {

              if (flag == 1){ color = vec4(1, 0, 0, 1)*texture(p3d_Texture0, texcoord);}
              else { color = vec4(1, 1, 0, 1);}
            }
            """

    return Shader.make(Shader.SL_GLSL, vertex, fragment)


class Demo(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)
        
        #self.cam.node().setCameraMask(BitMask32.bit(0))

        Buffer0 = base.win.makeTextureBuffer("stage4", 512, 512)
        Buffer0.setSort(0)
        Buffer0.setClearColor(LVector4(0, 0, 0, 1))
        # Creating a camera for the buffer.
        self.camera4 = base.makeCamera(Buffer0, lens=base.cam.node().getLens())
        
        Buffer1 = base.win.makeTextureBuffer("stage5", 512, 512)
        Buffer1.setSort(1)
        Buffer1.setClearColor(LVector4(0, 0, 0, 1))
        # Creating a camera for the buffer.
        self.camera5 = base.makeCamera(Buffer1, lens=base.cam.node().getLens())
        
        Buffer2= base.win.makeTextureBuffer("stage6", 512, 512)
        Buffer2.setSort(2)
        Buffer2.setClearColor(LVector4(0, 0, 0, 1))
        # Creating a camera for the buffer.
        self.camera6 = base.makeCamera(Buffer2, lens=base.cam.node().getLens())

        # Create a new scene.
        room = loader.load_model("box")
        room.setTag("Green", "True")
        room.setTag("Blue", "True")
        room.setTag("Red", "True")
        #room.hide(BitMask32.bit(0))
        room.reparent_to(render)
        
        green_render = NodePath("green_render")
        green_render.setShader(green())
        
        self.camera4.node().setTagStateKey("Green")
        self.camera4.node().setTagState("True", green_render.getState())

        blue_render = NodePath("blue_render")
        blue_render.setShader(blue())

        self.camera5.node().setTagStateKey("Blue")
        self.camera5.node().setTagState("True", blue_render.getState())

        self.red_render = NodePath("red_render")
        self.red_render.setShaderInput("flag", 1)
        self.red_render.setShader(red())

        self.camera6.node().setTagStateKey("Red")
        self.camera6.node().setTagState("True", self.red_render.getState())

        # Your render-to-texture operations.  This code configures the viewer.
        self.accept("v", base.bufferViewer.toggleEnable)
        base.bufferViewer.setPosition("llcorner")
        base.bufferViewer.setCardSize(0.5, 0)
        
        base.accept("1", self.set_flag, extraArgs = [0])
        base.accept("2", self.set_flag, extraArgs = [1])

    def set_flag(self, args):
        self.red_render.setShaderInput("flag", args)
        self.camera6.node().setTagState("True", self.red_render.getState())

demo = Demo()
demo.run()