首页 > 其他分享 >Qt+OpengGL使用教程(3)绘制矩形

Qt+OpengGL使用教程(3)绘制矩形

时间:2023-03-20 16:23:04浏览次数:60  
标签:GLWidget 教程 Qt ebo 0.5 program OpengGL 顶点 GL

Qt+OpengGL使用教程(2)中我们绘制了三角形,接下来我们需要使用qt的API绘制一个矩形,同时参考和对照:LearnOpenGL (3) 绘制矩形

一、准备工作

元素缓冲对象(EBO)

 

二、绘制矩形

我们使用两个三角形组成一个矩形。

为什么使用元素缓冲对象?

 

定义矩形的四个顶点

float 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   // 左上角
};

 

定义索引数组

unsigned int indices[] = {
    // 注意索引从0开始! 
    // 此例的索引(0,1,2,3)就是顶点数组vertices的下标,
    // 这样可以由下标代表顶点组合成矩形

    0, 1, 3, // 第一个三角形
    1, 2, 3  // 第二个三角形
};

 

创建元素缓冲对象

同创建顶点缓冲对象流程相同。

// 创建元素缓冲对象,
m_ebo = new QOpenGLBuffer(QOpenGLBuffer::IndexBuffer);
m_ebo->create();
m_ebo->bind();
// 分配显存大小,并搬运至显存
m_ebo->allocate(indices, sizeof(indices));

 

渲染循环

我们传递了GL_ELEMENT_ARRAY_BUFFER当作缓冲目标。最后一件要做的事是用glDrawElements来替换glDrawArrays函数,表示我们要从索引缓冲区渲染三角形。使用glDrawElements时,我们会使用当前绑定的索引缓冲对象中的索引进行绘制:

glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

 

结果如下:

完整代码如下:

查看代码
 //glwidget.h
#ifndef GLWIDGET_H
#define GLWIDGET_H

#include <QOpenGLWidget>
#include <QOpenGLExtraFunctions>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLBuffer>
#include <QOpenGLShader>
#include <QOpenGLShaderProgram>

class GLWidget : public QOpenGLWidget, protected QOpenGLFunctions
{
public:
    explicit GLWidget(QWidget *parent = nullptr);
    ~GLWidget();

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

private:
    QOpenGLVertexArrayObject *m_vao;    //顶点数组对象
    QOpenGLBuffer *m_vbo;               //顶点缓冲对象
    QOpenGLBuffer *m_ebo;               //元素缓冲对象
    QOpenGLShader *m_vshader;           //顶点着色器
    QOpenGLShader *m_fshader;           //片段着色器
    QOpenGLShaderProgram *m_program;    //着色器程序对象

};

#endif // GLWIDGET_H


//glwidget.cpp
#include "glwidget.h"
#include <QDebug>
float 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   // 左上角
};
unsigned int indices[] = {
    // 注意索引从0开始!
    // 此例的索引(0,1,2,3)就是顶点数组vertices的下标,
    // 这样可以由下标代表顶点组合成矩形
    0, 1, 3, // 第一个三角形
    1, 2, 3  // 第二个三角形
};

const char *vertexShaderSource =
    "#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"
    "} \0";


GLWidget::GLWidget(QWidget *parent) : QOpenGLWidget(parent)
{
    makeCurrent();

}

GLWidget::~GLWidget()
{
    if (m_program == nullptr) { return; }
    makeCurrent();
    delete m_program;
    delete m_vshader;
    delete m_fshader;
    m_vbo->destroy();
    m_vao->destroy();
    doneCurrent();
}

//设置OpenGL视口、投影等。每当窗口部件被调整大小时调用(也在第一次显示时调用,因为所有新创建的窗口部件都自动获得调整大小事件)。
void GLWidget::resizeGL(int w, int h)
{

}

//设置OpenGL资源和状态。在第一次调用resizeGL()或paintGL()之前调用一次。
void GLWidget::initializeGL()
{
    initializeOpenGLFunctions();
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);// 设置清屏颜色
    glEnable(GL_DEPTH_TEST);    // 启用深度测试
    glEnable(GL_COLOR_BUFFER_BIT);  // 启用颜色缓冲区

    // 创建顶点着色器对象,并编译
    m_vshader = new QOpenGLShader(QOpenGLShader::Vertex);
    m_vshader->compileSourceCode(vertexShaderSource);
    // 创建片段着色器对象,并编译
    m_fshader = new QOpenGLShader(QOpenGLShader::Fragment);
    m_fshader->compileSourceCode(fragmentShaderSource);
    // 创建着色器程序对象,添加顶点着色器和片段着色器,并链接它们
    m_program = new QOpenGLShaderProgram;
    m_program->addShader(m_vshader);
    m_program->addShader(m_fshader);
    m_program->link();
    // 创建顶点数组对象,并绑定到当前上下文
    m_vao = new QOpenGLVertexArrayObject;
    m_vao->create();
    QOpenGLVertexArrayObject::Binder vaoBinder(m_vao);
    // 创建顶点缓冲对象,
    m_vbo = new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer);
    m_vbo->create();
    m_vbo->bind();
    // 分配显存大小,并搬运至显存
    m_vbo->allocate(vertices, sizeof(vertices));
    // 链接顶点属性
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);
    // 顶点属性默认是禁用的,启用顶点属性0(location=0)
    m_program->enableAttributeArray(0);
    // 创建元素缓冲对象,
    m_ebo = new QOpenGLBuffer(QOpenGLBuffer::IndexBuffer);
    m_ebo->create();
    m_ebo->bind();
    // 分配显存大小,并搬运至显存
    m_ebo->allocate(indices, sizeof(indices));

    m_vao->release();
    m_vbo->release();
    // VAO还在使用时,不能释放EBO
}

//渲染OpenGL场景。每当窗口部件需要更新时调用。
void GLWidget::paintGL()
{
    // 清空颜色缓冲区和深度缓冲区
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // 绘制图形
    // 绑定着色器程序至当前上下文,相当于调用glUseProgram()
    m_program->bind();
    // 绑定VAO,调用设置的一组状态
    QOpenGLVertexArrayObject::Binder vaoBinder(m_vao);
    // 绘制三角形
//    glDrawArrays(GL_TRIANGLES, 0, 3);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    m_program->release();
    // 交换缓存
    auto *context = QOpenGLContext::currentContext();
    context->swapBuffers(context->surface());
    //使用swapBuffers后,必须调用makeCurrent后才能使用其他OpenGL函数。
    makeCurrent();
}

 

标签:GLWidget,教程,Qt,ebo,0.5,program,OpengGL,顶点,GL
From: https://www.cnblogs.com/errorman/p/17236724.html

相关文章

  • Blender材质贴图入门图文教程
    推荐:将 ​​NSDT场景编辑器​​ 加入你的3D开发工具链大家好,今天跟大家分享Blender材质贴图入门图文教程,一套blender的PBR材质包,和HDRI环境纹理贴图,在文末领取,希望能助到......
  • 超简单的Matlab2022b软件切换中/英文界面方法教程(附软件下载)
    在中文Windows操作系统中,MATLAB2015b之后版本安装默认为中文版,但有部分用户还是习惯使用英文界面下的MATLAB(个人偏好),下面以R2022b版分享一下中/英文界面的切换方法,超简单。......
  • Microsoft Access教程_编程入门自学教程_菜鸟教程-免费教程分享
    教程简介IT宝库整理的初学者MSAccess教程-从简单和简单的步骤学习MSAccess,从基本到高级概念,包括概述,RDBMS,对象,创建数据库,表,查询,关系,表单,数据类型,添加,查询,分组,汇总等示......
  • 跟老杜手撕Spring6教程(十)set注入专题-1
    set注入专题本篇文章是set注入专题,上篇说了构造注入​​https://blog.51cto.com/u_15485663/6132498​​配合视频教程观看,更易理解吸收,动力节点老杜的Spring6教程采用难度逐......
  • Qt 时间戳和时间相关的转换操作
    chatgpt1.获取时间戳#include<QDateTime>#include<QDebug>qint64timestamp=QDateTime::currentDateTime().toSecsSinceEpoch();qDebug()<<"当前时间戳:"<<ti......
  • Qt Json 处理
    chatgpt#include<QJsonDocument>#include<QJsonObject>#include<QDebug>//从JSON字符串中解析数据voidparseJson(constQString&jsonString){//将JS......
  • Qt5.12实战之QByteArray数据转换处理
    效果:视频:​​https://www.kuaishou.com/short-video/3xje8ib9gj68u52?authorId=3x8b3wqc6r8q766&streamSource=profile&area=profilexxnull​​示例源码:#include<QCo......
  • Qt5.12实战之基本数据类型
    注:macosx下要加上#include<QIODevice>//formacosxendl替换为Qt::endl;示例源码:#include<QCoreApplication>#include<QDebug>#include<QTextStream>stat......
  • 免费服务器申请教程
    福音虚拟主机永久免费使用了我一直想有一个属于自己的网站,但是苦于是新手,又不想花钱去买服务器。主要是怕买了不会用,就浪费掉了。诸多的机缘巧合下我知道了这个网站。随后......
  • Mac安装office2021套件 Mac原生版本教程(支持M1M2系列和Intel处理器)
    支持Mac的原生版本office2021来了,更新后的Mac原生版office2021适配了AppleM系列的处理器,运行速度提升更快、效率更高~office2021Mac原生激活版本Office2021Mac中文激......