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);
}
}
}