QT之openGL使用(一)

发布于:2025-07-21 ⋅ 阅读:(20) ⋅ 点赞:(0)

OpenGL简介

官网:OpenGL - The Industry Standard for High Performance Graphics

中文官网:主页 - LearnOpenGL CN

OpenGL(Open Graphics Library)是一种跨语言、跨平台的图形编程接口,主要用于渲染二维和三维矢量图形。它由一个庞大的函数库组成(只有头文件声明,由各家厂家自己实现内容),允许开发者通过编程方式与图形硬件进行交互,从而实现高效、复杂的图形渲染。

以下是OpenGL的一些关键特点和用途:

1. 跨平台和跨语言

  • OpenGL可以在多种操作系统上运行,如Windows、macOS、Linux、Android和iOS等。

  • 它支持多种编程语言,包括C、C++、Python、Java等。

2. 功能强大

  • OpenGL提供了丰富的图形渲染功能,包括几何图形绘制、纹理映射、光照处理、阴影计算、着色器编程等。

  • 它可以用于创建复杂的三维场景,支持实时渲染和交互式图形应用。

3. 硬件加速

  • OpenGL通过与图形硬件(如GPU)紧密配合,利用硬件加速来提高图形渲染的性能。

  • 这使得它在游戏开发、科学计算可视化、虚拟现实等领域表现出色。

4. 可扩展性

  • OpenGL通过扩展机制不断引入新功能,以适应图形硬件和图形技术的发展。

  • 开发者可以通过扩展来访问最新的图形硬件特性。

5. 着色器编程

  • OpenGL支持着色器语言(如GLSL),允许开发者编写自定义的顶点着色器和片元着色器。

  • 着色器编程可以实现复杂的视觉效果,如高级光照模型、动画、粒子系统等。

6. 应用场景

  • 游戏开发:许多游戏引擎(如Unity和Unreal Engine)在底层使用OpenGL或类似技术进行图形渲染。

  • 科学计算与可视化:用于医学成像、气象数据可视化等。

  • 虚拟现实(VR)和增强现实(AR):OpenGL可以高效地渲染沉浸式三维环境。

  • 工业设计与建模:用于CAD软件和三维建模工具。

7. 版本与兼容性

  • OpenGL有多个版本,从早期的1.x版本到现代的4.x版本。现代版本(如OpenGL 4.x)引入了更多高级功能,如计算着色器和多线程渲染。

  • 为了保证兼容性,OpenGL还提供了兼容性上下文(Compatibility Profile)和核心上下文(Core Profile)。

8. 与OpenGL ES的关系

  • OpenGL ES是OpenGL的一个子集,专为嵌入式设备(如移动设备和低功耗设备)设计。

  • 它在功能上与OpenGL相似,但进行了优化以适应移动设备的硬件限制。

9. 与其他图形API的比较

  • 与DirectX:OpenGL是跨平台的,而DirectX主要运行在Windows系统上。两者在功能上类似,但在生态系统和开发工具上有所不同。

  • 与Vulkan:Vulkan是OpenGL的后继者,提供了更底层的硬件访问和更高的性能,但学习曲线更陡峭。

总之,OpenGL是一个功能强大且广泛应用的图形编程接口,它为开发者提供了一个高效、灵活的方式来创建复杂的图形应用程序。

使用流程

初步使用(introduction)

QT中使用OpenGL使用QOpenGLWidget类,需要自己实例化这个类并且重写initializeGL,resizeGL,paintGL这三个保护的虚函数。

myopenglwidget.h

#ifndef MYOPENGLWIDGET_H
#define MYOPENGLWIDGET_H

#include <QWidget>
#include <QOpenGLWidget>
#include <qopenglfunctions_3_3_core.h>
#include  <QOpenGLFunctions_4_5_Core> //这是最新版本

class MyOpenGLWidget : public QOpenGLWidget,QOpenGLFunctions_3_3_Core
{
    Q_OBJECT
public:
    explicit MyOpenGLWidget(QWidget *parent = nullptr);

protected:
    virtual void initializeGL();
    virtual void resizeGL(int w, int h);
    virtual void paintGL();


signals:

};

#endif // MYOPENGLWIDGET_H

myopenglwidget.cpp

#include "myopenglwidget.h"

MyOpenGLWidget::MyOpenGLWidget(QWidget *parent) : QOpenGLWidget(parent)
{

}

void MyOpenGLWidget::initializeGL()
{
    initializeOpenGLFunctions(); //初始化OpenGL函数,将QT里的函数指针指向显卡的函数。
}

void MyOpenGLWidget::resizeGL(int w, int h)
{

}

void MyOpenGLWidget::paintGL()
{
    //需要先初始化在使用
    glClearColor(0.2f,0.2f,0.5f,0.5f); //设置状态
    glClear(GL_COLOR_BUFFER_BIT); //使用状态
}

VAO和VBO

顶点着色器:

他会在GPU上创建对象,用于存储我们的顶点数据,通过顶点缓存对象(Vertex Buffer Objects,VBO)管理。类型是:GL_ARRAY_BUFFER

配置OpenGL如何解释这些内存:

通过顶点数组对象(Vertex Array Objects,VAO)管理。

#include "myopenglwidget.h"

//创建VBO和VAO对象,并赋予ID
unsigned int VBO,VAO;
float vertices[] = {
    -0.5f,-0.5f,0.0f,
    0.5f,-0.5f,0.0f,
    0.0f,0.5f,0.0f
};

MyOpenGLWidget::MyOpenGLWidget(QWidget *parent) : QOpenGLWidget(parent)
{

}

void MyOpenGLWidget::initializeGL()
{
    initializeOpenGLFunctions(); //初始化OpenGL函数,将QT里的函数指针指向显卡的函数。

    //创建VBO和VAO对象,并赋予ID

    glGenVertexArrays(1,&VAO);
    glGenBuffers(1,&VBO);
    //绑定VBO和VAO对象
    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER,VBO);

    //为当前绑定到target的缓冲区对象创建一个新的数据存储
    //如果data不是NULL,则使用来自此指针的数据初始化数据存储
    glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);

    //告知显卡如何去解析缓冲区里的值
    glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,3*sizeof(float),(void*)0);
    //开启VAO管理的第一个属性值。
    glEnableVertexAttribArray(0);

    //VAO VBO 进行休息。
    glBindVertexArray(0);
    glBindBuffer(GL_ARRAY_BUFFER,0);

}

void MyOpenGLWidget::resizeGL(int w, int h)
{

}

void MyOpenGLWidget::paintGL()
{
    //需要先初始化在使用
    glClearColor(0.2f,0.2f,0.2f,1.0f); //设置状态
    glClear(GL_COLOR_BUFFER_BIT); //使用状态

    glBindVertexArray(VAO);
    glDrawArrays(GL_TRIANGLES,0,3);
}

编译链接着色器

#include "myopenglwidget.h"

//创建VBO和VAO对象,并赋予ID
unsigned int VBO,VAO;
float vertices[] = {
    -0.5f,-0.5f,0.0f,
    0.5f,-0.5f,0.0f,
    0.0f,0.5f,0.0f
};
//顶点片段着色器
const char* vertexSharedSource = "#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";

unsigned int shaderProgram ;
unsigned int vertexShader;
unsigned int fragmentShader;

MyOpenGLWidget::MyOpenGLWidget(QWidget *parent) : QOpenGLWidget(parent)
{

}

void MyOpenGLWidget::initializeGL()
{
    initializeOpenGLFunctions(); //初始化OpenGL函数,将QT里的函数指针指向显卡的函数。

    //创建VBO和VAO对象,并赋予ID

    glGenVertexArrays(1,&VAO);
    glGenBuffers(1,&VBO);
    //绑定VBO和VAO对象
    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER,VBO);

    //为当前绑定到target的缓冲区对象创建一个新的数据存储
    //如果data不是NULL,则使用来自此指针的数据初始化数据存储
    glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);

    //告知显卡如何去解析缓冲区里的值
    //第0个属性里面3个值
    glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,3*sizeof(float),(void*)0);
    //开启VAO管理的第一个属性值。
    glEnableVertexAttribArray(0);

    //VAO VBO 进行休息。
    glBindVertexArray(0);
    glBindBuffer(GL_ARRAY_BUFFER,0);


    //顶点着色器
    vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader,1,&vertexSharedSource,NULL);
    glCompileShader(vertexShader);

    //片段着色器shader
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader,1,&fragmentShaderSource,NULL);
    glCompileShader(fragmentShader); //编译程序

    //进行链接程序
    shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram,vertexShader);
    glAttachShader(shaderProgram,fragmentShader);
    glLinkProgram(shaderProgram);



}

void MyOpenGLWidget::resizeGL(int w, int h)
{

}

void MyOpenGLWidget::paintGL()
{
    //需要先初始化在使用
    glClearColor(0.2f,0.2f,0.2f,1.0f); //设置状态
    glClear(GL_COLOR_BUFFER_BIT); //使用状态

    glUseProgram(shaderProgram);

    glBindVertexArray(VAO);
    glDrawArrays(GL_TRIANGLES,0,3);

    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

}

    索引缓冲对象

(Element Buffer Object ,EBO)也叫(Index Buffer Object,IBO)可以绘制两个三角形来组成一个矩形(OPenGL主要处理三角形)这会生成下面的顶点的集合。

#include "myopenglwidget.h"

//创建VBO和VAO对象,并赋予ID
unsigned int VBO,VAO;

float vertices[] = {
    //6个点为一个矩形
    0.5f,0.5f,0.0f,
    0.5f,-0.5f,0.0f,
    -0.5f,0.5f,0.0f,

    0.5f,-0.5f,0.0f,
    -0.5f,0.5f,0.0f,
    -0.5f,-0.5f,0.0f,
};

//顶点片段着色器
const char* vertexSharedSource = "#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";

unsigned int shaderProgram ;
unsigned int vertexShader;
unsigned int fragmentShader;

MyOpenGLWidget::MyOpenGLWidget(QWidget *parent) : QOpenGLWidget(parent)
{

}

void MyOpenGLWidget::initializeGL()
{
    initializeOpenGLFunctions(); //初始化OpenGL函数,将QT里的函数指针指向显卡的函数。

    //创建VBO和VAO对象,并赋予ID

    glGenVertexArrays(1,&VAO);
    glGenBuffers(1,&VBO);
    //绑定VBO和VAO对象
    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER,VBO);

    //为当前绑定到target的缓冲区对象创建一个新的数据存储
    //如果data不是NULL,则使用来自此指针的数据初始化数据存储
    glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);

    //告知显卡如何去解析缓冲区里的值
    //第0个属性里面3个值
    glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,3*sizeof(float),(void*)0);
    //开启VAO管理的第一个属性值。
    glEnableVertexAttribArray(0);

    //VAO VBO 进行休息。
    glBindVertexArray(0);
    glBindBuffer(GL_ARRAY_BUFFER,0);


    //顶点着色器
    vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader,1,&vertexSharedSource,NULL);
    glCompileShader(vertexShader);

    //片段着色器shader
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader,1,&fragmentShaderSource,NULL);
    glCompileShader(fragmentShader); //编译程序

    //进行链接程序
    shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram,vertexShader);
    glAttachShader(shaderProgram,fragmentShader);
    glLinkProgram(shaderProgram);



}

void MyOpenGLWidget::resizeGL(int w, int h)
{

}

void MyOpenGLWidget::paintGL()
{
    //需要先初始化在使用
    glClearColor(0.2f,0.2f,0.2f,1.0f); //设置状态
    glClear(GL_COLOR_BUFFER_BIT); //使用状态

    glUseProgram(shaderProgram);

    glBindVertexArray(VAO);
    glDrawArrays(GL_TRIANGLES,0,6);
    glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); //用线条填充,查看边框

    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

}

EBO画矩形

#include "myopenglwidget.h"

//创建VBO和VAO对象,并赋予ID
unsigned int VBO,VAO,EBO;

float vertices[] = {
    //6个点为一个矩形
    0.5f,0.5f,0.0f,
    0.5f,-0.5f,0.0f,
    -0.5f,0.5f,0.0f,
//    -0.5f,0.5f,0.0f,
//    0.5f,-0.5f,0.0f,
    -0.5f,-0.5f,0.0f,
};

unsigned int indices[] = {
    0,1,2,
    1,2,3
};
//顶点片段着色器
const char* vertexSharedSource = "#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";

unsigned int shaderProgram ;
unsigned int vertexShader;
unsigned int fragmentShader;

MyOpenGLWidget::MyOpenGLWidget(QWidget *parent) : QOpenGLWidget(parent)
{

}

void MyOpenGLWidget::initializeGL()
{
    initializeOpenGLFunctions(); //初始化OpenGL函数,将QT里的函数指针指向显卡的函数。

    //创建VBO和VAO对象,并赋予ID

    glGenVertexArrays(1,&VAO);
    glGenBuffers(1,&VBO);
    //绑定VBO和VAO对象
    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER,VBO);

    //为当前绑定到target的缓冲区对象创建一个新的数据存储
    //如果data不是NULL,则使用来自此指针的数据初始化数据存储
    glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);

    //告知显卡如何去解析缓冲区里的值
    //第0个属性里面3个值
    glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,3*sizeof(float),(void*)0);
    //开启VAO管理的第一个属性值。
    glEnableVertexAttribArray(0);

    //VAO VBO 进行休息。
//    glBindVertexArray(0); //解绑
    glBindBuffer(GL_ARRAY_BUFFER,0);


    //顶点着色器
    vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader,1,&vertexSharedSource,NULL);
    glCompileShader(vertexShader);

    //片段着色器shader
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader,1,&fragmentShaderSource,NULL);
    glCompileShader(fragmentShader); //编译程序

    //进行链接程序
    shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram,vertexShader);
    glAttachShader(shaderProgram,fragmentShader);
    glLinkProgram(shaderProgram);


    //EBO
    glGenBuffers(1,&EBO);
    //绑定VBO和VAO对象
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(indices),indices,GL_STATIC_DRAW);

    //EBO解绑,解绑之后数据会丢失
//    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);

}

void MyOpenGLWidget::resizeGL(int w, int h)
{

}

void MyOpenGLWidget::paintGL()
{
    //需要先初始化在使用
    glClearColor(0.2f,0.2f,0.2f,1.0f); //设置状态
    glClear(GL_COLOR_BUFFER_BIT); //使用状态

    glUseProgram(shaderProgram);

    glBindVertexArray(VAO);
//    glDrawArrays(GL_TRIANGLES,0,6);
//    glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); //用线条填充,查看边框

    glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,0); //从索引里拿数据,可以直接用&indices,但是不能绑定在使用 也可以靠VAO监控EBO
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

}

练习

练习一

1.通过添加多个顶点数据,使用glDrawArrays绘制两个挨在一起的三角形

#include "myopenglwidget.h"

//创建VBO和VAO对象,并赋予ID
unsigned int VBO,VAO,EBO;

float vertices[] = {
    -0.9f,-0.5f,0.0f,
    -0.0f,-0.5f,0.0f,
    -0.45f,0.5f,0.0f,

    0.0f,-0.5f,0.0f,
    0.9f,-0.5f,0.0f,
    0.45f,0.5f,0.0f,



};

unsigned int indices[] = {
    0,1,2,
    1,2,3
};
//顶点片段着色器
const char* vertexSharedSource = "#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";

unsigned int shaderProgram ;
unsigned int vertexShader;
unsigned int fragmentShader;

MyOpenGLWidget::MyOpenGLWidget(QWidget *parent) : QOpenGLWidget(parent)
{

}

void MyOpenGLWidget::initializeGL()
{
    initializeOpenGLFunctions(); //初始化OpenGL函数,将QT里的函数指针指向显卡的函数。

    //创建VBO和VAO对象,并赋予ID

    glGenVertexArrays(1,&VAO);
    glGenBuffers(1,&VBO);
    //绑定VBO和VAO对象
    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER,VBO);

    //为当前绑定到target的缓冲区对象创建一个新的数据存储
    //如果data不是NULL,则使用来自此指针的数据初始化数据存储
    glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);

    //告知显卡如何去解析缓冲区里的值
    //第0个属性里面3个值
    glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,3*sizeof(float),(void*)0);
    //开启VAO管理的第一个属性值。
    glEnableVertexAttribArray(0);

    //VAO VBO 进行休息。
//    glBindVertexArray(0); //解绑
    glBindBuffer(GL_ARRAY_BUFFER,0);


    //顶点着色器
    vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader,1,&vertexSharedSource,NULL);
    glCompileShader(vertexShader);

    //片段着色器shader
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader,1,&fragmentShaderSource,NULL);
    glCompileShader(fragmentShader); //编译程序

    //进行链接程序
    shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram,vertexShader);
    glAttachShader(shaderProgram,fragmentShader);
    glLinkProgram(shaderProgram);


    //EBO
    glGenBuffers(1,&EBO);
    //绑定VBO和VAO对象
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(indices),indices,GL_STATIC_DRAW);

    //EBO解绑,解绑之后数据会丢失
//    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);

}

void MyOpenGLWidget::resizeGL(int w, int h)
{

}

void MyOpenGLWidget::paintGL()
{
    //需要先初始化在使用
    glClearColor(0.2f,0.2f,0.2f,1.0f); //设置状态
    glClear(GL_COLOR_BUFFER_BIT); //使用状态

    glUseProgram(shaderProgram);

    glBindVertexArray(VAO);
    glDrawArrays(GL_TRIANGLES,0,6);
//    glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); //用线条填充,查看边框

//    glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,0); //从索引里拿数据,可以直接用&indices,但是不能绑定在使用 也可以靠VAO监控EBO
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

}

练习二

创建两个相同的三角形,但对他们的数据使用不同的VAO和VBO

#include "myopenglwidget.h"

//创建VBO和VAO对象,并赋予ID
unsigned int VBO[2],VAO[2],EBO;

float firstTriangle[] = {
    -0.9f,-0.5f,0.0f,
    -0.0f,-0.5f,0.0f,
    -0.45f,0.5f,0.0f

};

float secondTriangle[] = {

    0.0f,-0.5f,0.0f,
    0.9f,-0.5f,0.0f,
    0.45f,0.5f,0.0f
};


//顶点片段着色器
const char* vertexSharedSource = "#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";

unsigned int shaderProgram ;
unsigned int vertexShader;
unsigned int fragmentShader;

MyOpenGLWidget::MyOpenGLWidget(QWidget *parent) : QOpenGLWidget(parent)
{

}

MyOpenGLWidget::~MyOpenGLWidget()
{
    glDeleteVertexArrays(2,VAO);
}

void MyOpenGLWidget::initializeGL()
{
    initializeOpenGLFunctions(); //初始化OpenGL函数,将QT里的函数指针指向显卡的函数。

    //一次创建多个VBO和VAO对象
    glGenVertexArrays(2,VAO);
    glGenBuffers(2,VBO);

    //绑定VBO和VAO对象
    glBindVertexArray(VAO[0]);
    glBindBuffer(GL_ARRAY_BUFFER,VBO[0]);

    //为当前绑定到target的缓冲区对象创建一个新的数据存储
    //如果data不是NULL,则使用来自此指针的数据初始化数据存储
    glBufferData(GL_ARRAY_BUFFER,sizeof(firstTriangle),firstTriangle,GL_STATIC_DRAW);

    //告知显卡如何去解析缓冲区里的值
    //第0个属性里面3个值
    glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,3*sizeof(float),(void*)0);
    //开启VAO管理的第一个属性值。
    glEnableVertexAttribArray(0);//VAO[0]的第一个属性

    //绑定VBO和VAO对象
    glBindVertexArray(VAO[1]);
    glBindBuffer(GL_ARRAY_BUFFER,VBO[1]);

    //为当前绑定到target的缓冲区对象创建一个新的数据存储
    //如果data不是NULL,则使用来自此指针的数据初始化数据存储
    glBufferData(GL_ARRAY_BUFFER,sizeof(secondTriangle),secondTriangle,GL_STATIC_DRAW);

    //告知显卡如何去解析缓冲区里的值
    //第0个属性里面3个值
    glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,3*sizeof(float),(void*)0);
    //开启VAO管理的第一个属性值。
    glEnableVertexAttribArray(0);//VAO[1]的第一个属性


    //顶点着色器
    vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader,1,&vertexSharedSource,NULL);
    glCompileShader(vertexShader);

    //片段着色器shader
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader,1,&fragmentShaderSource,NULL);
    glCompileShader(fragmentShader); //编译程序

    //进行链接程序
    shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram,vertexShader);
    glAttachShader(shaderProgram,fragmentShader);
    glLinkProgram(shaderProgram);


    //EBO
//    glGenBuffers(1,&EBO);
    //绑定VBO和VAO对象
//    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);
//    glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(indices),indices,GL_STATIC_DRAW);

    //EBO解绑,解绑之后数据会丢失
//    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);

}

void MyOpenGLWidget::resizeGL(int w, int h)
{

}

void MyOpenGLWidget::paintGL()
{
    //需要先初始化在使用
    glClearColor(0.2f,0.2f,0.2f,1.0f); //设置状态
    glClear(GL_COLOR_BUFFER_BIT); //使用状态

    glUseProgram(shaderProgram);

    glBindVertexArray(VAO[0]);
    glDrawArrays(GL_TRIANGLES,0,3);

    glBindVertexArray(VAO[1]);
    glDrawArrays(GL_TRIANGLES,0,3);

    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

}

练习三

创建两个着色器程序,其中一个使用片段着色器输出黄色

#include "myopenglwidget.h"

//创建VBO和VAO对象,并赋予ID
unsigned int VBO[2],VAO[2],EBO;

float firstTriangle[] = {
    -0.9f,-0.5f,0.0f,
    -0.0f,-0.5f,0.0f,
    -0.45f,0.5f,0.0f

};

float secondTriangle[] = {

    0.0f,-0.5f,0.0f,
    0.9f,-0.5f,0.0f,
    0.45f,0.5f,0.0f
};


//顶点片段着色器
const char* vertexSharedSource = "#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";

const char* fragmentShader2Source = "#version 330 core\n"
                                   "out vec4 FragColor;\n"
                                   "void main()\n"
                                   "{\n"
                                   "FragColor = vec4(1.0f,1.0f,0.0f,1.0f);\n }\n";


unsigned int shaderProgram ,shaderProgram2;
unsigned int vertexShader;
unsigned int fragmentShader,fragmentShader2;

MyOpenGLWidget::MyOpenGLWidget(QWidget *parent) : QOpenGLWidget(parent)
{

}

MyOpenGLWidget::~MyOpenGLWidget()
{
    glDeleteVertexArrays(2,VAO);
}

void MyOpenGLWidget::initializeGL()
{
    initializeOpenGLFunctions(); //初始化OpenGL函数,将QT里的函数指针指向显卡的函数。

    //一次创建多个VBO和VAO对象
    glGenVertexArrays(2,VAO);
    glGenBuffers(2,VBO);

    //绑定VBO和VAO对象
    glBindVertexArray(VAO[0]);
    glBindBuffer(GL_ARRAY_BUFFER,VBO[0]);

    //为当前绑定到target的缓冲区对象创建一个新的数据存储
    //如果data不是NULL,则使用来自此指针的数据初始化数据存储
    glBufferData(GL_ARRAY_BUFFER,sizeof(firstTriangle),firstTriangle,GL_STATIC_DRAW);

    //告知显卡如何去解析缓冲区里的值
    //第0个属性里面3个值
    glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,3*sizeof(float),(void*)0);
    //开启VAO管理的第一个属性值。
    glEnableVertexAttribArray(0);//VAO[0]的第一个属性

    //绑定VBO和VAO对象
    glBindVertexArray(VAO[1]);
    glBindBuffer(GL_ARRAY_BUFFER,VBO[1]);

    //为当前绑定到target的缓冲区对象创建一个新的数据存储
    //如果data不是NULL,则使用来自此指针的数据初始化数据存储
    glBufferData(GL_ARRAY_BUFFER,sizeof(secondTriangle),secondTriangle,GL_STATIC_DRAW);

    //告知显卡如何去解析缓冲区里的值
    //第0个属性里面3个值
    glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,3*sizeof(float),(void*)0);
    //开启VAO管理的第一个属性值。
    glEnableVertexAttribArray(0);//VAO[1]的第一个属性


    //顶点着色器
    vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader,1,&vertexSharedSource,NULL);
    glCompileShader(vertexShader);

    //片段着色器shader
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader,1,&fragmentShaderSource,NULL);
    glCompileShader(fragmentShader); //编译程序

    fragmentShader2 = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader2,1,&fragmentShader2Source,NULL);
    glCompileShader(fragmentShader2); //编译程序

    //进行链接程序
    shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram,vertexShader);
    glAttachShader(shaderProgram,fragmentShader);
    glLinkProgram(shaderProgram);


    shaderProgram2 = glCreateProgram();
    glAttachShader(shaderProgram2,vertexShader);
    glAttachShader(shaderProgram2,fragmentShader2);
    glLinkProgram(shaderProgram2);

    //EBO
//    glGenBuffers(1,&EBO);
    //绑定VBO和VAO对象
//    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);
//    glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(indices),indices,GL_STATIC_DRAW);

    //EBO解绑,解绑之后数据会丢失
//    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);

}

void MyOpenGLWidget::resizeGL(int w, int h)
{

}

void MyOpenGLWidget::paintGL()
{
    //需要先初始化在使用
    glClearColor(0.2f,0.2f,0.2f,1.0f); //设置状态
    glClear(GL_COLOR_BUFFER_BIT); //使用状态

    glUseProgram(shaderProgram);

    glBindVertexArray(VAO[0]);
    glDrawArrays(GL_TRIANGLES,0,3);

    glUseProgram(shaderProgram2);
    glBindVertexArray(VAO[1]);
    glDrawArrays(GL_TRIANGLES,0,3);

    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);
    glDeleteShader(fragmentShader2);

}


网站公告

今日签到

点亮在社区的每一天
去签到