"Qt for Android" OpenGL ES Draw colored cubes

Source: Internet
Author: User

QT built-in support for OpenGL ES, the use of QT for OpenGL ES Development is very convenient, many auxiliary classes are already available. A Qwindow class has been added since QT 5.0, which can either use OpenGL to draw 3D graphics, or use Qpainter to draw 2D traditional GDI + graphics, which are not recommended for use by the previous qglwidget. In the coming (official time this fall) Qt 5.4 will completely discard qglwidget, and as an alternative will add qopenglwidget and Qopenglwindow classes to facilitate OpenGL programming.

All right, nonsense, I'm going to use OpenGL ES to draw a color cube today, and then compile it once for the Android platform after the desktop platform has been successfully compiled, and here's how it works on Android, drawing four identical colored cubes based on the same shader.

To use OpenGL, I derive a Openglwindow class from the Qwindow class and the Qopenglfunctions class, which declares the following:

Class Openglwindow:public Qwindow, protected qopenglfunctions{    q_objectpublic:    Explicit Openglwindow ( Qwindow *parent = 0);    ~openglwindow ();    virtual void Initialize ();    virtual void render (Qpainter *painter);    virtual void render (double currenttime = 0.0);      Elapsed seconds from program started.protected:    void Exposeevent (qexposeevent *event);p rivate:    Qopenglpaintdevice *m_device;    Qopenglcontext *m_context;    Qtime   startTime;    Gluint m_program;//Qopenglshaderprogram *m_shaderprogram; };

Because it inherits from Qwindow, you can use the OpenGL environment provided by Qwindow, which does not require EGL to control local window display graphics. As well as inheriting from Qopenglfunctions, the native OpenGL API of gl* style can be used directly in the member functions of the Openglwindow class. There are a number of packaged OpenGL handy classes in Qt, such as Qopenglshaderprogram, which can be easily manipulated by shader programs, but this may be unfriendly to people unfamiliar with QT, so here I don't use QT-provided convenience classes, but directly using native C-style OpenGL API, which is perfectly possible (which is one of the reasons I like QT: While providing your own class library, you can use non-QT classes and provide conversions between them, such as the container class Qvector, Qmap, qstring in Qt, and C + + The corresponding containers in the standard library are converted to each other). You can even mix OpenGL classes with QT and native OpenGL APIs.

Here's a look at some key functions. First, initialize () is responsible for creating, compiling, linking, and setting the background color of the shader. The code below, where the annotated part is implemented using the QT self-contained class library, implements the same functionality.

void Openglwindow::initialize () {const char *vertexshadersrc = "attribute Vec4 a_position; \ n "" Uniform mat4 U_MVP; \ n "" varying vec4 v_color; \ n "" void main () \ n "" {\ n "" V_color = A_posi  tion*0.7 + 0.5; \ n "" gl_position = U_MVP * a_position;    \ n "} \ n"; const char *FRAGMENTSHADERSRC = "varying vec4 v_color; \ n "" void main () \ n "" {\ n "" Gl_fragco Lor = V_color;    \ n "} \ n";    Gluint vertexshader = Glcreateshader (Gl_vertex_shader);    Glshadersource (vertexshader, 1, &VERTEXSHADERSRC, NULL);    Glcompileshader (vertexshader);    Gluint Fragmentshader = Glcreateshader (Gl_fragment_shader);    Glshadersource (Fragmentshader, 1, &FRAGMENTSHADERSRC, NULL); Glcompileshader (FragmentsHader);    M_program = Glcreateprogram ();    Glattachshader (M_program, vertexshader);    Glattachshader (M_program, Fragmentshader); Gllinkprogram (M_program);//   //Add vertex shader (compiled internal)//    m_ Shaderprogram->addshaderfromsourcecode (Qopenglshader::vertex, VERTEXSHADERSRC);//   //Add Fragment shader (compiled internal)//    M_shaderprogram->addshaderfromsourcecode (qopenglshader: : Fragment, FRAGMENTSHADERSRC);//   //link shaders to program//    m_shaderprogram-    >link ();    Set the background clear color. Glclearcolor (0.0f, 0.0f, 0.0f, 1.0f);}

Then take a look at the Qexposeevent event of Qwindow, which calls the handler for the event when Qwindow needs to redraw exposeevent (), where I override the event's handler function. Isexposed () is used to determine whether the current window is displayed on the screen (onscreen or offscreen) and is redrawn only when it is displayed on the screen (although the window needs to be redrawn, but it is not displayed on the screen, and no one can see it, So add this judgment to reduce unnecessary drawing operations). The OpenGL context is created first, and then the corresponding initialization function is called, and the two steps are executed only the first time and will not be executed again. Next is the core part of the function, calling the render () function to render the back-end buffer graphically, then swapping the front-end and back-end buffers for the back-end buffer graph to display on the interface.

void Openglwindow::exposeevent (Qexposeevent *event) {    q_unused (event)    static bool Needinit = TRUE;    Returns true if this window was exposed in the windowing system.    if (isexposed ())    {        if (M_context = = nullptr)        {            m_context = new Qopenglcontext (this);            M_context->setformat (Requestedformat ());            M_context->create ();        }        M_context->makecurrent (this);        if (needinit)        {            initializeopenglfunctions ();            This->initialize ();            Needinit = false;        }        Calculate elapsed seconds from program started.        Double duration = Starttime.msecsto (Qtime::currenttime ())/1000.0;        Render (duration);        M_context->swapbuffers (this);}    }

Finally look at the render () rendering function, which is also the main part of learning OpenGL.

A Qopenglpaintdevice instance is created at the beginning of the render () function, which is used to draw Qpainter's drawing operations, which can be omitted or deleted. The next step is to define the vertex position of the cube and the vertex index. Creates 2 vertex buffer objects (vertex buffer object), places the vertex position and vertex of the cube through the Glbufferdata () function so that it is placed in the vertex buffer object, passing the vertex position through the glvertexattribpointer () Passed to the vertex shader. Calculates the model/view/projection, then passes the result through GLUNIFORMMATRIX4FV () to the MVP in the vertex shader, and finally draws the cube using Gldrawelement (). The color of each point in the cube is determined by its location, so vertices at different locations have different colors.

void Openglwindow::render (double currenttime) {if (M_device = = nullptr) M_device = new Qopenglpaintdevice;    M_device->setsize (This->size ()); Static Glfloat vcubevertices[] = { -0.5f, 0.5f, 0.5f,//v0-0.5f, -0.5f, 0.5f,//v1 0.5f,-0.         5f, 0.5f,//v2 0.5f, 0.5f, 0.5f,//V3 0.5f, -0.5f, -0.5f,//V4 0.5f, 0.5f, -0.5f,//v5    -0.5f, 0.5f, -0.5f,//v6-0.5f, -0.5f, -0.5f,//V7};        Static Glushort vcubeindices[] = {0, 1, 2, 0, 2, 3,//Front face 5, 6, 7, 4, 5, 7,//Back Face 0, 1, 7, 0, 6, 7,//Left face 2, 3, 4, 3, 4, 5,//Right face 0, 3, 5, 0, 5, 6,//top face 1    , 2, 4, 1, 4, 7//Bottom Face};    Glviewport (0, 0, Width (), height ()); Glclear (Gl_color_buffer_bit |    Gl_depth_buffer_bit);    Gluseprogram (M_program);    Gluint vbos[2];    Glgenbuffers (2, VBOs);    Glbindbuffer (Gl_array_buffer, vbos[0]); Glbufferdata (gl_aRray_buffer, sizeof (vcubevertices), vcubevertices, Gl_static_draw);    Glbindbuffer (Gl_element_array_buffer, vbos[1]);    Glbufferdata (Gl_element_array_buffer, sizeof (vcubeindices), vcubeindices, Gl_static_draw);    Glbindbuffer (Gl_array_buffer, vbos[0]);    Glenablevertexattribarray (0);    Glvertexattribpointer (0, 3, gl_float, Gl_false, 0, 0);    Glbindattriblocation (m_program, 0, "a_position");    static glfloat angle = 0.0;    Gluint Mvploc = glgetuniformlocation (M_program, "U_MVP");    qmatrix4x4 model, view, projection, MVP;    Model.rotate (angle + 5, Qvector3d (1,0,0));    Model.rotate (angle-5, Qvector3d (0,1,0));    Model.scale (0.5, 0.5, 0.5);    View.translate (0.5, 0.5, 0);    Angle + = 10;    MVP = projection * View * model;    GLUNIFORMMATRIX4FV (Mvploc, 1, Gl_false, Mvp.constdata ());    Glbindbuffer (Gl_element_array_buffer, vbos[1]);    Gldrawelements (gl_triangles, sizeof (vcubeindices)/sizeof (Glushort), Gl_unsigned_short, 0); /* Draw another cube in different place with the Same shader */view.translate (-1.0, 0, 0);    MVP = projection * View * model;    GLUNIFORMMATRIX4FV (Mvploc, 1, Gl_false, Mvp.constdata ());    Glbindbuffer (Gl_element_array_buffer, vbos[1]);    Gldrawelements (gl_triangles, sizeof (vcubeindices)/sizeof (Glushort), Gl_unsigned_short, 0);    View.translate (0.0,-1.0, 0);    MVP = projection * View * model;    GLUNIFORMMATRIX4FV (Mvploc, 1, Gl_false, Mvp.constdata ());    Glbindbuffer (Gl_element_array_buffer, vbos[1]);    Gldrawelements (gl_triangles, sizeof (vcubeindices)/sizeof (Glushort), Gl_unsigned_short, 0);    View.translate (1.0, 0, 0);    MVP = projection * View * model;    GLUNIFORMMATRIX4FV (Mvploc, 1, Gl_false, Mvp.constdata ());    Glbindbuffer (Gl_element_array_buffer, vbos[1]);    Gldrawelements (gl_triangles, sizeof (vcubeindices)/sizeof (Glushort), Gl_unsigned_short, 0);    qpainter painter (m_device);    Render (&painter); Gldeletebuffers (2, VBOs);}

All right, that's it.

"Qt for Android" OpenGL ES Draw colored cubes

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.