1. Creating the OpenGL Window
- Inherit
QOpenGLWidget: Provides a rendering viewport, functionally similar toGLFW. - Inherit
QOpenGLFunctions: ProvidesinitializeOpenGLFunctions()to retrieve OpenGL function pointers from the driver, analogous toGLAD. - Member
QOpenGLShaderProgram *program_;: Stores the shader script context.
GLFW provides a cross-platform OpenGL rendering window, managing keyboard, mouse, and other interactions uniformly. GLAD proivdes a cross-platform function loader that loads OpenGL API function pointers from the driver.
#pragma once
#include <QtOpenGL/qopenglshaderprogram.h>
#include <QtOpenGLWidgets/QOpenGLWidget>
#include <QOpenGLFunctions>
class RenderCanvas : public QOpenGLWidget, protected QOpenGLFunctions
{
Q_OBJECT
public:
RenderCanvas(QWidget *parent = nullptr);
~RenderCanvas();
protected:
void initializeGL() override;
void paintGL() override;
void resizeGL(int w, int h) override;
private:
// Stores shader script context and parameters passed to OpenGL API
QOpenGLShaderProgram *shaderProgram_;
};
2. Initializing Function Pointers and Obtaining Shader Objects
void RenderCanvas::initializeGL()
{
// Initialize global OpenGL function pointers
initializeOpenGLFunctions();
// Internally uses the global OpenGL function pointers directly
shaderProgram_ = new QOpenGLShaderProgram(this);
}
graph LR
A[QOpenGLWidget] -->|Creates| B(OpenGL Context)
B --> C[QOpenGLFunctions]
C -->|Loads| D(glCreateProgram, glLinkProgram...)
E[QOpenGLShaderProgram] -->|Calls| D
E -->|Encapsulates| F(Shader Management Interface)
C -->|Provides| G(User-called OpenGL API)
3. Writing Shader Programs
#include "rendercanvas.h"
#include <QOpenGLShaderProgram>
// Vertex shader (directly outputs vertex position and a fixed color)
const char* vertexSource = R"(
void main() {
gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
}
)";
// Fragment shader (outputs solid red)
const char* fragmentSource = R"(
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
)";
4. Compiling and Linking OpenGL Shaders
Compilation: shaderProgram_.addShaderFromSourceCode(QOpenGLShader::Vertex, vertexSource);
Linking: shaderProgram_.link(); Merges multiple shaders into a complete program; performed once during initialization.
Activation: shaderProgram_.bind(); Sets the program as the active GPU program for subsequent rendering calls.
void RenderCanvas::initializeGL() {
// Critical: Initialize OpenGL function pointers
initializeOpenGLFunctions();
// Compile shaders
shaderProgram_.addShaderFromSourceCode(QOpenGLShader::Vertex, vertexSource);
shaderProgram_.addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentSource);
// Link shader program: combines compiled vertex and fragment shaders into a single complete shader program.
shaderProgram_.link();
}
void RenderCanvas::paintGL() {
// Clear screen (defaults to black)
glClear(GL_COLOR_BUFFER_BIT);
// Set the linked shader program as the current active program on GPU for subsequent draw calls.
shaderProgram_.bind();
// Draw a triangle (demonstrates workflow despite missing vertex data)
glDrawArrays(GL_TRIANGLES, 0, 3);
shaderProgram_.release();
}
graph TD
A[initializeGL] --> B[initializeOpenGLFunctions]
B --> C[shaderProgram_->addShaderFromSourceCode]
C --> D[shaderProgram_->link]
D --> E[paintGL]
E --> F[shaderProgram_->bind]
F --> G[glDrawArrays]
G --> H[shaderProgram_->release]