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 之間的內容。