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对象,并赋予IDglGenVertexArrays(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对象,并赋予IDglGenVertexArrays(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);//片段着色器shaderfragmentShader = 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对象,并赋予IDglGenVertexArrays(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);//片段着色器shaderfragmentShader = 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对象,并赋予IDglGenVertexArrays(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);//片段着色器shaderfragmentShader = glCreateShader(GL_FRAGMENT_SHADER);glShaderSource(fragmentShader,1,&fragmentShaderSource,NULL);glCompileShader(fragmentShader); //编译程序//进行链接程序shaderProgram = glCreateProgram();glAttachShader(shaderProgram,vertexShader);glAttachShader(shaderProgram,fragmentShader);glLinkProgram(shaderProgram);//EBOglGenBuffers(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监控EBOglDeleteShader(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对象,并赋予IDglGenVertexArrays(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);//片段着色器shaderfragmentShader = glCreateShader(GL_FRAGMENT_SHADER);glShaderSource(fragmentShader,1,&fragmentShaderSource,NULL);glCompileShader(fragmentShader); //编译程序//进行链接程序shaderProgram = glCreateProgram();glAttachShader(shaderProgram,vertexShader);glAttachShader(shaderProgram,fragmentShader);glLinkProgram(shaderProgram);//EBOglGenBuffers(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监控EBOglDeleteShader(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);//片段着色器shaderfragmentShader = 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);//片段着色器shaderfragmentShader = 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);}