On Qt3D module

Keywords: Qt Attribute github less

0. Preface

Qt3D is initiated by Nokia, and then improved by Digia and KDAB (the new version seems to be basically made by KDAB). It is a 3D image display and processing module based on OpenGL. Unfortunately, the data of Qt3D is relatively small, and with the version change, many online old Demo can't run.

In addition to the examples in QtCreator, here we recommend several github projects of Qt3D, which can refer to learning:

https://github.com/MidoriYakumo/learnopengl-qt3d

https://github.com/jaredtao/Qt3D-learn

https://github.com/KDAB/qt3d-examples

In addition, you can see the overview of Qt3D: https://doc.qt.io/qt-5/qt3d-overview.html

Because I just played, so a lot of things do not understand, slowly learn. Text code link: https://github.com/gongjianbo/HelloQt3D

1. Use Qt3D in QtQuick

Before use, add the Qt3D module to the pro file

QT += qml quick
QT += 3dcore 3drender 3dinput 3dlogic 3dextras 3dquick 3danimation

To create a 3D scene embedded in QtQuick, you need a Scene3D object. In scene, we define our 3D objects through Entity. The organizational structure of multiple entities is similar to the object tree. Scene3D needs a root Entity to define some basic behaviors. A simple empty window example is as follows:

import QtQuick 2.15
import QtQuick.Scene3D 2.15
import Qt3D.Core 2.15
import Qt3D.Render 2.15

Item{
    //Create 3d scene embedded in QtQuick
    Scene3D {
        id: scene3d
        anchors.fill: parent
        anchors.margins: 20
        //Entity entity is a Node subclass, which can aggregate several Component3D instances to specify its behavior
        //Root entity
        Entity {
            //The RenderSettings component must be a component of the scene root entity.
            //It specifies the rendering policy and selection settings, and hosts the active FrameGraph
            RenderSettings {
                //Equivalent to glClearColor
                activeFrameGraph: ClearBuffers {
                    buffers: ClearBuffers.ColorBuffer
                    clearColor: Qt.rgba(0.0,0.5,0.0,1.0)
                    RenderSurfaceSelector {
                        // Default render output: window surface
                    }
                }
            }
        }
    }
    Text {
        anchors.centerIn: parent
        text: "First Window"
    }
}

Qt3D provides us with some basic Mesh and Material components. For simple applications, we can directly splice these basic shapes (some basic information in my book is written on the code Notes):

import QtQuick.Scene3D 2.15
import Qt3D.Core 2.15
import Qt3D.Render 2.15
import Qt3D.Input 2.15
import Qt3D.Extras 2.15
import Qt3D.Logic 2.15

//Create 3d scene embedded in QtQuick
Scene3D {
    //Automatic Aspect Ratio 
    cameraAspectRatioMode: Scene3D.AutomaticAspectRatio
    aspects: ["logic", "input"]

    //Entity entity is a Node subclass, which can aggregate several Component3D instances to specify its behavior
    //Root entity
    Entity {
        id: root
        //camera
        Camera {
            id: camera
            //perspective projection 
            projectionType: CameraLens.PerspectiveProjection
            fieldOfView: 45
            nearPlane: 0.1
            farPlane: 1000.0
            position: Qt.vector3d(0.0, 0.0, 10.0)
            upVector: Qt.vector3d(0.0, 1.0, 0.0)
            viewCenter: Qt.vector3d(0.0, 0.0, 0.0)
        }
        //For camera control
        OrbitCameraController {
            // Press the left mouse button to move the camera position when dragging along the x or y axis
            // Press the right mouse button to control the camera deflection when dragging along the x or y axis
            camera: camera
        }
        //The RenderSettings component must be a component of the scene root entity.
        //It specifies the rendering policy and selection settings, and hosts the active FrameGraph
        RenderSettings {
            //Forward rendering. A rendering method that is calculated on a light by light basis.
            activeFrameGraph: ForwardRenderer {
                camera: camera
                clearColor: Qt.rgba(0.0, 0.3, 0.0, 1.0)
            }
        }
        //The InputSettings component must be a component of the scene root entity.
        //It stores a pointer to an object that acts as the source of input events to be processed by various input classes.
        InputSettings{
        }

        //Object Node
        Entity {
            PhongMaterial {
                id: material
                //Ambient light
                ambient: "gray"
                //Diffuse light
                diffuse: "orange"
                //Specular Highlights 
                specular: "yellow"
                //Highlight radius
                shininess:32

            }
            /*CuboidMesh {
                id: cube
            }
            Transform {
                id: trans
                matrix: {
                    let m = Qt.matrix4x4();
                    //Rotate the lower angle, the default front facing can't see the effect
                    m.rotate(45, Qt.vector3d(1, 1, 0))
                    return m;
                }
            }
            components: [material, cube, trans]*/
            Entity{
                id: sub1
                CuboidMesh {
                    id: cube1
                    xExtent: 2
                    zExtent: 2
                }
                Transform {
                    id: trans1
                    matrix: {
                        let m = Qt.matrix4x4();
                        //The angle under the rectangle rotation is invisible by default
                        m.rotate(45, Qt.vector3d(1, 1, 0))
                        return m;
                    }
                }
                components: [cube1, trans1,material]
            }
            Entity{
                id:sub2
                SphereMesh {
                    id: ball2
                    //Radius defaults to 1
                    radius: 1
                    //Number of grid rings
                    rings: 2
                    //Number of grid slices
                    slices: 10
                }
                Transform {
                    id: trans2
                    matrix: {
                        let m = Qt.matrix4x4();
                        //Stagger with another mesh
                        m.translate(Qt.vector3d(3, 0, 0))
                        return m;
                    }
                }
                components: [ball2, trans2,material]
            }
        }
    }
}

2. Draw a triangle

3D learning without triangles is incomplete. To draw triangles, you need to add GeometryRenderer geometric rendering objects and Material objects to entities. Vertex information is in Geometry, while shaders are in Material:

import QtQuick 2.15
import QtQuick.Scene3D 2.15
import Qt3D.Core 2.15
import Qt3D.Render 2.15
import Qt3D.Extras 2.15

//The documents of Qt3D QML are not very detailed. For some documents, please refer to the CPP version
//Create 3d scene embedded in QtQuick
Scene3D{
    id:scene
    anchors.fill: parent

    //Root Entity
    Entity {
        //The RenderSettings component must be a component of the scene root entity.
        //It specifies the rendering policy and selection settings, and hosts the active FrameGraph
        RenderSettings {
            id: renderSettings
            //Save the currently active FrameGraph
            //Qt 3D rendering allows the rendering algorithm to be completely data driven.
            //The data structure of this control is called framework
            activeFrameGraph: ClearBuffers {
                //Why can't ColorBuffer render triangles?
                buffers: ClearBuffers.ColorDepthBuffer
                clearColor: Qt.rgba(0.0,0.5,0.0,1.0)

                //Can be used to select the surface of the Qt3D rendered content.
                //The surface can be a window surface or an off screen surface.
                RenderSurfaceSelector {
                    //In contrast to each material state that you can set on RenderPass,
                    //The state set on the RenderStateSet is global
                    RenderStateSet {
                        renderStates: DepthTest {
                            //Pass the depth test if the fragment depth is less than the z buffer value
                            depthFunction: DepthTest.Less
                        }
                    }
                }
            }
        }

        //Triangle Entity
        Entity{
            //Geometry renderer
            GeometryRenderer {
                id: geometry
                //Geometry
                //The Geometry type is used to group the list of Attribute objects together,
                //To form the geometry that Qt3D can render with GeometryRenderer.
                geometry: Geometry {
                    //Attribute attribute, corresponding to attribute in Shader
                    Attribute {
                        id: position
                        attributeType: Attribute.VertexAttribute
                        vertexBaseType: Attribute.Float
                        vertexSize: 3
                        count: 3
                        name: "position"
                        buffer: Buffer {
                            type: Buffer.VertexBuffer
                            usage: Buffer.StaticDraw
                            accessType: Buffer.Write
                            data: new Float32Array(
                                      [
                                          -0.5, -0.5, 0.0,
                                          0.5, -0.5, 0.0,
                                          0.0,  0.5, 0.0,
                                      ])

                        }
                    }
                }
            }//end GeometryRenderer
            //Material definition how to render Entity
            Material {
                id: material
                effect: Effect {
                    //A rendering method, Technique, specifies a set of RenderPass objects, FilterKey objects, Parameter objects and graphicfiifilter,
                    //Together, they define rendering techniques that a given graphics API can render.
                    techniques: Technique {
                        //Specify the graphics API filter to use
                        //profile defaults to NoProfile. When in Core mode, set to CoreProfile. Streamline.
                        graphicsApiFilter.profile: GraphicsInfo.profile === GraphicsInfo.CoreProfile ?
                                                       GraphicsApiFilter.CoreProfile : GraphicsApiFilter.NoProfile
                        //Specifies the rendering channel used by tehcnique
                        renderPasses: RenderPass {
                            //Shaders
                            shaderProgram: ShaderProgram {
                                //GLSL can use strings or files
                                vertexShaderCode: vertStr
                                //vertexShaderCode: loadSource('qrc:/triangle1.vert')
                                fragmentShaderCode: fragStr
                                //fragmentShaderCode: loadSource('qrc:/triangle1.frag')
                            }
                        }
                    }
                }

            }//end Material
            components: [geometry, material]
        }


    }

    property string vertStr: '
                    #version 330 core
                    layout (location = 0) in vec3 position;
                    void main()
                    {
                        gl_Position = vec4(position, 1.0f);
                    }
                    '
    property string fragStr: '
                    #version 330 core
                    out vec4 color;
                    void main()
                    {
                        color = vec4(0.0f, 1.0f, 0.0f, 1.0f);
                    }
                    '
}

 

Posted by Mattyspatty on Sat, 13 Jun 2020 18:10:30 -0700