在使用纯C++进行OpenGL开发的时候,需要使用额外的库(例如:GLFW、GLAD等),但是使用Qt进行OpenGL开发时将不再需要安装额外的库,自Qt5.4以后Qt便有了QOpenGLWidget类使我们方便的进行开发。
初学OpenGL在求助前辈后得到一个国外大神编写的OpenGL教程,由国内大神进行了翻译(网址在文末给出)。但是大神是用的纯C++进行的开发,所以并不是很适合Qt+OpenGL的模式。那么如何根据大神的代码进行修改变成适合Qt的代码呢?
1、创建自定义OpenGLWidget并继承自QOpenGLWidget以及QOpenGLFunctions_3_0(此处根据需要采用的OpenGL版本进行调整,为了跟教程一致故笔者采用3.0版本);
2、实现QOpenGLWidget的三个纯虚函数initializeGL()、paintGL()、resizeGL(int w,int h)以及初始化functions。代码如下:
//openglwidget_glfw.h文件
#ifndef OPENGL_GLFW_H
#define OPENGL_GLFW_H
#include
#include
#include
#include
class OpenGL_GLFW:public QOpenGLWidget,protected QOpenGLFunctions_3_0
{
Q_OBJECT
public:
explicit OpenGL_GLFW(QWidget *parent = nullptr);
~OpenGL_GLFW();
protected:
void initializeGL();
void paintGL();
void resizeGL(int w,int h);
private:
unsigned int shaderProgram;
};
#endif // OPENGL_GLFW_H
//openglwidget_glfw.cpp
#include "opengl_glfw.h"
#include
float vertices[] = {
-0.5f,-0.5f,0.0f,
0.5f,0.5f,0.0f,
0.0f,0.5f,0.0f
};
//顶点着色器源码
const char *vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
//片段着色器源码
const char *fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
" FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";
OpenGL_GLFW::OpenGL_GLFW(QWidget *parent):
QOpenGLWidget(parent)
{
}
OpenGL_GLFW::~OpenGL_GLFW()
{
}
void OpenGL_GLFW::initializeGL()
{
initializeOpenGLFunctions();
}
void OpenGL_GLFW::paintGL()
{
}
void OpenGL_GLFW::resizeGL(int w, int h)
{
glViewport(0,0,w,h);
}
3、教程中的定义着色器部分以及编译链接着色器只需要执行一次,故我们放在initializeGL中,代码如下:
void OpenGL_GLFW::initializeGL()
{
initializeOpenGLFunctions();
unsigned int vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);//创建顶点着色器
glShaderSource(vertexShader,1,&vertexShaderSource,NULL);//参数2为需要编译的着色器源码的数量
glCompileShader(vertexShader);
int success;
char infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);//检查着色器编译是否成功
if(!success)
{
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);//获取错误消息
qDebug() << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog;
}
unsigned int fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);//创建片段着色器
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
success = -1;
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);//检查着色器编译是否成功
if(!success)
{
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);//获取错误消息
qDebug() << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog;
}
shaderProgram = glCreateProgram();//创建程序对象
glAttachShader(shaderProgram,vertexShader);//附加着色器到程序对象上
glAttachShader(shaderProgram,fragmentShader);//附加着色器到程序对象上
glLinkProgram(shaderProgram);
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);//检查程序对象编译是否成功
if(!success) {
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
qDebug() << "ERROR::SHADER::SHADERPROGRAM::COMPILATION_FAILED\n" << infoLog;
}
glUseProgram(shaderProgram);//激活程序对象
glDeleteShader(vertexShader);//删除顶点着色器
glDeleteShader(fragmentShader);//删除片段着色器
}
}
4、绘制代码放入paintGL中,代码如下:
void OpenGL_GLFW::paintGL()
{
glEnable(GL_DEPTH_TEST);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
float vertices[] = {
-0.5f, -0.5f, 0.0f, // left
0.5f, -0.5f, 0.0f, // right
0.0f, 0.5f, 0.0f // top
};
unsigned int VBO, VAO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
// bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind
glBindBuffer(GL_ARRAY_BUFFER, 0);
// You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other
// VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary.
glBindVertexArray(0);
glUseProgram(shaderProgram);
glBindVertexArray(VAO); // seeing as we only have a single VAO there's no need to bind it every time, but we'll do so to keep things a bit more organized
glDrawArrays(GL_TRIANGLES, 0, 3);
}
代码运行结果如下:
笔者Qt版本:5.8.0
完整代码:https://download.csdn.net/download/juicyactivegilbert/11184953
参考网址:https://learnopengl-cn.github.io/01%20Getting%20started/04%20Hello%20Triangle/