随笔 - 632  文章 - 17  评论 - 54  阅读 - 93万

QT+OpenGL 使用VAO、VBO、EBO结合绘制一个正方形

QT+OpenGL基础:

  1. QT+OpenGL创建一个三角形并动态改变三角形颜色
  2. OpenGL中的VAO、VBO、EBO
  3. QT+OpenGL 使用VAO、VBO、EBO结合绘制一个正方形
  4. QT+OpenGL使用一组顶点绘制两个三角形
  5. QT+OpenGL通过两个VAO来管理两个三角形
  6. QT+Opengl使用两个Shader绘制两个不同颜色的三角形
  7. QT+OpenGL从顶点着色器传递颜色数据给片元着色器
  8. QT+OpenGL简单纹理贴图
  9. QT+OpenGL纹理与颜色混合
  10. Qt+OpenGL混合两个纹理,并可以改变纹理透明度

一、概述

  需求:

    绘制一个正方形,可以控制正方形的颜色、可以切换正方形为线框模式/填充模式

  绘制流程:

    1.定义一个顶点着色器和片元着色器shader

    2.Qt创建一个Widget并继承QOpenGLWidget、QOpenGLFunctions,并重写initializeGL()、resizeGL(w,h)、paintGL()

    3.定义顶点坐标数组、元素索引数组、创建VAO、VBO、EBO并给其分配相应的内存

    4.告知显卡如何解析顶点

    5.创建shader、编译shader、关联shader、链接shader

    6.绑定VAO、使用program、绘制正方形

 

二、代码示例

    1.定义一个顶点着色器和片元着色器shader

      a.顶点着色器代码

#version 330 core
layout (location = 0) in vec3 aPos;
void main()
{
    gl_Position = vec4(aPos, 1.0);
}

      b.片元着色器代码

#version 330 core
out vec4 FragColor;
uniform vec4 ourColor;
void main()
{
    FragColor = ourColor;
}

    2.Qt创建一个Widget并继承QOpenGLWidget、QOpenGLFunctions,并重写initializeGL()、resizeGL(w,h)、paintGL()

复制代码
class GLSquareWindow : public QOpenGLWidget, protected QOpenGLFunctions_3_3_Core
{
    Q_OBJECT

public:
    GLSquareWindow(QWidget *parent = nullptr);
    ~GLSquareWindow();

protected:
    virtual void initializeGL();//初始化OpenGL
    virtual void resizeGL(int w, int h);//ResizeWindow大小
    virtual void paintGL();//绘制OpenGL
复制代码

    3.定义顶点坐标数组、元素索引数组、创建VAO、VBO、EBO并给其分配相应的内存

复制代码
//创建四边形的顶点
GLfloat vertices[] = {
    // 位置 
     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.0f, -0.5f, 0.0f,  // left
     //0.9f, -0.5f, 0.0f,  // right
     //0.45f, 0.5f, 0.0f   // top 
};

glGenVertexArrays(1, &VAO);//创建VAO:顶点数组对象
glGenBuffers(1, &VBO);//创建VBO:顶点数组缓冲

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

//把顶点数据放入缓冲区
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);

//EBO创建与绑定
glGenBuffers(1, &EBO);//EBO元素索引缓冲,用来指定顶点应该如何排列和绘制
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

复制代码

    4.告知显卡如何解析顶点

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

    5.创建shader、编译shader、关联shader、链接shader

复制代码
//创建顶点着色器
unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
QFile vertexShaderFile(":/QtForOpenCV4Tool/shader/square.vert");
if (!vertexShaderFile.open(QIODevice::ReadOnly)) {
    qDebug() << "Cannot open vertex shader file for reading";
}
QString verQStr = vertexShaderFile.readAll();
std::string verStdStr = verQStr.toStdString();
const char* vertexStr = verStdStr.c_str();
qDebug() << "vertexStr-------------" << vertexStr;
vertexShaderFile.close();
glShaderSource(vertexShader, 1, &vertexStr, NULL);
glCompileShader(vertexShader);
//创建片元着色器
QFile fragShaderFile(":/QtForOpenCV4Tool/shader/square.frag");
if (!fragShaderFile.open(QIODevice::ReadOnly)) {
    qDebug() << "Cannot open frag shader file for reading";
}
QString fragQStr = fragShaderFile.readAll();
std::string fragStdStr = fragQStr.toStdString();
const char* fragmentStr = fragStdStr.c_str();
qDebug() << "fragmentStr-------------" << fragmentStr;
unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentStr, NULL);
fragShaderFile.close();
glCompileShader(fragmentShader);

//创建program
programShaderNative = glCreateProgram();
//将着色器和显卡程序关联
glAttachShader(programShaderNative, vertexShader);
glAttachShader(programShaderNative, fragmentShader);
glLinkProgram(programShaderNative);//链接程序

//着色器使用后删除掉
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
复制代码

 

    6.绑定VAO、使用program、绘制正方形

复制代码
void GLSquareWindow::paintGL() {
    if (isFullMode) {//切换线框模式
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    }
    else {
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    }
    //原生绘制
    glUseProgram(programShaderNative);
    //找到ourColor的位置
    GLint colorLocation = glGetUniformLocation(programShaderNative, "ourColor");
    switch (mColor) {
    case SquareColor::RED2:
        glUniform4f(colorLocation, 1.0f, 0.0f, 0.0f, 1.0f);//给ourColor赋值
        break;
    case SquareColor::GREEN2:
        glUniform4f(colorLocation, 0.0f, 1.0f, 0.0f, 1.0f);//给ourColor赋值
        break;
    case SquareColor::BLUE2:
        glUniform4f(colorLocation, 0.0f, 0.0f, 1.0f, 1.0f);//给ourColor赋值
        break;
    }
    glBindVertexArray(VAO);//说明要使用VAO配置的顶点属性及对应的VBO及EBO
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, /*indices*/0);
}
复制代码

 

posted on   飘杨......  阅读(181)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
历史上的今天:
2023-08-21 EventBus源码再分析
2013-08-21 Android 导入工程文件引用包出错
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示