本篇文章参考的是Joey De Vries的现代OpenGL教程。
原教程是在windows visual studio环境下开发的,但因本人所用系统为ubuntu,所以便尝试在ubuntu qt开发环境下进行opengl的学习。
原Joey De Vries 的现代OpenGL教程链接如下
运行结果如下图所示:
1.创建工程的步骤在上一篇博客已有展示,这里就不写了,直接把最后的项目工程贴上:
2.首先在opengl_rect.pro文件中添加opengl模块以使opengl函数库中的函数可用,如图黑色横线上面部分:
添加完opengl模块后要先编译一下以确保模块成功加载),编译按钮如图黑色圆圈里面部分:
3. widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include
#include
#include
#include
#include
#include
class Rect : public QOpenGLWidget,protected QOpenGLFunctions_3_3_Core //qt对opengl的支持,必须public继承QOpenGLWidget类(QOpenGLFunctions_3_3_Core表示所用版本为3.3,需要protected继承)
{
Q_OBJECT
public:
Rect();//构造函数
~Rect();//析构函数
protected:
//重写这三个函数
virtual void initializeGL();//用来初始化opengl的资源和状态
virtual void resizeGL(int w, int h);//用来设置窗口大小
virtual void paintGL();//用来绘制窗口
private:
QOpenGLShaderProgram shaderProgram;//着色器类
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include
static unsigned int VAO,VBO,EBO;
Rect::Rect()
{
this->setWindowTitle("rect");//设置窗口标题
}
Rect::~Rect()//析构函数,用来在程序运行结束时释放VAO,VBO,EBO
{
glDeleteVertexArrays(1,&VAO);
glDeleteBuffers(1,&VBO);
glDeleteBuffers(1,&EBO);
}
void Rect::initializeGL()
{
this->initializeOpenGLFunctions();//初始化qt opengl部分
bool success = shaderProgram.addShaderFromSourceFile(QOpenGLShader::Vertex,":/rect.vert");//加载顶点着色器
if(!success)
{
QMessageBox::critical(this,"error","顶点着色器triangle.vert加载失败");
}
success = shaderProgram.addShaderFromSourceFile(QOpenGLShader::Fragment,":/rect.frag");//加载片段着色器
if(!success)
{
QMessageBox::critical(this,"error","片段着色器triangle.frag加载失败");
}
success = shaderProgram.link();//把着色器链接到程序上
if(!success)
{
QMessageBox::critical(this,"error","着色器连接失败");
}
float vertices[]={ //坐标数组
-0.5f,-0.5f,0.0f, //左下角顶点,对应索引序号0
0.5f,-0.5f,0.0f, //右下角顶点,对应索引序号1
0.5f,0.5f,0.0f, //右上角顶点,对应索引序号2
-0.5f,0.5f,0.0f //左上角顶点,对应索引序号3
};
unsigned int indices[]=
{
0,1,2, //索引都是从0开始
2,3,0
};
glGenVertexArrays(1,&VAO);//生成一个顶点数组对象
glGenBuffers(1,&VBO);//生成一个顶点缓冲对象
glGenBuffers(1,&EBO);//生成一个索引缓冲对象
glBindVertexArray(VAO);//通过VAO绑定VBO的顶点数据
glBindBuffer(GL_ARRAY_BUFFER,VBO);//把新建的VBO缓冲绑定到GL_ARRAY_BUFFER目标上
glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);//把之前定义的顶点数据复制到缓冲的内存中
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);//绑定EBO缓冲到GL_ARRAY_BUFFER目标上
glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(indices),indices,GL_STATIC_DRAW);//复制索引数组到索引缓冲
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,3*sizeof(GL_FLOAT),(void*)0);//告诉opengl如何解析顶点数据
glEnableVertexAttribArray(0);//启用顶点属性0
glBindBuffer(GL_ARRAY_BUFFER,0);//取消VBO的绑定
glBindVertexArray(0);//取消VAO的绑定
}
void Rect::resizeGL(int w, int h)
{
glViewport(0,0,w,h);//控制渲染窗口的大小
}
void Rect::paintGL()
{
glClearColor(0.2f,0.3f,0.3f,1.0f);
glClear(GL_COLOR_BUFFER_BIT);
shaderProgram.bind();
glBindVertexArray(VAO);
//glDrawArrays(GL_TRIANGLES,0,3);
glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,0);//指明要从索引缓冲渲染
shaderProgram.release();
}
main.cpp
#include "widget.h"
#include
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Rect w;
w.show();
return a.exec();
}
rect.vert
#version 330 core
layout(location = 0)in vec3 aPos;
void main()
{
gl_Position = vec4(aPos.x,aPos.y,aPos.z,1.0f);
}
rect.frag
#version 330 core
out vec4 FragColor;
void main()
{
FragColor = vec4(0.0f,1.0f,1.0f,1.0f);
}