qt+opengl 着色器VAO、VBO、EBO(四)

文章目录

  • 一、顶点着色器和片段着色器代码分析
    • 1. 着色器1
    • 2. 顶点着色器2
  • 二、使用步骤
    • 1. 使用着色器1
    • 2. 使用着色器2
    • 3. 在着色器2中使用EBO
  • 三、完整代码


一、顶点着色器和片段着色器代码分析

1. 着色器1

用到的坐标矩阵, 四个四边形顶点坐标

float vertices_data[36] = {// 所有的值是在[-1, 1]之间的-0.5f, 0.4f, 0.0f,-0.5f, 0.2f, 0.0f,-0.3f, 0.2f, 0.0f,-0.3f, 0.4f, 0.0f,-0.1f, 0.4f, 0.0f,-0.1f, 0.2f, 0.0f,0.1f, 0.2f, 0.0f,0.1f, 0.4f, 0.0f,0.3f, 0.4f, 0.0f,0.3f, 0.2f, 0.0f,0.5f, 0.2f, 0.0f,0.5f, 0.4f, 0.0f
};

// 顶点着色器1

//! 1. "#version 450 core": 版本号; GLSL版本号要和OpenGL版本号匹配
//! 2. "layout(location = 0) in vec3 aPos;": 顶点属性;
//!     (1) glsl中,layout修饰符,(location = 0) 把顶点属性和特定缓冲区关联起来,并且顶点属性的识别号为0(创建顶点着色器处对比说明),
//!     (2) in:输入顶点属性
//!     (3) out:输出顶点属性
//!     (4) vec3是数据类型,三元组
//!     (5) aPos是定义的变量。即定义一个vec3类型变量aPos,将缓冲区0位置的顶点属性输入
//! 3. "gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0f);": 是GLSL的内建变量,会成为该顶点着色器的输出; 是一个4维向量(vec4),它包含了3个空间坐标(x, y, z)和齐次坐标(w), 通常将w设置为1.0
//! 4. "out vec4 FragColor":定义一个vec4变量FragColor, 并输出
//!
//! gl_Position设置的值会成为该顶点着色器的输出。由于我们的输入是一个3分量的向量,我们必须把它转换为4分量的向量(vec4)
//! 因为GLSL中没有一个3分量的向量的构造函数可以直接把一个vec3作为参数,所以我们必须先把vec3转换为vec4,然后再把它赋值给gl_Position
//! gl_Position 是一个vec4类型的输出变量,它会被转换为裁剪空间坐标
//! vec4是一个4维向量,它包含了3个空间坐标(x, y, z),还有一个齐次坐标(w), 通常将w设置为1.0
//! 裁剪空间坐标会被转换为屏幕空间坐标,同时也会被进行透视除法(Perspective Division) 除以w分量
//! 透视除法会将裁剪空间坐标的xyz分量分别除以w分量,最终得到的结果就是标准化设备坐标(Normalized Device Coordinates)
const char *vertexShaderSource ="#version 450 core\n""layout(location = 0) in vec3 aPos;\n""void main()\n""{\n""gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0f);\n""}\n\0";

//片段着色器1

const char *fragmentShaderSource ="#version 450 core\n""out vec4 FragColor;\n""void main()\n""{\n""FragColor = vec4(0.4f, 0.6f, 0.8f, 1.0f);\n""}\n\0";

2. 顶点着色器2

用到的矩阵:坐标矩阵(包含坐标和颜色)、索引矩阵

float vertices_data2[72] = {// 所有的值是在[-1, 1]之间的//坐标               //颜色-0.5f, -0.2f, 0.0f, 0.0f, 0.0f, 0.0f,-0.5f, -0.4f, 0.0f, 1.0f, 0.0f, 0.0f,-0.3f, -0.4f, 0.0f, 0.0f, 1.0f, 0.0f,-0.3f, -0.2f, 0.0f, 1.1f, 1.0f, 0.0f,-0.1f, -0.2f, 0.0f, 0.0f, 0.0f, 1.0f,-0.1f, -0.4f, 0.0f, 1.0f, 0.0f, 1.0f,0.1f, -0.4f, 0.0f, 0.0f, 1.0f, 1.0f,0.1f, -0.2f, 0.0f, 1.0f, 1.0f, 1.0f,0.3f, -0.2f, 0.0f, 0.0f, 0.0f, 0.0f,0.3f, -0.4f, 0.0f, 1.0f, 0.0f, 0.0f,0.5f, -0.4f, 0.0f, 0.0f, 1.0f, 0.0f,0.5f, -0.2f, 0.0f, 1.0f, 1.0f, 0.0f
};//控制绘制顺序
GLuint vertex_index[20] = {0, 1, 2, 3,2, 3, 4, 5,4, 5, 6, 7,6, 7, 8, 9,8, 9, 10,11
};//!

// 顶点着色器2
//! 顶点着色器从矩阵中读取颜色,通过"out vec3 mcolor;"输出给片段着色器
注意此处的layout(location = 0)和layout(location = 1),对应下文解析数据时的参数

const char *vertexShaderSource2 ="#version 450 core\n""layout(location = 0) in vec3 aPos;\n""layout(location = 1) in vec3 aColor;\n""out vec3 mcolor;\n""void main()\n""{\n""gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0f);\n""mcolor = aColor;\n""}\n\0";

//片段着色器2 接收顶点着色器输出的颜色

const char *fragmentShaderSource2 ="#version 450 core\n""out vec4 FragColor;\n""in vec3 mcolor;\n""void main()\n""{\n""FragColor = vec4(mcolor, 1.0f);\n""}\n\0";

二、使用步骤

1. 使用着色器1

void MOpenGLWidgetShader::initializeGL()
{initializeOpenGLFunctions();glClearColor(0.0, 0.2, 0.3, 1.0);// ------------------------一、VAO和VBO------------------------// 1.创建VAO和VBO对象,并赋予ID(使用Gen)glGenVertexArrays(1, &VAO_id);glGenBuffers(1, &VBO_id);// 2.绑定VAO,开始记录属性相关glBindVertexArray(VAO_id);// 3.绑定VBO(一定是先绑定VAO再绑定VBO)glBindBuffer(GL_ARRAY_BUFFER, VBO_id);// 4.把数据放进VBOglBufferData(GL_ARRAY_BUFFER, sizeof(vertices_data), vertices_data, GL_STATIC_DRAW);// 5.解析数据//! glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer)//! index 指定要配置的顶点属性的编号。//! size 指定每个顶点属性的分量数(1、2、3 或 4,就像向量的维度一样)。//! type 指定每个分量的数据类型,可以是 GL_BYTE、GL_UNSIGNED_BYTE、GL_SHORT、GL_UNSIGNED_SHORT、GL_INT、GL_UNSIGNED_INT、GL_FLOAT 或 GL_DOUBLE。//! normalized1 指定是否将数据归一化到 [0,1] 或 [-1,1] 范围内。//! stride (步长)指定连续两个顶点属性间的字节数。如果为 0,则表示顶点属性是紧密排列的。//! pointer 指向缓冲对象中第一个顶点属性的第一个分量的地址。(offset的作用)glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);// 6.开启location = 0的属性解析(就是上面顶点着色器处未说明的)glEnableVertexAttribArray(0);// 7.解绑VBO和VAO;  绑定一个ID为0,也就是不存在的ID,相当于接绑定(绑定新的ID,之前绑定的也就解除了)glBindBuffer(GL_ARRAY_BUFFER, 0);glBindVertexArray(0);// -----------------------------end---------------------------// ------------------------二、着色器相关------------------------// 1.创建顶点着色器unsigned int vertexShader_id = glCreateShader(GL_VERTEX_SHADER);glShaderSource(vertexShader_id, 1, &vertexShaderSource, NULL);glCompileShader(vertexShader_id);// 2.创建片段着色器unsigned int fragmentShader_id = glCreateShader(GL_FRAGMENT_SHADER);glShaderSource(fragmentShader_id, 1, &fragmentShaderSource, NULL);//编译代码glCompileShader(fragmentShader_id);// -----------------------------end---------------------------// -----------------------三、着色器程序相关----------------------shaderProgram1_id = glCreateProgram();glAttachShader(shaderProgram1_id, vertexShader_id);glAttachShader(shaderProgram1_id, fragmentShader_id);glLinkProgram(shaderProgram1_id);// -----------------------------end---------------------------// 删除顶点着色器和片段着色器(不能将着色器程序也给delete掉)glDeleteShader(vertexShader_id);glDeleteShader(fragmentShader_id);
}
void MOpenGLWidgetShader::paintGL()
{//清除屏幕glClear(GL_COLOR_BUFFER_BIT);// 【画一个图形时需要说使用哪个着色器】glUseProgram(shaderProgram1_id);// 使用时还需要再绑定一次glBindVertexArray(VAO_id);// 开始绘制//! GL_APICALL void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);//! first,从数组缓存中的哪一位开始绘制,一般为0。//! count,数组中顶点的数量。glPointSize(8);glDrawArrays(GL_POINTS, 0, 12);glDrawArrays(GL_QUADS, 0, 12);
}

结果如图

在这里插入图片描述

2. 使用着色器2

void MOpenGLWidgetShader::initializeGL()
{initializeOpenGLFunctions();glClearColor(0.0, 0.2, 0.3, 1.0);//***********************************************************************//***********************************************************************//!                          VAO2、VBO2、EBO2//***********************************************************************//***********************************************************************glGenVertexArrays(1, &VAO2_id);glBindVertexArray(VAO2_id);glGenBuffers(1, &VBO2_id);glBindBuffer(GL_ARRAY_BUFFER, VBO2_id);//    glGenBuffers(1, &EBO2_id);
//    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO2_id);//读取矩阵数据到VBO2glBufferData(GL_ARRAY_BUFFER, sizeof(vertices_data2), vertices_data2, GL_STATIC_DRAW);//! 告诉OpenGL该如何解析顶点数据(应用到逐个顶点属性上)。//! 参数1:要配置的顶点属性(layout(location = 0),故0),//! 参数2:指定顶点属性的大小(vec3,故3),//! 参数3:指定数据的类型,//! 参数4:是否希望数据被标准化,//! 参数5:在连续的顶点属性组之间的间隔,6*sizeof(float)//! 参数6:表示位置数据在缓冲中起始位置的偏移量(Offset),0*sizeof(float)。// 解析数据:按layout(location = 0)解析,每6位一组,每组偏移0处读取3位glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);//! 参数1:要配置的顶点属性(layout(location = 1),故1)//! 参数2:指定顶点属性的大小(vec3,故3),//! 参数3:指定数据的类型,//! 参数4:是否希望数据被标准化,//! 参数5:在连续的顶点属性组之间的间隔,//! 参数6:表示位置数据在缓冲中起始位置的偏移量(Offset), 3*sizeof(float)。// 解析数据:按layout(location = 1)解析,每6位一组,每组偏移3处读取3位glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3*sizeof(float)));glEnableVertexAttribArray(1);//    //加载索引矩阵数据; GL_ELEMENT_ARRAY_BUFFER
//    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(vertex_index), vertex_index, GL_STATIC_DRAW);glBindVertexArray(0);glBindBuffer(GL_ARRAY_BUFFER, 0);
//    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);// ------------------------二、着色器相关------------------------// 创建顶点着色器unsigned int vertexShader2_id = glCreateShader(GL_VERTEX_SHADER);glShaderSource(vertexShader2_id, 1, &vertexShaderSource2, NULL);glCompileShader(vertexShader2_id);// 创建片段着色器unsigned int fragmentShader2_id = glCreateShader(GL_FRAGMENT_SHADER);glShaderSource(fragmentShader2_id, 1, &fragmentShaderSource2, NULL);glCompileShader(fragmentShader2_id);//判断着顶点色器编译是否成功int success;char infoLog[512];glGetShaderiv(vertexShader2_id, GL_COMPILE_STATUS, &success);if(!success){glGetShaderInfoLog(vertexShader2_id, 512, NULL, infoLog);qDebug() << "ERROR::VERTEX::COMPILATION_FAILED\n" << infoLog;};//判断着片段色器编译是否成功glGetShaderiv(fragmentShader2_id, GL_COMPILE_STATUS, &success);if(!success){glGetShaderInfoLog(fragmentShader2_id, 512, NULL, infoLog);qDebug() << "ERROR::SHADER::COMPILATION_FAILED\n" << infoLog;};// -----------------------------end---------------------------// -----------------------三、着色器程序相关----------------------shaderProgram2_id = glCreateProgram();glAttachShader(shaderProgram2_id, vertexShader2_id);glAttachShader(shaderProgram2_id, fragmentShader2_id);glLinkProgram(shaderProgram2_id);//判断着片段色器编译是否成功glGetShaderiv(shaderProgram2_id, GL_LINK_STATUS, &success);if(!success){glGetShaderInfoLog(shaderProgram2_id, 512, NULL, infoLog);qDebug() << "ERROR::PROGRAM::LINKING_FAILED\n" << infoLog;};// -----------------------------end---------------------------// 删除顶点着色器和片段着色器(不能将着色器程序也给delete掉)glDeleteShader(vertexShader2_id);glDeleteShader(fragmentShader2_id);
}
void MOpenGLWidgetShader::paintGL()
{//清除屏幕glClear(GL_COLOR_BUFFER_BIT);// 【画一个图形时需要说使用哪个着色器】glUseProgram(shaderProgram2_id);// 使用时还需要再绑定一次glBindVertexArray(VAO2_id);// 开始绘制//! GL_APICALL void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);//! first,从数组缓存中的哪一位开始绘制,一般为0。//! count,数组中顶点的数量。glPointSize(8);glDrawArrays(GL_POINTS, 0, 12);glDrawArrays(GL_QUADS, 0, 12);
//    glDrawElements(GL_POINTS, 20, GL_UNSIGNED_INT, 0);
//    glDrawElements(GL_QUADS, 20, GL_UNSIGNED_INT, 0);
}

结果如图:

在这里插入图片描述

3. 在着色器2中使用EBO

将(二、2)中initializeGL()函数中被注释的如下代码取消注释:

glGenBuffers(1, &EBO2_id);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO2_id);......//加载索引矩阵数据; GL_ELEMENT_ARRAY_BUFFER
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(vertex_index), vertex_index, GL_STATIC_DRAW);...
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

将(二、2)中paintGL()函数的如下代码替换注释

    glDrawArrays(GL_POINTS, 0, 12);glDrawArrays(GL_QUADS, 0, 12);//! 绘图类型 索引矩阵中有20个索引, 索引数据类型是无符号整形
//    glDrawElements(GL_POINTS, 20, GL_UNSIGNED_INT, 0);
//    glDrawElements(GL_QUADS, 20, GL_UNSIGNED_INT, 0);

替换为

//    glDrawArrays(GL_POINTS, 0, 12);
//    glDrawArrays(GL_QUADS, 0, 12);//! 绘图类型 索引矩阵中有20个索引, 索引数据类型是无符号整形glDrawElements(GL_POINTS, 20, GL_UNSIGNED_INT, 0);glDrawElements(GL_QUADS, 20, GL_UNSIGNED_INT, 0);

结果如图

在这里插入图片描述

三、完整代码

#ifndef MOPENGLWIDGETSHADER_H
#define MOPENGLWIDGETSHADER_H#include <QObject>
#include <QWidget>
#include <GL/glu.h>
#include <QGL>
#include <QtOpenGL>
#include <QGLWidget>
#include <QOpenGLWidget>
#include <QOpenGLFunctions_4_5_Core>
#include <QGridLayout>
#include <QDebug>class MOpenGLWidgetShader : public QOpenGLWidget, QOpenGLFunctions_4_5_Core
{Q_OBJECT
public:explicit MOpenGLWidgetShader(QWidget* parent = nullptr);// 顶点的数据:没有解析的数据是没有意义的// 内存中的数据,关键是如何将内存中的数据给显卡float vertices_data[36] = {// 所有的值是在[-1, 1]之间的-0.5f, 0.4f, 0.0f,-0.5f, 0.2f, 0.0f,-0.3f, 0.2f, 0.0f,-0.3f, 0.4f, 0.0f,-0.1f, 0.4f, 0.0f,-0.1f, 0.2f, 0.0f,0.1f, 0.2f, 0.0f,0.1f, 0.4f, 0.0f,0.3f, 0.4f, 0.0f,0.3f, 0.2f, 0.0f,0.5f, 0.2f, 0.0f,0.5f, 0.4f, 0.0f};float vertices_data2[72] = {// 所有的值是在[-1, 1]之间的//坐标               //颜色-0.5f, -0.2f, 0.0f, 0.0f, 0.0f, 0.0f,-0.5f, -0.4f, 0.0f, 1.0f, 0.0f, 0.0f,-0.3f, -0.4f, 0.0f, 0.0f, 1.0f, 0.0f,-0.3f, -0.2f, 0.0f, 1.1f, 1.0f, 0.0f,-0.1f, -0.2f, 0.0f, 0.0f, 0.0f, 1.0f,-0.1f, -0.4f, 0.0f, 1.0f, 0.0f, 1.0f,0.1f, -0.4f, 0.0f, 0.0f, 1.0f, 1.0f,0.1f, -0.2f, 0.0f, 1.0f, 1.0f, 1.0f,0.3f, -0.2f, 0.0f, 0.0f, 0.0f, 0.0f,0.3f, -0.4f, 0.0f, 1.0f, 0.0f, 0.0f,0.5f, -0.4f, 0.0f, 0.0f, 1.0f, 0.0f,0.5f, -0.2f, 0.0f, 1.0f, 1.0f, 0.0f};//控制绘制顺序GLuint vertex_index[20] = {0, 1, 2, 3,2, 3, 4, 5,4, 5, 6, 7,6, 7, 8, 9,8, 9, 10,11};// VAO和VBO变量(无符号整型)unsigned int VAO_id,VBO_id;// 着色器变量unsigned int shaderProgram1_id;// VAO和VBO变量(无符号整型)、索引缓冲对象unsigned int VAO2_id,VBO2_id, EBO2_id;// 着色器变量unsigned int shaderProgram2_id;
public:protected:protected:virtual void initializeGL();virtual void resizeGL(int w, int h);virtual void paintGL();protected:virtual void mousePressEvent(QMouseEvent *event);virtual void mouseReleaseEvent(QMouseEvent *event);virtual void mouseMoveEvent(QMouseEvent *event);virtual void wheelEvent(QWheelEvent *event);
};#endif // MOPENGLWIDGETSHADER_H
#include "mopenglwidgetshader.h"//! 1. "#version 450 core": 版本号; GLSL版本号要和OpenGL版本号匹配
//! 2. "layout(location = 0) in vec3 aPos;": 顶点属性;
//!     (1) glsl中,layout修饰符,(location = 0) 把顶点属性和特定缓冲区关联起来,并且顶点属性的识别号为0(创建顶点着色器处对比说明),
//!     (2) in:输入顶点属性
//!     (3) out:输出顶点属性
//!     (4) vec3是数据类型,三元组
//!     (5) aPos是定义的变量。即定义一个vec3类型变量aPos,将缓冲区0位置的顶点属性输入
//! 3. "gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0f);": 是GLSL的内建变量,会成为该顶点着色器的输出; 是一个4维向量(vec4),它包含了3个空间坐标(x, y, z)和齐次坐标(w), 通常将w设置为1.0
//! 4. "out vec4 FragColor":定义一个vec4变量FragColor, 并输出
//!
//! gl_Position设置的值会成为该顶点着色器的输出。由于我们的输入是一个3分量的向量,我们必须把它转换为4分量的向量(vec4)
//! 因为GLSL中没有一个3分量的向量的构造函数可以直接把一个vec3作为参数,所以我们必须先把vec3转换为vec4,然后再把它赋值给gl_Position
//! gl_Position 是一个vec4类型的输出变量,它会被转换为裁剪空间坐标
//! vec4是一个4维向量,它包含了3个空间坐标(x, y, z),还有一个齐次坐标(w), 通常将w设置为1.0
//! 裁剪空间坐标会被转换为屏幕空间坐标,同时也会被进行透视除法(Perspective Division) 除以w分量
//! 透视除法会将裁剪空间坐标的xyz分量分别除以w分量,最终得到的结果就是标准化设备坐标(Normalized Device Coordinates)// 顶点着色器1
const char *vertexShaderSource ="#version 450 core\n""layout(location = 0) in vec3 aPos;\n""void main()\n""{\n""gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0f);\n""}\n\0";//片段着色器1
const char *fragmentShaderSource ="#version 450 core\n""out vec4 FragColor;\n""void main()\n""{\n""FragColor = vec4(0.4f, 0.6f, 0.8f, 1.0f);\n""}\n\0";//!
//! 顶点着色器从矩阵中读取颜色,通过"out vec3 mcolor;"输出给片段着色器
//! //!
// 顶点着色器2
const char *vertexShaderSource2 ="#version 450 core\n""layout(location = 0) in vec3 aPos;\n""layout(location = 1) in vec3 aColor;\n""out vec3 mcolor;\n""void main()\n""{\n""gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0f);\n""mcolor = aColor;\n""}\n\0";//片段着色器2
const char *fragmentShaderSource2 ="#version 450 core\n""out vec4 FragColor;\n""in vec3 mcolor;\n""void main()\n""{\n""FragColor = vec4(mcolor, 1.0f);\n""}\n\0";MOpenGLWidgetShader::MOpenGLWidgetShader(QWidget *parent): QOpenGLWidget{parent}
{}void MOpenGLWidgetShader::initializeGL()
{initializeOpenGLFunctions();glClearColor(0.0, 0.2, 0.3, 1.0);// ------------------------一、VAO和VBO------------------------// 1.创建VAO和VBO对象,并赋予ID(使用Gen)glGenVertexArrays(1, &VAO_id);glGenBuffers(1, &VBO_id);// 2.绑定VAO,开始记录属性相关glBindVertexArray(VAO_id);// 3.绑定VBO(一定是先绑定VAO再绑定VBO)glBindBuffer(GL_ARRAY_BUFFER, VBO_id);// 4.把数据放进VBOglBufferData(GL_ARRAY_BUFFER, sizeof(vertices_data), vertices_data, GL_STATIC_DRAW);// 5.解析数据//! glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer)//! index 指定要配置的顶点属性的编号。//! size 指定每个顶点属性的分量数(1、2、3 或 4,就像向量的维度一样)。//! type 指定每个分量的数据类型,可以是 GL_BYTE、GL_UNSIGNED_BYTE、GL_SHORT、GL_UNSIGNED_SHORT、GL_INT、GL_UNSIGNED_INT、GL_FLOAT 或 GL_DOUBLE。//! normalized1 指定是否将数据归一化到 [0,1] 或 [-1,1] 范围内。//! stride (步长)指定连续两个顶点属性间的字节数。如果为 0,则表示顶点属性是紧密排列的。//! pointer 指向缓冲对象中第一个顶点属性的第一个分量的地址。(offset的作用)glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);// 6.开启location = 0的属性解析(就是上面顶点着色器处未说明的)glEnableVertexAttribArray(0);// 7.解绑VBO和VAO;  绑定一个ID为0,也就是不存在的ID,相当于接绑定(绑定新的ID,之前绑定的也就解除了)glBindBuffer(GL_ARRAY_BUFFER, 0);glBindVertexArray(0);// -----------------------------end---------------------------// ------------------------二、着色器相关------------------------// 1.创建顶点着色器unsigned int vertexShader_id = glCreateShader(GL_VERTEX_SHADER);glShaderSource(vertexShader_id, 1, &vertexShaderSource, NULL);glCompileShader(vertexShader_id);// 2.创建片段着色器unsigned int fragmentShader_id = glCreateShader(GL_FRAGMENT_SHADER);glShaderSource(fragmentShader_id, 1, &fragmentShaderSource, NULL);//编译代码glCompileShader(fragmentShader_id);// -----------------------------end---------------------------// -----------------------三、着色器程序相关----------------------shaderProgram1_id = glCreateProgram();glAttachShader(shaderProgram1_id, vertexShader_id);glAttachShader(shaderProgram1_id, fragmentShader_id);glLinkProgram(shaderProgram1_id);// -----------------------------end---------------------------// 删除顶点着色器和片段着色器(不能将着色器程序也给delete掉)glDeleteShader(vertexShader_id);glDeleteShader(fragmentShader_id);//***********************************************************************//***********************************************************************//!                          VAO2、VBO2、EBO2//***********************************************************************//***********************************************************************glGenVertexArrays(1, &VAO2_id);glBindVertexArray(VAO2_id);glGenBuffers(1, &VBO2_id);glBindBuffer(GL_ARRAY_BUFFER, VBO2_id);glGenBuffers(1, &EBO2_id);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO2_id);//读取矩阵数据到VBO2glBufferData(GL_ARRAY_BUFFER, sizeof(vertices_data2), vertices_data2, GL_STATIC_DRAW);//! 告诉OpenGL该如何解析顶点数据(应用到逐个顶点属性上)。//! 参数1:要配置的顶点属性(layout(location = 0),故0),//! 参数2:指定顶点属性的大小(vec3,故3),//! 参数3:指定数据的类型,//! 参数4:是否希望数据被标准化,//! 参数5:在连续的顶点属性组之间的间隔,6*sizeof(float)//! 参数6:表示位置数据在缓冲中起始位置的偏移量(Offset),0*sizeof(float)。// 解析数据:按layout(location = 0)解析,每6位一组,每组偏移0处读取3位glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);//! 参数1:要配置的顶点属性(layout(location = 1),故1)//! 参数2:指定顶点属性的大小(vec3,故3),//! 参数3:指定数据的类型,//! 参数4:是否希望数据被标准化,//! 参数5:在连续的顶点属性组之间的间隔,//! 参数6:表示位置数据在缓冲中起始位置的偏移量(Offset), 3*sizeof(float)。// 解析数据:按layout(location = 1)解析,每6位一组,每组偏移3处读取3位glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3*sizeof(float)));glEnableVertexAttribArray(1);//加载索引矩阵数据; GL_ELEMENT_ARRAY_BUFFERglBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(vertex_index), vertex_index, GL_STATIC_DRAW);glBindVertexArray(0);glBindBuffer(GL_ARRAY_BUFFER, 0);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);// ------------------------二、着色器相关------------------------// 创建顶点着色器unsigned int vertexShader2_id = glCreateShader(GL_VERTEX_SHADER);glShaderSource(vertexShader2_id, 1, &vertexShaderSource2, NULL);glCompileShader(vertexShader2_id);// 创建片段着色器unsigned int fragmentShader2_id = glCreateShader(GL_FRAGMENT_SHADER);glShaderSource(fragmentShader2_id, 1, &fragmentShaderSource2, NULL);glCompileShader(fragmentShader2_id);//判断着顶点色器编译是否成功int success;char infoLog[512];glGetShaderiv(vertexShader2_id, GL_COMPILE_STATUS, &success);if(!success){glGetShaderInfoLog(vertexShader2_id, 512, NULL, infoLog);qDebug() << "ERROR::VERTEX::COMPILATION_FAILED\n" << infoLog;};//判断着片段色器编译是否成功glGetShaderiv(fragmentShader2_id, GL_COMPILE_STATUS, &success);if(!success){glGetShaderInfoLog(fragmentShader2_id, 512, NULL, infoLog);qDebug() << "ERROR::SHADER::COMPILATION_FAILED\n" << infoLog;};// -----------------------------end---------------------------// -----------------------三、着色器程序相关----------------------shaderProgram2_id = glCreateProgram();glAttachShader(shaderProgram2_id, vertexShader2_id);glAttachShader(shaderProgram2_id, fragmentShader2_id);glLinkProgram(shaderProgram2_id);//判断着片段色器编译是否成功glGetShaderiv(shaderProgram2_id, GL_LINK_STATUS, &success);if(!success){glGetShaderInfoLog(shaderProgram2_id, 512, NULL, infoLog);qDebug() << "ERROR::PROGRAM::LINKING_FAILED\n" << infoLog;};// -----------------------------end---------------------------// 删除顶点着色器和片段着色器(不能将着色器程序也给delete掉)glDeleteShader(vertexShader2_id);glDeleteShader(fragmentShader2_id);}void MOpenGLWidgetShader::resizeGL(int w, int h)
{//防止height为0if (h == 0) { h = 1; }//重置当前的视口glViewport(0, 0,(GLint)w, (GLint)h);}void MOpenGLWidgetShader::paintGL()
{//清除屏幕glClear(GL_COLOR_BUFFER_BIT);// 【画一个图形时需要说使用哪个着色器】glUseProgram(shaderProgram2_id);// 使用时还需要再绑定一次glBindVertexArray(VAO2_id);// 开始绘制//! GL_APICALL void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);//! first,从数组缓存中的哪一位开始绘制,一般为0。//! count,数组中顶点的数量。glPointSize(8);
//    glDrawArrays(GL_POINTS, 0, 12);
//    glDrawArrays(GL_QUADS, 0, 12);//! 绘图类型 索引矩阵中有20个索引, 索引数据类型是无符号整形glDrawElements(GL_POINTS, 20, GL_UNSIGNED_INT, 0);glDrawElements(GL_QUADS, 20, GL_UNSIGNED_INT, 0);
}void MOpenGLWidgetShader::wheelEvent(QWheelEvent *event)
{QOpenGLWidget::wheelEvent(event);}void MOpenGLWidgetShader::mousePressEvent(QMouseEvent *event)
{QOpenGLWidget::mousePressEvent(event);}void  MOpenGLWidgetShader::mouseReleaseEvent(QMouseEvent *event)
{QOpenGLWidget::mouseReleaseEvent(event);
}void MOpenGLWidgetShader::mouseMoveEvent(QMouseEvent *event)
{QOpenGLWidget::mouseMoveEvent(event);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/144178.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mybatis之主键返回

1.在mybatis的xml中加入 <insert id"insertUser" keyProperty"id" useGeneratedKeys"true" parameterType"com.UserAndOrder"> insert into Tuser(userName,passWord) values (#{userName},#{passWord} ) </insert&…

多维时序 | MATLAB实现PSO-BiLSTM-Attention粒子群优化双向长短期记忆神经网络融合注意力机制的多变量时间序列预测

多维时序 | MATLAB实现PSO-BiLSTM-Attention粒子群优化双向长短期记忆神经网络融合注意力机制的多变量时间序列预测 目录 多维时序 | MATLAB实现PSO-BiLSTM-Attention粒子群优化双向长短期记忆神经网络融合注意力机制的多变量时间序列预测预测效果基本介绍模型描述程序设计参考…

国产高云FPGA开发软件Gowin的下载、安装、Licence共享,按照我的方案保证立马能用,不能用你铲我耳屎

目录 1、前言2、GOWIN简介3、GOWIN下载4、GOWIN安装5、Licence共享方案&#xff0c;立马就能用6、网盘福利领取 1、前言 “苟利国家生死以&#xff0c;岂因祸福避趋之&#xff01;”大洋彼岸的我优秀地下档员&#xff0c;敏锐地洞察到祖国的短板在于高精尖半导体的制造领域&am…

WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!

WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! 解决方案 解决方案 ssh-keygen -f "/home/oyk/.ssh/known_hosts" -R "[192.168.30.125]:6004"再重连就行

使用IDEA 将Eclipse java工程转为maven格式

使用IDEA 将Eclipse java工程转为maven格式 ①使用idea打开项目&#xff0c;在项目根目录下右键选择 Add Framework Support 选择 maven &#xff0c;引入maven ②找到项目中的.classpath文件或者lib目录 根据.classpath文件或者lib目录中列举的jar包名&#xff0c;将其依次手…

Redis 配置文件信息中文翻译版

前言 Redis 配置文件信息中文翻译版&#xff0c;方便大家阅读和理解对应参数信息及配置参数信息 # Redis configuration file example# Note on units: when memory size is needed, it is possible to specify # it in the usual form of 1k 5GB 4M and so forth: # 注意:当…

信息检索与数据挖掘 | 【实验】检索评价指标MAP、MRR、NDCG

文章目录 &#x1f4da;实验内容&#x1f4da;知识梳理&#x1f4da;实验步骤&#x1f407;前情提要&#x1f407;MAP评价指标函数&#x1f407;MRR 评价指标函数&#x1f407;NDCG评价指标函数&#x1f407;调试结果 &#x1f4da;实验内容 实现以下指标评价&#xff0c;并对…

锐捷EG易网关login.php以及其后台cli.php/branch_passw.php RCE漏洞复现 [附POC]

文章目录 锐捷EG易网关login.php以及其后台cli.php/branch_passw.php远程代码执行漏洞复现 [附POC]0x01 前言0x02 漏洞描述0x03 影响版本0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现 锐捷EG易网关login.php以及其后台cli.php/branch_passw.php远程代码执行漏洞复…

【Java 进阶篇】JQuery 案例:下拉列表选中条目左右移动,打破选择的边界

在前端的舞台上&#xff0c;下拉列表是常见的用户交互元素&#xff0c;但有时候我们想要更多的交互体验。通过巧妙运用 JQuery&#xff0c;我们可以实现下拉列表中选中条目的左右移动功能&#xff0c;为用户提供更加灵活的选择方式。本篇博客将深入研究 JQuery 中实现这一功能的…

操作系统(二 )| 进程控制 进程状态 进程描述 进程控制 进程同步互斥

文章目录 1 进程和程序区别2 进程状态2.1 进程的5种基本状态2.2 进程状态之间转换2.3 七状态模型 3 进程描述3.1 进程控制块 PCB3.2 进程块组织方式 4 进程控制5 进程同步 互斥5.1 区分进程互斥和同步5.2 核心方案5.3 其他方案方案1 设置锁变量方案2 严格轮转法方案3 Peterson解…

post 和get参数 请求

json参数 post请求格式 RestController public class HelloController { //json参数 post 请求RequestMapping("/jsonParam")public String jsonParam(RequestBody User user){System.out.println(user);return "OK";} } postman 接口测试工具…

服务器数据恢复—服务器发生故障导致数据丢失如何恢复服务器数据?

服务器常见故障&#xff1a; 硬件故障&#xff1a;磁盘、板卡、电源故障等。 软件故障&#xff1a;操作系统崩溃、程序运行错误等。 入侵破坏&#xff1a;加密、删除服务数据等。 不可控力&#xff1a;浸水、火烧、倒塌等。 误操作&#xff1a;格式化、删除、覆盖等。 如何减少…

从零搭建微服务架构:Spring Boot与Nacos完美整合

&#x1f38f;&#xff1a;你只管努力&#xff0c;剩下的交给时间 &#x1f3e0; &#xff1a;小破站 从零搭建微服务架构&#xff1a;Spring Boot与Nacos完美整合 前言第一&#xff1a;服务注册与发现第二&#xff1a;配置中心第三&#xff1a;报错问题解决第四&#xff1a;什…

继承、多态

复习 需求&#xff1a; 编写一个抽象类&#xff1a;职员Employee,其中定义showSalary(int s)抽象方法&#xff1b;编写Employee的子类&#xff0c;分别是销售员Sales和经理Manager,分别在子类中实现对父类抽象方法的重写&#xff0c;并编写测试类Test查看输出结果 package cn.…

某头部通信企业:SDLC+模糊测试,保障数实融合安全发展

某头部通信企业是全球领先的综合通信信息解决方案提供商&#xff0c;为全球电信运营商、政企客户和消费者提供创新的技术与产品解决方案。该企业持续关注核心技术攻关&#xff0c;深入打造系列化标杆项目和价值场景&#xff0c;加强数字化平台的推广应用&#xff0c;加快共建开…

【机器学习基础】多元线性回归(适合初学者的保姆级文章)

&#x1f680;个人主页&#xff1a;为梦而生~ 关注我一起学习吧&#xff01; &#x1f4a1;专栏&#xff1a;机器学习 欢迎订阅&#xff01;后面的内容会越来越有意思~ &#x1f4a1;往期推荐&#xff1a; 【机器学习基础】机器学习入门&#xff08;1&#xff09; 【机器学习基…

FreeSWITCH案例跟踪之一,sip bye发不出去

报故障的说&#xff0c;网关呼叫fs&#xff0c;网关收不到fs的sip bye Wireshark看call-flow, 是这样的&#xff1a; INVITE里面的contact是<sip:172.23.4.109:5060;transporttcp> 于是Wireshark设置过滤条件为ip.addr 172.23.4.109 and tcp.port 5060 fs tcp连网关被…

【前端】使用json-server报错

当我们使用json-server模仿后端接口时需要运行json-server --watch index.json这个命令生成增删改查接口但是可能会报这个错误&#xff0c;如图 这时我们运行 npm i json-server -g命令即可&#xff0c;然后再重新运行json-server --watch index.json就行了

基于SSM的校园家教兼职信息交流平台设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

深入探索 Django Channels

概要 随着 Web 应用的发展&#xff0c;实时功能如即时消息、实时通知等变得越来越重要。Django Channels 是 Django 的一个扩展&#xff0c;它使得在 Django 中构建实时功能变得可能。本文将深入探讨 Django Channels 的核心概念、架构以及如何实现一个实时应用。 1. Django C…