基于 Ubuntu Qt的OpenGL编程 ------1.2 矩形

本篇文章参考的是Joey De Vries的现代OpenGL教程。
原教程是在windows visual studio环境下开发的,但因本人所用系统为ubuntu,所以便尝试在ubuntu qt开发环境下进行opengl的学习。

原Joey De Vries 的现代OpenGL教程链接如下

运行结果如下图所示:
基于 Ubuntu Qt的OpenGL编程 ------1.2 矩形_第1张图片
1.创建工程的步骤在上一篇博客已有展示,这里就不写了,直接把最后的项目工程贴上:
基于 Ubuntu Qt的OpenGL编程 ------1.2 矩形_第2张图片
2.首先在opengl_rect.pro文件中添加opengl模块以使opengl函数库中的函数可用,如图黑色横线上面部分:
基于 Ubuntu Qt的OpenGL编程 ------1.2 矩形_第3张图片
添加完opengl模块后要先编译一下以确保模块成功加载),编译按钮如图黑色圆圈里面部分:
基于 Ubuntu Qt的OpenGL编程 ------1.2 矩形_第4张图片
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);
}

你可能感兴趣的:(qt,opengl,c++)