Vẽ tam giác bằng OpenGL trong Qt

Trong bài viết này, chúng ta sẽ tìm hiểu cách sử dụng OpenGL để vẽ một tam giác ở giữa màn hình với sự hỗ trợ của thư viện Qt.

Cấu hình dự án CMake

Dưới đây là cấu hình CMake để xây dựng ứng dụng:


cmake_minimum_required(VERSION 3.12)

project(glqt VERSION 1.0 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)

# Đảm bảo mã nguồn được xử lý dưới định dạng UTF-8
if(MSVC)
    add_compile_options(/utf-8)
endif()

find_package(Qt5 REQUIRED COMPONENTS Core Widgets OpenGL)

file(GLOB SOURCES *.cpp)
file(GLOB RESOURCE_FILES "${CMAKE_SOURCE_DIR}/*.qrc")

add_executable(${PROJECT_NAME} ${SOURCES} ${RESOURCE_FILES})

target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Core Qt5::Widgets Qt5::OpenGL)

Tạo cửa sổ chính

Lớp MainWindow đại diện cho cửa sổ chính của ứng dụng:


#include <QMainWindow>

class MainWindow : public QMainWindow {
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
};

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent) {
    setCentralWidget(new CustomGLWidget());
}

MainWindow::~MainWindow() {}

Tạo widget OpenGL tùy chỉnh

Lớp CustomGLWidget kế thừa từ QOpenGLWidgetQOpenGLFunctions_4_5_Core:


#include <QOpenGLWidget>
#include <QOpenGLFunctions_4_5_Core>
#include <QOpenGLShaderProgram>
#include <QOpenGLBuffer>
#include <QOpenGLVertexArrayObject>

class CustomGLWidget : public QOpenGLWidget, protected QOpenGLFunctions_4_5_Core {
    Q_OBJECT

public:
    CustomGLWidget(QWidget *parent = nullptr);
    ~CustomGLWidget();

protected:
    void initializeGL() override;
    void resizeGL(int w, int h) override;
    void paintGL() override;

private:
    QOpenGLShaderProgram *shaderProgram;
    QOpenGLBuffer vertexBuffer;
    QOpenGLVertexArrayObject vertexArrayObject;
};

CustomGLWidget::CustomGLWidget(QWidget *parent)
    : QOpenGLWidget(parent) {
    QSurfaceFormat format;
    format.setVersion(4, 5);
    format.setProfile(QSurfaceFormat::CoreProfile);
    setFormat(format);
}

CustomGLWidget::~CustomGLWidget() {
    if (vertexArrayObject.isCreated()) {
        vertexArrayObject.destroy();
    }
    if (vertexBuffer.isCreated()) {
        vertexBuffer.destroy();
    }
}

void CustomGLWidget::initializeGL() {
    initializeOpenGLFunctions();

    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

    shaderProgram = new QOpenGLShaderProgram(this);

    shaderProgram->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/custom_vertex.glsl");
    shaderProgram->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/custom_fragment.glsl");
    shaderProgram->link();

    const float vertices[] = {
        -0.5f, -0.5f, 0.0f,
         0.5f, -0.5f, 0.0f,
         0.0f,  0.5f, 0.0f
    };

    vertexArrayObject.create();
    vertexArrayObject.bind();

    vertexBuffer.create();
    vertexBuffer.bind();
    vertexBuffer.allocate(vertices, sizeof(vertices));

    shaderProgram->bind();
    shaderProgram->enableAttributeArray(0);
    shaderProgram->setAttributeBuffer(0, GL_FLOAT, 0, 3, 3 * sizeof(float));
    shaderProgram->release();

    vertexArrayObject.release();
    vertexBuffer.release();
}

void CustomGLWidget::resizeGL(int w, int h) {
    glViewport(0, 0, w, h);
}

void CustomGLWidget::paintGL() {
    glClear(GL_COLOR_BUFFER_BIT);

    shaderProgram->bind();
    vertexArrayObject.bind();

    glDrawArrays(GL_TRIANGLES, 0, 3);

    vertexArrayObject.release();
    shaderProgram->release();
}

Shaders tùy chỉnh

Đây là nội dung của các tệp shader:

// custom_vertex.glsl
#version 450 core
layout(location = 0) in vec3 vertexPosition;
void main() {
    gl_Position = vec4(vertexPosition, 1.0);
}

// custom_fragment.glsl
#version 450 core
out vec4 outputColor;
void main() {
    outputColor = vec4(0.0, 0.0, 1.0, 1.0);
}

Kết quả cuối cùng là một tam giác màu xanh lam được hiển thị ở giữa cửa sổ.

Thẻ: Qt OpenGL glsl

Đăng vào ngày 29 tháng 8 lúc 22:10