OpenGL是一款强大的图形渲染库,而Qt则提供了一套方便的工具集,使得在Qt应用程序中集成OpenGL变得相对简单。本文将介绍如何使用Qt和OpenGL,通过单独的顶点着色器和片段着色器文件,绘制一个带有纹理贴图的正方形。我们将分步讲解,确保你能轻松理解每个步骤。
在创建一个Qt Widgets应用程序项目后,首先在项目的根目录下创建两个文件,分别命名为vertexshader.glsl
和fragmentshader.glsl
。这两个文件将包含我们的顶点着色器和片段着色器代码。
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;
out vec2 TexCoord;
void main()
{
gl_Position = vec4(aPos, 1.0);
TexCoord = aTexCoord;
}
fragmentshader.glsl:
#version 330 core
in vec2 TexCoord;
out vec4 FragColor;
uniform sampler2D ourTexture;
void main()
{
FragColor = texture(ourTexture, TexCoord);
}
修改主窗口类的头文件和源文件,添加对应的成员变量和函数,以便使用着色器文件和绘制正方形。
mainwindow.h:
// mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include
#include
#include
#include
namespace Ui {
class MainWindow;
}
class MyOpenGLWidget : public QOpenGLWidget, protected QOpenGLFunctions
{
Q_OBJECT
public:
MyOpenGLWidget(QWidget *parent = nullptr);
~MyOpenGLWidget() override;
protected:
void initializeGL() override;
void resizeGL(int w, int h) override;
void paintGL() override;
private:
QOpenGLShaderProgram shaderProgram;
GLuint VAO, VBO, EBO;
GLuint textureID;
void setupShaderProgram();
void setupVertices();
void setupTexture();
};
#endif // MAINWINDOW_H
mainwindow.cpp:
// mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include
#include
#include
MyOpenGLWidget::MyOpenGLWidget(QWidget *parent)
: QOpenGLWidget(parent)
{
}
MyOpenGLWidget::~MyOpenGLWidget()
{
}
void MyOpenGLWidget::initializeGL()
{
initializeOpenGLFunctions();
glEnable(GL_DEPTH_TEST);
setupShaderProgram();
setupVertices();
setupTexture();
}
void MyOpenGLWidget::resizeGL(int w, int h)
{
glViewport(0, 0, w, h);
}
void MyOpenGLWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
shaderProgram.bind();
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
shaderProgram.release();
}
void MyOpenGLWidget::setupShaderProgram()
{
// 加载顶点着色器和片段着色器
shaderProgram.addShaderFromSourceFile(QOpenGLShader::Vertex, ":/vertexshader.glsl");
shaderProgram.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/fragmentshader.glsl");
// 链接着色器程序
shaderProgram.link();
}
void MyOpenGLWidget::setupVertices()
{
GLfloat vertices[] = {
// 位置 // 纹理坐标
0.5f, 0.5f, 0.0f, 1.0f, 1.0f, // 右上角
0.5f, -0.5f, 0.0f, 1.0f, 0.0f, // 右下角
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, // 左下角
-0.5f, 0.5f, 0.0f, 0.0f, 1.0f // 左上角
};
GLuint indices[] = {
0, 1, 3, // 第一个三角形
1, 2, 3 // 第二个三角形
};
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
// 顶点位置
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// 纹理坐标
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void MyOpenGLWidget::setupTexture()
{
QImage image(":/texture.jpg");
if (image.isNull()) {
qDebug() << "Failed to load texture image";
return;
}
QOpenGLTexture* texture = new QOpenGLTexture(image.mirrored());
texture->setMinificationFilter(QOpenGLTexture::Linear);
texture->setMagnificationFilter(QOpenGLTexture::Linear);
texture->setWrapMode(QOpenGLTexture::Repeat);
textureID = texture->textureId();
shaderProgram.bind();
shaderProgram.setUniformValue("ourTexture", 0);
shaderProgram.release();
}
确保将你的纹理图片(如texture.jpg
)放在项目的资源文件夹中。然后运行程序,你应该能够看到一个带有纹理的正方形。
这个简单的例子展示了如何在Qt中使用OpenGL,加载纹理贴图,并通过顶点着色器和片段着色器文件绘制一个带有纹理的正方形。你可以基于这个例子进行更复杂的OpenGL应用程序的开发。