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ừ QOpenGLWidget và QOpenGLFunctions_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ổ.