Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QT3D RenderPassFilter does not seem to filter away other renderpasses



  • I have an issue with RenderPassFilter in QML.

    I have a material define like so:

    
    Material {
        id: materialId
    
        ...   
    
        ShaderProgram {
            id: programForwardId
            objectName: "programForward"
            vertexShaderCode: loadSource(Qt.resolvedUrl("glsl/volume_texture.vert"))
            fragmentShaderCode: loadSource(Qt.resolvedUrl("glsl/volume_forward.frag"))
        }
    
        ShaderProgram {
            id: programHeavyCacheId
            objectName: "programHeavyCache"
            vertexShaderCode: loadSource(Qt.resolvedUrl("glsl/volume_texture.vert"))
            fragmentShaderCode: loadSource(Qt.resolvedUrl("glsl/volume_heavy_cache.frag"))
        }
    
        ShaderProgram {
            id: programHeavyMaximumId
            objectName: "programHeavyMaximum"
            vertexShaderCode: loadSource(Qt.resolvedUrl("glsl/volume_texture_position.vert"))
            fragmentShaderCode: loadSource(Qt.resolvedUrl("glsl/volume_heavy_max.frag"))
        }
    
        parameters: [...]
    
        effect: Effect {
    
            techniques: [
                Technique {
                    graphicsApiFilter {
                        api: GraphicsApiFilter.OpenGL
                        profile: GraphicsApiFilter.CoreProfile
                        majorVersion: 3
                        minorVersion: 1
                    }
                    renderPasses: [
                        RenderPass {
                            filterKeys: [ FilterKey { name: "heavy"; value: "cache" } ]
                            shaderProgram: programHeavyCacheId
                        },
                        RenderPass {
                            filterKeys: [ FilterKey { name: "heavy"; value: "final" } ]
                            shaderProgram: programHeavyMaximumId
                        },
                        RenderPass {
                            filterKeys: [ FilterKey { name: "forward"; value: "default" } ]
                            shaderProgram: programForwardId
                        }
                    ]
                }
            ]
        }
    }
    

    I want to render this material differently depending on my DisplayMode (set in a C++ class).

    My Scene3D picks between two framegraphs depending on the DisplayMode enum.

    Scene3D {
            id: scene3DId
            objectName: "scene3D"
            focus: true
            anchors.fill: parent
            aspects: ["render", "logic"]
            cameraAspectRatioMode: Scene3D.AutomaticAspectRatio
    
            Entity {
                id: rootEntityId
    
                Camera {
                    id: mainCameraId
                    projectionType: CameraLens.OrthographicProjection
                    projectionMatrix: orientationViewModel.projection
    
                    position: orientationViewModel.cameraPosition
                    upVector: orientationViewModel.cameraUpVector
                    viewCenter: orientationViewModel.viewCenter
                }
                
                components: [
                    RenderSettings {
                        renderPolicy: RenderSettings.OnDemand
                        FrameGraphForward {
                            id: frameGraphForwardId
                            camera: mainCameraId
                            clearColor: "black"
                        }
                        FrameGraphHeavy {
                            id: frameGraphHeavyId
                            camera: mainCameraId
                            clearColor: "black"
                        }
                        activeFrameGraph: { 
                            if (displayMode == DisplayModes.Texture) {
                                return frameGraphForwardId
                            }
                            if (displayMode == DisplayModes.Maximum) {
                                return frameGraphHeavyId
                            }
                        }
                    }
                ]
            }
        }
    
    

    I use the following RenderPassFilter in my FrameGraphHeavy.qml to select the exact RenderPass I want to utilize:

    RenderPassFilter {
        matchAny: [ FilterKey { name: "heavy"; value: "final" } ]
    }
    

    In FrameGraphForward.qml I do the same but with the other filter keys:

    RenderPassFilter {
        matchAny: [ FilterKey { name: "forward"; value: "default" } ]
    }
    

    My issue is that the heavy renderpass should only be rendered when the display mode dictates it. But if I use FrameGraphHeavy just once, the heavy renderpass is executed every frame after, even with another framegraph selected.
    I would assume the selection of RenderPassFilter would filter out other render passes but it seems not. The documentation isn't very detailed on this so I'm having difficulty using it.

    The only solution I have found is to make a single RenderPass in which the ShaderProgram is picked depending on the DisplayMode, removing the need for the filters.


  • Qt Champions 2017

    I think you should create the frame graph nodes outside of the render settings, at least it's worth a try.
    E.g.:

    ... 
    
    FrameGraphForward {
       id: frameGraphForwardId
       camera: mainCameraId
       clearColor: "black"
    }
    
    FrameGraphHeavy {
       id: frameGraphHeavyId
       camera: mainCameraId
       clearColor: "black"
    }
    
    components: [
       RenderSettings {
          renderPolicy: RenderSettings.OnDemand
    
          activeFrameGraph: { 
             if (displayMode == DisplayModes.Texture) {
                return frameGraphForwardId
             }
             if (displayMode == DisplayModes.Maximum) {
                return frameGraphHeavyId
             }
          }
       }
    ]

Log in to reply