当前位置: 首页 > news >正文

QT之openGL使用(一)

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);}

http://www.dtcms.com/a/284192.html

相关文章:

  • 燕之屋打造多元化产品组合,引领行业迈向高质量发展新里程
  • 心通达OA知识管理平台:高效解决单位知识管理难题
  • 点晴模切ERP帮忙模切行业向数智化管理转型
  • Rocky Linux 9 源码包安装php7
  • 如何通过mac的前24bit,模糊确认是那一台什么样的设备
  • macOS 字体管理全攻略:如何查看已安装字体及常见字体格式区
  • 从基础到实战:.NET 反射机制的进阶用法与最佳实践
  • Tekla多部门协作,授权资源如何共享与调度?
  • 暑期算法训练.3
  • day29:零基础学嵌入式之线程1.0
  • HTML 极简个人介绍卡片(侧重语义化标签和响应式布局)
  • pytorch小记(三十二):深度解析 PyTorch 的 `torch.remainder`:向下取整余数运算
  • 【web安全】DVWA存储型XSS分析与利用
  • 第6天| openGauss中用户一次只能连接到一个数据库,没法访问其他数据库的对象
  • arping(ARP协议网络测试工具)
  • 【实时Linux实战系列】实时系统的安全性架构
  • MySQL如何解决事务并发的幻读问题
  • 从单线程到云原生:Redis 二十年演进全景与内在机理深剖
  • RuoYi-Cloud 定制微服务
  • 宝塔申请证书错误,提示 module ‘OpenSSL.crypto‘ has no attribute ‘sign‘
  • 有痛呻吟!!!
  • 09-three.js Materials
  • 任务4.1 谁做的好事
  • Nginx/OpenResty HTTP 请求处理阶段与 Lua 实践全解20250717
  • Python包测试全攻略:从单元测试到持续集成
  • Rabbitmq Direct Exchange(直连交换机)多个消费者,配置相同的key ,队列,可以保证只有一个消费者消费吗
  • 生成式AI干预下的认知依赖与批判性思维发展:基于ChatGPT辅助写作的纵向追踪
  • stl-string模拟
  • [NIPST AI]对抗性机器学习攻击和缓解的分类和术语
  • 【机器学习【7】】数据预处理:数据准备、数据转换、数据输出