SoFunction
Updated on 2025-04-14

Guide to Drawing Triangles with OpenGL in Qt

This article only introduces the use of basic QOpenGLWidget and QOpenGLFunctions. Friends who want to learn OpenGL are recommended to visit the classic OpenGL learning website:LearnOpenGL CN

In this article, we will take drawing a classic triangle as an example and talk about how to use OpenGL in Qt to draw GPU.

Preface

In high-performance rendering scenarios, CPU resources are often over-consuming, resulting in interface stuttering. As an industry-standard graphics API, OpenGL can significantly reduce CPU load through GPU hardware acceleration. This article will use drawing triangles as an example to teach you how to implement cross-platform GPU rendering through QT's QOpenGLWidget and QOpenGLFunctions.

QOpenGLFunctions

There are differences in the implementation of OpenGL functions on different platforms (Windows/Linux/Mac). For example:

platform Function loading method
Windows wglGetProcAddress
Linux glXGetProcAddress

Qt byQOpenGLFunctionsEncapsulated these underlying differences, developers only need to inherit this class and use itglClear()The unified interface calls OpenGL functions without writing platform-specific code. In this way, we can use an OpenGL phase on different platforms using a set of code. It is also very simple to use this class. Let our class inherit directly.QOpenGLFuntionsJust be fine. You can also cooperateQOpenGLWidgetCome to use it ininitializeGLIn the function, callinitializeOpenGLFunctionsAfter that, it's OKDirectly use OpenGL functions

Loading under Windows (wglGetProcAddress)

For example, under Windows, we usewglGetProcAddressTo dynamically load these functions (e.g.glClear), here is the loading code:

Contains the necessary header files

#include <>
#include <GL/>
#include <GL/>  // supply OpenGL Extended Statement

Define function pointer type

// Example: Define the function pointer type of glCleartypedef void (APIENTRY *PFNGLCLEARPROC)(GLbitfield);
PFNGLCLEARPROC glClear;

Loading OpenGL functions

// Initialize OpenGL functionvoid initOpenGLFunctions() {
    // 1. Load the OpenGL 1.1 function (provided by)    glClear = (PFNGLCLEARPROC)wglGetProcAddress("glClear");
    // 2. Check whether the loading is successful    if (!glClear) {
        // If it fails, it may be that the driver does not support the function        MessageBoxA(NULL, "Failed to load glClear", "Error", MB_OK);
        exit(1);
    }
    // 3. Load other functions in a similar way...    // glDrawArrays = (PFNGLDRAWARRAYSPROC)wglGetProcAddress("glDrawArrays");
    // ...
}

Using loaded functions

glClear(GL_COLOR_BUFFER_BIT);  // It can be called normally now

Loading under Linux (glXGetProcAddress )

And in linux, the loaded function becomes:glXGetProcAddress, the corresponding code is:

Contains the necessary header files

#include <GL/>
#include <GL// OpenGL extension for X11#include &lt;GL/&gt;

Define function pointer type

// Example: Define the function pointer type of glCleartypedef void (*PFNGLCLEARPROC)(GLbitfield);
PFNGLCLEARPROC glClear;

Loading OpenGL functions

void initOpenGLFunctions() {
    // 1. Load glClear    glClear = (PFNGLCLEARPROC)glXGetProcAddress((const GLubyte*)"glClear");
    // 2. Check whether the loading is successful    if (!glClear) {
        fprintf(stderr, "Failed to load glClear\n");
        exit(1);
    }
    // 3. Load other functions in a similar way...    // glDrawArrays = (PFNGLDRAWARRAYSPROC)glXGetProcAddress((const GLubyte*)"glDrawArrays");
    // ...
}

Using loaded functions

glClear(GL_COLOR_BUFFER_BIT);  // It can be called normally now

QOpenGLWidget

QOpenGLWidgetis a widget class provided by Qt, used to embed OpenGL rendering content in Qt applications. It inherits fromQWidget, an OpenGL context is managed internally (for example, calls under WindowswglMakeCurrent / wglDoneCurrent) and frame buffers and provide the ability to seamlessly integrate with the Qt windowing system. For details, please see:QOpenGLWidget Class

We can create our own window, inherit QOpenGLWidget, and then rewrite the following three functions to handle some OpenGL-related work.

initializeGL

Initialize some OpenGL-related resources or states. This function is called for the first timeresizeGLorpaintGLCalled before.

paintGL

Rendering OpenGL scenes, similar to what we usually useQWidget::paintEvent, called when the window needs to be updated.

resizeGL

Resize or project the OpenGL Viewport, etc., and call it when the window needs to be resized.

Complete code

#pragma once
#include <QOpenGLBuffer>
#include <QOpenGLWidget>
#include <QOpenGLShaderProgram>
#include <QOpenGLFunctions>
#include ""
class COpenGLRenderWidget : public QOpenGLWidget, protected QOpenGLFunctions
{
    Q_OBJECT
public:
    explicit COpenGLRenderWidget(QWidget *parent = nullptr);
    ~COpenGLRenderWidget() override;
private:
    void InitShaders();
private:
    void initializeGL() override;
    void paintGL() override;
    void resizeGL(int w, int h) override;
private:
    QOpenGLShaderProgram m_shaderProgram;
    QOpenGLBuffer m_vbo;
};
#include ""
static const GLfloat coordinateBasic[] = {
    // Vertex coordinates, storing 3 xyz coordinates    // x     y     z
    -0.5f, -0.5f, 0.0f,
     0.5f, -0.5f, 0.0f,
     0.0f,  0.5f, 0.0f,
};
constexpr auto VERTEX_SHADER_BASIC = R"(
attribute vec3 vertexIn; 
varying vec2 textureOut; 
void main(void)
{
    gl_Position = vec4(vertexIn, 1.0);
}
)";
constexpr auto FRAGMENT_SHADER_BASIC = R"(
varying vec2 textureOut;
void main(void) 
{ 
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); 
}
)";
COpenGLRenderWidget::COpenGLRenderWidget(QWidget *parent)
    : QOpenGLWidget(parent)
{}
COpenGLRenderWidget::~COpenGLRenderWidget()
{}
void COpenGLRenderWidget::initializeGL()
{
    initializeOpenGLFunctions();
    glDisable(GL_DEPTH_TEST);
    m_vbo.create();
    m_vbo.bind();
    m_vbo.allocate(coordinateBasic, sizeof(coordinateBasic));
    InitShaders();
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
}
void COpenGLRenderWidget::paintGL()
{
    m_shaderProgram.bind();
    glDrawArrays(GL_TRIANGLES, 0, 3);
    m_shaderProgram.release();
}
void COpenGLRenderWidget::resizeGL(int w, int h)
{
    glViewport(0, 0, w, h);
    update();
}
void COpenGLRenderWidget::InitShaders()
{
    QOpenGLShader vertexShader(QOpenGLShader::Vertex);
    if (!(VERTEX_SHADER_BASIC))
    {
        qDebug() &lt;&lt; "Vertex shader compilation failed. Error: " &lt;&lt; ();
        return;
    }
    QOpenGLShader fragmentShader(QOpenGLShader::Fragment);
    if (!(FRAGMENT_SHADER_BASIC))
    {
        qDebug() &lt;&lt; "Fragment shader compilation failed. Error: " &lt;&lt; ();
        return;
    }
    m_shaderProgram.addShader(&amp;vertexShader);
    m_shaderProgram.addShader(&amp;fragmentShader);
    m_shaderProgram.link();
    m_shaderProgram.bind();
    m_shaderProgram.setAttributeBuffer("vertexIn", GL_FLOAT, 0, 3, 3 * sizeof(float));
    m_shaderProgram.enableAttributeArray("vertexIn");
}

This is the article about using OpenGL drawing guide in Qt. For more information about using OpenGL drawing guide in Qt, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!