Qt Canvas 3D是Qt 基于WebGL的3D内容运行环境。因为QtQuick自己就是经过类js引擎执行,并且渲染层面基于opengl技术。故结合webgL和Qtquick的优点,利用js高效的特色,给Qtquick增长了3d功能。并且Qt Canvas 3D还能够利用成熟的web 3d框架,如three.js、gl-matrix.js等,大大方便了利用QtQuick编写3d内容。Qt Canvas 3D是由官方支持,比Qt3D模块较成熟。至于二者性能上的差别尚待对比。html
最新版QtCreater支持在建立项目时指定Qt Canvas 3D应用,下面咱们经过该方式建立一个默认应用,学习其结构组成。经过QtCreater建立一个使用three.js的应用。c++
main.cpp
git
#include <QGuiApplication> #include <QQmlApplicationEngine> int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); return app.exec(); }
从上面能够看出,Canvas 3D应用和普通qml应用对于c++后端要求一致,没有额外内容,由下面qml代码可知,Canvas3D即一个普通的QtQuick Item。github
main.qmlweb
import QtQuick 2.4 import QtCanvas3D 1.0 import QtQuick.Window 2.2 import "glcode.js" as GLCode Window { title: qsTr("untitled1") width: 1280 height: 768 visible: true Canvas3D { id: canvas3d anchors.fill: parent focus: true onInitializeGL: { GLCode.initializeGL(canvas3d); } onPaintGL: { GLCode.paintGL(canvas3d); } onResizeGL: { GLCode.resizeGL(canvas3d); } } }
上述代码经过Canvas3D元素定义了3d场景,当场景初始化后会发送 initializeGL 信号,从而执on initializeGL 槽。实际的控制逻辑写在了glcode.js中,经过槽函数将要操做的场景对象canvas3d传给js代码。canvas
glcode.js首先导入three.js,而后实现了main.qml中对应的3个槽对应的函数功能。其语法和普通的three.js应用区别不大,故一个基于html的three.js应用能够很方便的移植到QtQuick中。后端
The Canvas3D is a QML element that, when placed in your Qt Quick 2 scene, allows you to get a 3D rendering context and call 3D rendering API calls through that context object. Use of the rendering API requires knowledge of OpenGL-like rendering APIs.app
There are two functions that are called by the Canvas3D implementation:框架
initializeGL is emitted before the first frame is rendered, and usually during that you get the 3D context and initialize resources to be used later on during the rendering cycle.函数
paintGL is emitted for each frame to be rendered, and usually during that you submit 3D rendering calls to draw whatever 3D content you want to be displayed.
逻辑代码
Qt.include("three.js") var camera, scene, renderer; var cube; function initializeGL(canvas) { scene = new THREE.Scene(); //custom begain camera = new THREE.PerspectiveCamera(75, canvas.width / canvas.height, 0.1, 1000); camera.position.z = 5; var material = new THREE.MeshBasicMaterial({ color: 0x80c342, ambient: 0x000000, shading: THREE.SmoothShading }); var cubeGeometry = new THREE.BoxGeometry(1, 1, 1); cube = new THREE.Mesh(cubeGeometry, material); cube.rotation.set(0.785, 0.785, 0.0); scene.add(cube); //custom end renderer = new THREE.Canvas3DRenderer( { canvas: canvas, antialias: true, devicePixelRatio: canvas.devicePixelRatio }); renderer.setSize(canvas.width, canvas.height); } function resizeGL(canvas) { camera.aspect = canvas.width / canvas.height; camera.updateProjectionMatrix(); renderer.setPixelRatio(canvas.devicePixelRatio); renderer.setSize(canvas.width, canvas.height); } function paintGL(canvas) { renderer.render(scene, camera); }
从上述js代码能够看出,resizeGL和paintGL通常默认便可,不须要改动,须要咱们编写的是initializeGL中//custom begain 和//custom end 之间的内容。