Qt3D Problem with transparent object.



  • Hello. I'm adding a Sphere with a texture and a transparent Teapot to the scene. Everything is displayed as it should(pic 1). But when I swap the Sphere with the Teapot, the Sphere is always displayed in the foreground(pic 2) .

    pic 1. Sphere with texture and transparent Teapot
    0_1505835196973_5.9-back.png

    Scene.qml

    import QtQuick 2.0
    
    import Qt3D.Core 2.0
    import Qt3D.Render 2.0
    import Qt3D.Extras 2.0
    import Qt3D.Input 2.0
    
    Entity  {
        id: scene
        objectName: "scene"
        property real cameraDistance: 100
    
        function spherePos(pos, angle) {
            sphere.position = pos;
            sphere.angle = angle;
        }
    
        Camera {
            id: camera
            projectionType: CameraLens.PerspectiveProjection
            fieldOfView: 40
            aspectRatio:  _window.width / _window.height
            nearPlane : 0.1
            farPlane : 1000.0
            position: Qt.vector3d( 0.0, 100.0, 30 )
            upVector: Qt.vector3d( 0.0, 0.0, 1.0 )
            viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 )
        }
    
        components: [
            RenderSettings {
                activeFrameGraph: ForwardRenderer{
                    camera: camera
                    clearColor: "white"
                }
            }
        ]
    
        Sphere {
            id: sphere
        }
    
        Teapot {
    
        }
    }
    

    Sphere.qml

    import QtQuick 2.0
    import Qt3D.Core 2.0
    import Qt3D.Render 2.0
    import Qt3D.Extras 2.0
    
    Entity {
        property alias position: transform.translation
        property real angle: 0
    
        onPositionChanged: {
            var x = cameraDistance * Math.cos(-(angle-180)*Math.PI/180)
            var y = cameraDistance * Math.sin(-(angle-180)*Math.PI/180)
            camera.upVector = Qt.vector3d( 0.0, 0.0, 1.0 )
            camera.viewCenter = position
            camera.position = Qt.vector3d(x, y, 30).plus(position)
        }
        onAngleChanged: {
            var x = cameraDistance * Math.cos(-(angle-180)*Math.PI/180)
            var y = cameraDistance * Math.sin(-(angle-180)*Math.PI/180)
            camera.upVector = Qt.vector3d( 0.0, 0.0, 1.0 )
            camera.viewCenter = position
            camera.position = Qt.vector3d(x, y, 30).plus(position)
        }
    
        Behavior on angle{
            RotationAnimation { duration: 5000; direction: RotationAnimation.Shortest }
        }
    
        components: [ sphere, diffusematerial, transform ]
    
        DiffuseMapMaterial {
            id: diffusematerial
            ambient: Qt.rgba( 1, 1, 1, 1 )
            diffuse: TextureLoader{ source: "qrc:/assets/textures/sphere.jpg" }
            shininess: 0
            specular: Qt.rgba( 1, 1, 1, 1 )
            textureScale: 4
        }
    
        Transform {
            id: transform
            rotation: fromEulerAngles( angle+180, 90, 90 )
            scale: 10
    
            Behavior on translation {
                Vector3dAnimation { duration: 5000 }
            }
        }
    
        SphereMesh {
            id: sphere
        }
    
    }
    

    Teapot.qml

    import QtQuick 2.0
    import Qt3D.Core 2.0
    import Qt3D.Render 2.0
    import Qt3D.Extras 2.0
    
    Entity {
        property alias position: transform.translation
        property real angle: 0
    
        Behavior on angle{
            RotationAnimation { duration: 5000; direction: RotationAnimation.Shortest }
        }
    
        components: [ mesh, alpha, transform ]
    
        PhongMaterial {
            id: material
            ambient: Qt.rgba( 1, 0, 0, 1 )
            diffuse: Qt.rgba( 1, 0, 0, 1 )
            shininess: 50
        }
    
        PhongAlphaMaterial {
            id: alpha
            alpha: 0.9
            ambient: Qt.rgba( 1, 0, 0, 1 )
            diffuse: Qt.rgba( 1, 0, 0, 1 )
            shininess: 50
        }
    
        Transform {
            id: transform
            rotation: fromEulerAngles( angle+180, 90, 90 )
            scale: 10
    
            Behavior on translation {
                Vector3dAnimation { duration: 5000 }
            }
        }
    
        Mesh {
            id: mesh
            source: "qrc:/assets/mesh/teapot.obj"
        }
    
    }
    

    pic 2. Swapped the Sphere and the Teapot
    0_1505835615385_5.9-forward.png

    Scene.qml

    import QtQuick 2.0
    
    import Qt3D.Core 2.0
    import Qt3D.Render 2.0
    import Qt3D.Extras 2.0
    import Qt3D.Input 2.0
    
    Entity  {
        id: scene
        objectName: "scene"
        property real cameraDistance: 100
    
        function tractorPos(pos, angle) {
            sphere.position = pos;
            sphere.angle = angle;
        }
    
        Camera {
            id: camera
            projectionType: CameraLens.PerspectiveProjection
            fieldOfView: 40
            aspectRatio:  _window.width / _window.height
            nearPlane : 0.1
            farPlane : 1000.0
            position: Qt.vector3d( 0.0, 100.0, 30 )
            upVector: Qt.vector3d( 0.0, 0.0, 1.0 )
            viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 )
        }
    
        components: [
            RenderSettings {
                activeFrameGraph: ForwardRenderer{
                    camera: camera
                    clearColor: "white"
                }
            }
        ]
    
        Teapot {
    
        }
    
        Sphere {
            id: sphere
        }
    
    }
    
    


  • Why does the order of writing objects in the code affect their display?


  • Qt Champions 2017

    Hi
    Maybe it gets the zorder that way?



  • @mrjj do you mean z buffer?

    By the way, if use a material without transparency (for example: PhongMaterial). Order of objects does not affect the display

    pic 1. Normal order of objects
    0_1505897675710_5.9-back-m.png

    pic 2. Order of objects is changed
    0_1505897738006_5.9-forward-m.png

    I think I need to use custom FrameGraph. But, I do not understand how to write it to ensure, that transparency worked normally.



  • And the most interesting. Everything I described above appears in versions 5.6 and 5.9. And in versions 5.7 and 5.8 the behavior is different.

    pic 1. Normal order of objects (5.7 and 5.8)
    0_1505898303092_5.7-back.png

    pic 2. Order of objects is changed (5.7 and 5.8)
    0_1505898322858_5.7-forward.png



  • I have similar problems whenever I try to rend any 3D object that uses a built-in material with alpha. It's like transparent objects stop writing depth values in z-buffer. And alpha blend stage looks weird too: it looks like pixels with alpha are not blended against the 3D viewport clear color but underlying window color or any other QML visual item that's beneath Scene3D object.



  • I think the intention is that you draw opaque objects, then draw transparent ones using the render graph system to set up multiple passes. This is a pain in the ass, and not at all clear from the documentation. (A lot of parts of Qt3D are still maturing.)

    Traditionally, it's a common idiom in game rendering to draw all opaque objects with Z-writing enabled, then sort the transparent objects back to front and draw them with Z buffer writes disabled. The result is that you will blend a transparent object with whatever is behind it, and reject the fragment if it is behind something opaque. A reasonable person might expect Qt3D to do this for you, given the relatively high level expectations when working in something like QML, but c'est la vie. Qt3D tries to give you a bunch of flexibility to control the lower level fraw process of frame graph evaluation, rather than just being a trivial drawscene() API with a bunch of magic that isn't flexible. In moments of frustration, I have described the general philosophy as "making hard things somewhat easier by making some of the easy things much, much harder."



  • Also, I am like 90% sure that using https://doc.qt.io/qt-5.10/qt3drender-qsortpolicy.html in your frame graph and setting Qt3DRender::QSortPolicy::BackToFront will be useful in getting the transparency render pass working.

    But right now the documentation is not quite fleshed out in this area. For example, the value of Qt3DRender::QSortPolicy::FrontToBack is just listed as a "?" in the table. So even the documentation is confused and has no real idea what exactly it is or how you are supposed to use it. Life is fun on the bleeding edge. So you are gonna need to do a bit of experimentation with setting up the frame graph in c++.



  • @wrosecrans Yeah, that makes sense. Thanks. I guess that built-in materials like Phong and PhongAlpha probably set their own render states when rendering. Just like you can set render states when building your own custom Material by filling renderSates list property in RenderPass.

    And setting sorting in the frame graph takes care of the render sequence.



  • Glad to hear that sorting worked for you.

    Obviously, if you are sorting geometry that is completely opaque, sorting it is a waste of time if you could just render it with a Z-buffer. So separating into several passes with filters, and tweaking what geometry gets filtered with what coarseness, how, is necessary if you are trying to push the limits of performance, etc. I have managed to grasp quite a bit of the theory, but actually taking advantage of all the bells and whistles in Qt3D in an optimal way still seems rather complex.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.