QT Mobile Application Development (eight): enabling cross-platform QML and OpenGL mixed rendering

Source: Internet
Author: User

QT Mobile Application Development (eight): enabling cross-platform QML and OpenGL mixed rendering

The previous article talked about the use of C + + as a bridge, and we implemented QML and Java interactions. Qt 5 Highly respected QML/JS development, let the light-weight, rapid development of QML/JS lead, so that the weight of C + + support, almost any technology can be achieved. The next article is about using the QML, with QT libraries and OpenGL, to achieve a rendering that uses shaders to define OpenGL, rendering the effect of mixed rendering.

original article, against undeclared references. Original Blog address:http://blog.csdn.net/gamesdev/article/details/38024327

The difficulty of this article is large, suitable for experienced QT development Peer learning communication.

Demo Program: here

Source code: Here

The demo program is as follows (Android):

First, let's look at the simple QML code. This example is simple, there is only one interface, no jump on any interface. We show a rectangle in front, which says "Hello World!" Text, followed by a rotated rectangle. According to the provisions, the first display of the content at the bottom of the display, so we put the cube in front, rectangle placed in the back.

Import QtQuick 2.2import qtquick.window 2.2import openglcube 1.0window{id:root Width:Qt.platform.os = = = "Android" ? screen.width:320 Height:Qt.platform.os = = = "Android"?        screen.height:480 visible:true Cube {id:cube anchors.fill:parent parallelanimation  {running:true Numberanimation {Target:cube property: "Rotateangle" from:0 to:360 duration:5000} Vector3 Danimation {Target:cube property: "Axis" From:Qt.vector3d (0, 1 , 0) To:Qt.vector3d (1, 0, 0) duration:5000} loops:Animation.Inf Inite}} Rectangle {anchors.centerIn:parent width:textField.width * 1.2 height:t Extfield.height * 1.5 RADIUS:TEXTFIELD.HEIGHT/3 color: "LightsteelblUE "Border.color:" White "border.width:2 Text {Id:textfield anchors.c Enterin:parent text: "Hello world!" "Font.pixelsize:root.width/20}}}

We found that the cube class was not a QT quick, but a QML module openglcube that we customized. According to the method in the sixth article, we implemented the QML class in C + + to enable QML to access C + + code. The following is the implementation of the main function:

#include <QApplication> #include <QQmlApplicationEngine> #include "Cube.h" int main (int argc, char** argv) { C1/>qapplication app (argc, argv);    Qmlregistertype<cube> ("Openglcube", 1, 0, "Cube");    Qqmlapplicationengine engine;    Engine.load (Qurl (qstringliteral ("qrc:///main.qml"));    return app.exec ();}

A QML class is registered with the QML environment through the QMLREGISTERTYPE function in the main function. The next step is the definition and implementation of the Cube class.

Cube.h

#ifndef cube_h#define cube_h#include <QVector3D> #include <QMatrix4x4> #include <qopenglfunctions># Include <QOpenGLBuffer> #include <QOpenGLShaderProgram> #include <QQuickItem> #include < Qquickwindow> #define Declrare_q_property (Atype, Aproperty) protected:atype m_ # # Aproperty;     Public:atype aproperty (void) {return m_ # # aproperty;}        void Set # # Aproperty (atype _ # # Aproperty) {m_ # # Aproperty = _ # # aproperty;        if (window ()! = q_nullptr) {window ()->update (); }}class cube:public qquickitem{q_object q_property (qreal rotateangle READ rotateangle WRITE SE Trotateangle NOTIFY rotateanglechanged) q_property (Qvector3d axis READ axis WRITE Setaxis NOTIFY Axisc    hanged) public:explicit Cube (void), signals:void rotateanglechanged (void);    void axischanged (void);p rotected slots:void Render (void); void Onwindowchanged (Qquickwindow* Pwindow);    void Release (void);p Rotected:bool RunOnce (void);    qmatrix4x4 M_modelviewmatrix;    qmatrix4x4 M_projectionmatrix;    Qopenglbuffer M_vertexbuffer, M_indexbuffer;    Qopenglbuffer M_colorbuffer;    Qopenglshaderprogram M_shaderprogram; Declrare_q_property (Qreal, Rotateangle) declrare_q_property (Qvector3d, Axis)}; #endif//Cube_h

In Cube.h, we let Cube inherit Qquickitem. Because Cube is also a display object for QT quick. By the way, the C + + Qquickitem corresponds to the QML item class, while the C + + Qobject is the Qtobject class corresponding to QML. In C + +, Qquickitem inherits from Qobject, and in Qml, item inherits Qtobject. In the definition of a class, I used Qopenglbuffer to maintain various drawing caches (buffers) and to easily load shader data using Qopenglshaderprogram. Finally, I used a handy macro to define member variables that are controlled by the Qml property system. When these variables change, let them notify the parent window (Qquickwindow) to update.

Cube.cpp

Cube.cpp#include "Cube.h" Cube::cube (void): M_vertexbuffer (Qopenglbuffer::vertexbuffer), M_indexbuffer (QOpenG Lbuffer::indexbuffer), M_colorbuffer (Qopenglbuffer::vertexbuffer), M_rotateangle (0.0f), M_axis (1.0f, 1.0f, 0.0f) {//Initialize connect (this, SIGNAL (windowchanged (qquickwindow*)), this, SLOT (onwindowchanged ( qquickwindow*)));}    void cube::onwindowchanged (qquickwindow* pwindow) {if (Pwindow = = q_nullptr) return;    Connect (Pwindow, SIGNAL (beforerendering ()), this, SLOT (Render ()), Qt::D irectconnection); Pwindow->setclearbeforerendering (false);}    void Cube::render (void) {static bool runOnce = RunOnce ();    Q_unused (runOnce);    Sport m_modelviewmatrix.settoidentity ();    M_modelviewmatrix.translate (0.0f, 0.0f, -60.0f);    M_modelviewmatrix.rotate (M_rotateangle, M_axis.x (), M_axis.y (), m_axis.z ()); Render Glviewport (0, 0, window ()->width (), WINdow ()->height ());    Glclearcolor (0.0f, 0.0f, 0.0f, 1.0f); Glclear (Gl_color_buffer_bit |    Gl_depth_buffer_bit);    Glenable (gl_depth_test);    Glenable (Gl_cull_face);    Glfrontface (GL_CW);    M_shaderprogram.bind ();    M_vertexbuffer.bind ();    int posloc = m_shaderprogram.attributelocation ("position");    M_shaderprogram.enableattributearray (Posloc);               M_shaderprogram.setattributebuffer (Posloc,//Position gl_float, Type 0,//Offset 3                    ,//meta size 0);    Mai M_colorbuffer.bind ();    int colorloc = m_shaderprogram.attributelocation ("color");    M_shaderprogram.enableattributearray (Colorloc);               M_shaderprogram.setattributebuffer (Colorloc,//Position gl_float,Type 0,//offset 4,                    Meta size 0);    Mai M_indexbuffer.bind ();    M_shaderprogram.setuniformvalue ("Modelviewmatrix", M_modelviewmatrix);    M_shaderprogram.setuniformvalue ("ProjectionMatrix", M_projectionmatrix);    Gldrawelements (Gl_triangles, Gl_unsigned_byte, q_nullptr);    M_shaderprogram.disableattributearray (Posloc);    M_shaderprogram.disableattributearray (Colorloc);    M_indexbuffer.release ();    M_vertexbuffer.release (); M_shaderprogram.release ();}                                             BOOL Cube::runonce (void) {//Initialize shader M_shaderprogram.addshaderfromsourcefile (Qopenglshader::vertex,    ":/shader/shader.vsh"); M_shaderprogram.addshaderfromsourcefile (Qopenglshader::fragment, ":/shader/sh    Ader.fsh "); M_shaderprogram.link ();   Initialize vertex cache const Glfloat length = 10.0f; Const Glfloat vertices[] = {length,-length, length, length,-length,-length,-length,-length, -length,-length,-length, length, length, length, length, length, length,-length,-length, L    Ength,-length,-length, length, length};    M_vertexbuffer.setusagepattern (Qopenglbuffer::staticdraw);    M_vertexbuffer.create ();    M_vertexbuffer.bind ();    M_vertexbuffer.allocate (vertices, sizeof (vertices)); Initialize color cache const Glfloat Colors[] = {1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0. 0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f,    1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f};    M_colorbuffer.setusagepattern (Qopenglbuffer::staticdraw);    M_colorbuffer.create ();    M_colorbuffer.bind (); M_colorbuffer.allocate (colors, sizeof (colors));   Initialize index cache glubyte indices[] = {0, 1, 2, 0, 2, 3,//below 7, 6, 4, 6, 5, 4,//above 7, 4, 3, 4, 0    , 3,//left 5, 6, 1, 6, 2, 1,//right 4, 5, 0, 5, 1, 0,//Front 3, 2, 6, 3, 6, 7,//back};    M_indexbuffer.setusagepattern (Qopenglbuffer::staticdraw);    M_indexbuffer.create ();    M_indexbuffer.bind ();    M_indexbuffer.allocate (indices, sizeof (indices));    Set model matrix and projection matrix float aspectratio = float (window ()->width ())/Float (window ()->height ());                                    M_projectionmatrix.perspective (45.0f, Aspectratio,    0.5f, 500.0f); Connect (Window ()->openglcontext (), SIGNAL (abouttobedestroyed ()), this, SLOT (Release ())    , Qt::D irectconnection); return true;}    void Cube::release (void) {Qdebug ("Vertex buffer and index buffer is to be destroyed.");    M_vertexbuffer.destroy (); M_inDexbuffer.destroy (); M_colorbuffer.destroy ();}

Class is more complex to implement. It is divided into tectonic phase, initialization stage, rendering stage and releasing space stage. Here we use the OpenGL ES 2.0 common Buffer + attribute array method for efficient rendering. For the above OpenGL knowledge, interested peers can take a look at "OpenGL ES 2.0 Programming Guide", QT books about OpenGL, the Kdab blog about OpenGL knowledge and my other blogs to get the relevant knowledge.

The above program loads the vertex shader and fragment shader. They are as follows:

Shader.vshattribute highp vec3 position;attribute highp vec4 color;uniform mat4 modelviewmatrix;uniform mat4 projectio Nmatrix;varying highp vec4 v_color;void Main (void) {    gl_position = ProjectionMatrix *            Modelviewmatrix *            VEC4 (position, 1.0);    V_color = Color;}

Shader.fshvarying highp vec4 v_color;void Main (void) {    gl_fragcolor = V_color;}

This example works on three desktop platforms and works smoothly on the Android platform.


QT Mobile Application Development (eight): enabling cross-platform QML and OpenGL mixed rendering

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.