Using a display of regions with a single camera and objects

I was thinking about implementing multi-pass rendering. However, studying the examples in the OpenGL network, I noticed that it is possible to use different object States for each pass. However, in Panda, I have to duplicate several cameras and objects.

from direct.showbase.ShowBase import ShowBase
from panda3d.core import DirectionalLight, AmbientLight, LVector4, StencilAttrib, NodePath, Camera
from direct.task import Task

class Demo(ShowBase):

    def __init__(self):
        ShowBase.__init__(self)

        self.disableMouse()
        self.camera.setPos(0, -10 , 0)

        # --- Stage 1 we write the silhouettes of the figures in the stencil buffer.

        base.win.setSort(0)
        cube_stencil = loader.loadModel("box")
        cube_stencil.setColor(LVector4(0, 1, 0, 1))
        cube_stencil.reparentTo(render)

        # --- In step 2, we render the cube using the stencil mask.

        # Create a new scene node.
        render2 = NodePath('render2')

        # Create a camera and configure the camera.
        self.camera2 = render2.attachNewNode(Camera('cam'))
        self.camera2.node().setLens(base.cam.node().getLens())
        self.camera2.setPos(0, -10 , 0)

        # Create a display region.
        self.display_my = base.win.makeDisplayRegion()
        self.display_my.setSort(1)
        
        self.display_my.setCullCallback(self.Render_display2)

        self.display_my.setClearColorActive(True)
        self.display_my.setClearColor(base.getBackgroundColor())

        self.display_my.setClearDepthActive(True)
        self.display_my.setClearDepth(1.0)

        # Set the camera for display.
        self.display_my.setCamera(self.camera2)

        cube_render = loader.loadModel("box")
        cube_render.setColor(LVector4(1, 0, 0, 1))
        cube_render.reparentTo(render2)

        # Press "2" on the keyboard to disable the second stage of rendering.
        self.accept("2", self.display_my_active)

        self.status = True
        #Disable region of the display for stage 2.
    def display_my_active(self):
        self.status = not self.status
        self.display_my.setActive(self.status)
        
        
    def Render_display2(self, cbdata):
        cbdata.upcall()
        print ("Render2")


demo = Demo()
demo.run()

The question is simple, how to use one camera. In Discord, RDB told me that this is possible. Also note that I had to create an additional reference to the cube model. While in OpenGL examples, this is not necessary.

There is a second question, how to set up a callback when the green box is rendered?

Hmm, I just noticed that there is a mirror inversion in the texture. I wonder what this might be related to… Oh Yes, with color inversion.

You have created a second scene graph. This is not necessary. You need only a single scene graph. You can hide certain objects for a specific camera only if needed. You can set an initial state or a tag state on the camera to render objects differently through it.

You don’t need to create a second camera in normal cases, except if you want to use different render attributes for the second pass. This is because of the way the Panda cull process works; it culls the scene for a particular camera, so if the scene needs to be culled differently (due to a different state), it needs a separate camera right now. This is a limitation we hope to eliminate in the future.
To assign a different state when rendering the same scene from a different camera, you can use camera.setInitialState(state). If you need more control, you need to look into tag states.

If you want a callback when the green box is rendered, you can either use a CallbackNode on it (possibly hidden to one of the cameras if you have both cameras rendering the same scene), or you can assign a callback to the entire display region that is rendering the box green.

That’s the question. And I don’t know how to do it.