Qt例子学习笔记 - Examples/Qt-6.2.0/qt3d/multiviewport

71 篇文章 4 订阅
这个示例展示了如何使用Qt3D库在QML中创建一个多视口渲染的3D场景。通过四个虚拟摄像机从不同角度呈现场景,模拟3DCAD、建模工具或游戏中的视图配置。代码包括了多个透视投影相机设置,以及通过Qt3DQuickWindow和QML组件管理输入和渲染。
摘要由CSDN通过智能技术生成

main.cpp

#include <Qt3DQuickExtras/qt3dquickwindow.h>
#include <QGuiApplication>
//演示从多个视口渲染场景图形的 QML 示例。
//多视口从四个虚拟摄像机的角度将场景图形渲染到窗口的四个象限中。
//这是 3D CAD 或建模工具的常见配置,或者可以进行调整以帮助渲染赛车游戏
//或闭路电视摄像机显示器中的后视镜。

int main(int ac, char **av)
{
    QGuiApplication app(ac, av);
    Qt3DExtras::Quick::Qt3DQuickWindow view;
    view.setSource(QUrl("qrc:/main.qml"));
    view.show();

    return app.exec();
}

main.qml

import QtQuick 2.0
import Qt3D.Core 2.0
import Qt3D.Render 2.0
import Qt3D.Input 2.0
import Qt3D.Extras 2.0

Entity {
    id: rootNode
    components: [quadViewportFrameGraph, inputSettings]

    QuadViewportFrameGraph {
        id: quadViewportFrameGraph
        topLeftCamera: cameraSet.cameras[0]
        topRightCamera: cameraSet.cameras[1]
        bottomLeftCamera: cameraSet.cameras[2]
        bottomRightCamera: cameraSet.cameras[3]
    }

    // Event Source will be set by the Qt3DQuickWindow
    InputSettings { id: inputSettings }

    Entity {
        id: cameraSet
        property var cameras: [camera1, camera2, camera3, camera4]

        CameraLens {
            id: cameraLens
            projectionType: CameraLens.PerspectiveProjection
            fieldOfView: 45
            aspectRatio: 16/9
            nearPlane: 0.01
            farPlane: 1000.0
        }
        CameraLens {
            id: cameraLens2
            projectionType: CameraLens.PerspectiveProjection
            fieldOfView: 15
            aspectRatio: 16/9
            nearPlane: 0.01
            farPlane: 1000.0
        }
        CameraLens {
            id: cameraLens3
            projectionType: CameraLens.PerspectiveProjection
            fieldOfView: 5
            aspectRatio: 16/9
            nearPlane: 0.01
            farPlane: 1000.0
        }

        SimpleCamera {
            id: camera1
            lens: cameraLens2
            position: Qt.vector3d(10.0, 1.0, 10.0)
            viewCenter: Qt.vector3d(0.0, 1.0, 0.0)
        }

        SimpleCamera {
            id: camera2
            lens: cameraLens
            position: Qt.vector3d(0.0, 0.0, 5.0)
            viewCenter: Qt.vector3d(0.0, 0.0, 0.0)
        }

        SimpleCamera {
            id: camera3
            lens: cameraLens2
            position: Qt.vector3d(30.0, 30.0, 20.0)
            viewCenter: Qt.vector3d(0.0, 0.0, -8.0)
        }

        SimpleCamera {
            id: camera4
            lens: cameraLens3
            position: Qt.vector3d(100.0, 0.0, -6.0)
            viewCenter: Qt.vector3d(0.0, 0.0, -6.0)
        }
    }

    Entity {
        id: sceneRoot
        property real rotationAngle: 0

        SequentialAnimation {
            running: true
            loops: Animation.Infinite
            NumberAnimation { target: sceneRoot; property: "rotationAngle"; to: 360; duration: 4000; }
        }

        Entity {
            components: [
                Transform {
                    rotation: fromAxisAndAngle(Qt.vector3d(0, 0, 1), -sceneRoot.rotationAngle)
                },
                SceneLoader {
                    source: "qrc:/Gear_scene.dae"
                }
            ]
        }
    } // sceneRoot
} // rootNode

QuadViewportFrameGraph.qml

import Qt3D.Core 2.0
import Qt3D.Render 2.0

RenderSettings {
    id: quadViewportFrameGraph

    property alias topLeftCamera: cameraSelectorTopLeftViewport.camera;
    property alias topRightCamera: cameraSelectorTopRightViewport.camera;
    property alias bottomLeftCamera: cameraSelectorBottomLeftViewport.camera;
    property alias bottomRightCamera: cameraSelectorBottomRightViewport.camera;
    property alias window: surfaceSelector.surface

    //保存当前活动的 FrameGraph。
    //提供一种指定渲染表面的方法。
    //RenderSurfaceSelector 可用于选择表面,Qt3D 在此渲染内容。 表面可以是窗口表面或屏幕外表面。
    //externalRenderTargetSize 用于在使用离屏表面时指定渲染目标的实际大小。

    //使用 Framegraph Rules 中定义的规则,我们从 FrameGraph 构造五个 RenderView 对象:
    //顺序很重要。
    //如果 ClearBuffers 节点是最后一个而不是第一个,这将导致黑屏,原因
    //很简单,所有内容都将在经过如此仔细的渲染后立即被清除。
    //出于类似的原因,它不能用作 FrameGraph 的根
    //因为这会导致调用为我们的每个视口清除整个屏幕。
    //尽管 FrameGraph 的声明顺序很重要,但 Qt 3D 能够并行处理每个 RenderView
    //因为每个 RenderView 都独立于其他渲染视图,以便在 RenderView   
    //的状态有效时生成一组要提交的 RenderCommand。
    //Qt 3D 使用基于任务的并行方法,该方法自然会随着可用内核的数量而扩展。
    //RenderViews 的 RenderCommands 可以跨多个内核并行生成
    //只要我们注意在专用的 OpenGL 提交线程上以正确的顺序提交 RenderViews,生成的场景就会被正确渲染。
    activeFrameGraph: RenderSurfaceSelector {
        id: surfaceSelector
        //Viewport场景的视口指定 Qt3D 渲染到渲染表面的哪个部分。
        //视口外的区域保持不变。 它还控制该视口中渲染的全局参数,如 gamma。
        //指定视口的伽马系数。 默认值为 2.2,它应该在大多数屏幕上给出正确的结果。
        //创建多个渲染视图
        Viewport {
            id: mainViewport
            //指定视口的规范化矩形,即视口矩形是相对于渲染表面大小指定的。 
            //整个表面大小的视口指定为 [0.0, 0.0, 1.0, 1.0],这是默认值。
            normalizedRect: Qt.rect(0, 0, 1, 1)
            //Qt3DRender::QClearBuffers FrameGraph 节点可以清除具有特定值的特定渲染目标缓冲区。
            ClearBuffers {
                buffers: ClearBuffers.ColorDepthBuffer
                clearColor: Qt.rgba(0.6, 0.6, 0.6, 1.0)
            }
            //CameraSelector 可用于选择相机,在绘制实体时由 FrameGraph 使用。
            Viewport {
                id: topLeftViewport
                normalizedRect: Qt.rect(0, 0, 0.5, 0.5)
                CameraSelector { id: cameraSelectorTopLeftViewport }
            }

            Viewport {
                id: topRightViewport
                normalizedRect: Qt.rect(0.5, 0, 0.5, 0.5)
                CameraSelector { id: cameraSelectorTopRightViewport }
            }

            Viewport {
                id: bottomLeftViewport
                normalizedRect: Qt.rect(0, 0.5, 0.5, 0.5)
                CameraSelector { id: cameraSelectorBottomLeftViewport }
            }

            Viewport {
                id: bottomRightViewport
                normalizedRect: Qt.rect(0.5, 0.5, 0.5, 0.5)
                CameraSelector { id: cameraSelectorBottomRightViewport }
            }
        }
    }
}

SimpleCamera.qml


import Qt3D.Core 2.0
import Qt3D.Render 2.0

Entity {
    id: root

    property vector3d position: Qt.vector3d(0.0, 0.0, 10.0)
    property vector3d viewCenter: Qt.vector3d(0.0, 0.0, 0.0)
    property vector3d upVector: Qt.vector3d(0.0, 1.0, 0.0)
    property CameraLens lens: null

    components: [lens, transform]

    Transform {
        id: transform
        matrix: {
            var m = Qt.matrix4x4();
            m.translate(root.position)
            var zAxis = root.position.minus(root.viewCenter).normalized()
            var xAxis = root.upVector.crossProduct(zAxis).normalized();
            var yAxis = zAxis.crossProduct(xAxis);
            var r = Qt.matrix4x4(xAxis.x, yAxis.x, zAxis.x, 0,
                                 xAxis.y, yAxis.y, zAxis.y, 0,
                                 xAxis.z, yAxis.z, zAxis.z, 0,
                                 0, 0, 0, 1)
            return m.times(r);
        }
    }
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值