Search code examples
python-3.xqt5pyside2qt3d

Qt3D Window and two layers, viewports, layerfilters, etc


I want to code a Qt3DWindow where I would have two QLayer-s, QLayerFilter-s, QViewport-s, etc. I need this because I want to render entities in QViewport 1 in a usual way and entities in QViewport 2 always visible (even when they are actually behind entities 1).

Here is my code:

class Window(Qt3DExtras.Qt3DWindow):
    def __init__(self):
        super().__init__()
        self.root_entity = Qt3DCore.QEntity()
        self.entity_1 = Qt3DCore.QEntity(self.root_entity)
        self.entity_2 = Qt3DCore.QEntity(self.root_entity)
        self.setRootEntity(self.root_entity)

        # some other code

        self.surselector = Qt3DRender.QRenderSurfaceSelector()
        self.surselector.setSurface(self)

        # Viewport 1
        self.viewport_1 = Qt3DRender.QViewport(self.surselector)
        self.layerfilter_1 = Qt3DRender.QLayerFilter(self.viewport_1)
        self.layer_1 = Qt3DRender.QLayer(self.entity_1)
        self.entity_1.addComponent(self.layer_1)
        self.layer_1.setRecursive(True)
        self.layerfilter_1.addLayer(self.layer_1)
        self.cameraSelector_1 = Qt3DRender.QCameraSelector(self.layerfilter_1)
        self.clearBuffers_1 = Qt3DRender.QClearBuffers(self.cameraSelector_1)
        self.cameraSelector_1.setCamera(self.camera())
        self.clearBuffers_1.setBuffers(Qt3DRender.QClearBuffers.AllBuffers)

        # Viewport 2
        self.viewport_2 = Qt3DRender.QViewport(self.surselector)
        self.layerfilter_2 = Qt3DRender.QLayerFilter(self.viewport_2)
        self.layer_2 = Qt3DRender.QLayer(self.entity_2)
        self.entity_2.addComponent(self.layer_2)
        self.layer_2.setRecursive(True)
        self.layerfilter_2.addLayer(self.layer_2)
        self.cameraSelector_2 = Qt3DRender.QCameraSelector(self.layerfilter_2)
        self.clearBuffers_2 = Qt3DRender.QClearBuffers(self.cameraSelector_2)
        self.cameraSelector_2.setCamera(self.camera())

        # The line below causes that no entity appears
        self.clearBuffers_2.setBuffers(Qt3DRender.QClearBuffers.AllBuffers)

        # The code below is what make viewport 2 / layer 2 / layerfilter 2 different from view port 1 / etc.
        self.rendstate_2 = Qt3DRender.QRenderStateSet(self.clearBuffers_2)
        self.rendstate_2.setParent(self.clearBuffers_2)
        depth = Qt3DRender.QDepthTest()
        depth.setDepthFunction(Qt3DRender.QDepthTest.LessOrEqual)
        self.rendstate_2.addRenderState(depth)

        self.setActiveFrameGraph(self.surselector)

Solution

  • If I understand correctly you want both viewports be drawn over each other (i.e. not in left and right half), while the first one draws all normal entities and the second one the ones that are always visible.

    First of all, I think you don't need the viewports. Qt defaults this to the rectangle (0, 0, 1, 1) if none is present, but I'm not sure about this.

    The actual issue is this line

    self.clearBuffers_2.setBuffers(Qt3DRender.QClearBuffers.AllBuffers)
    

    because here you delete the color buffer as well, which deletes everything the first viewport rendered. Try setting it to Qt3DRender.QClearBuffers.DepthBuffer. This only clears your depth buffer.The entites of the second viewport will be drawn ontop of the rendering of the first viewport.