Unsolved 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.
-
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 } } } ]