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 byQOpenGLFunctions
Encapsulated 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.QOpenGLFuntions
Just be fine. You can also cooperateQOpenGLWidget
Come to use it ininitializeGL
In the function, callinitializeOpenGLFunctions
After that, it's OKDirectly use OpenGL functions。
Loading under Windows (wglGetProcAddress)
For example, under Windows, we usewglGetProcAddress
To 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 <GL/>
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
QOpenGLWidget
is 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 timeresizeGL
orpaintGL
Called 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() << "Vertex shader compilation failed. Error: " << (); return; } QOpenGLShader fragmentShader(QOpenGLShader::Fragment); if (!(FRAGMENT_SHADER_BASIC)) { qDebug() << "Fragment shader compilation failed. Error: " << (); return; } m_shaderProgram.addShader(&vertexShader); m_shaderProgram.addShader(&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!