学习OpenGL(五):QML纹理加载

本系列文章主要是记录学习OpenGL的过程,旨在驱动学习理解OpenGL,最终达到能够使用相关接口解决实际项目问题,学习流程参考《LearnOpenGL》。主要展现形式是"代码示例+接口分析"的形式,编码主要是基于Qt封装的OpenGL模块展开,这样对于我来说更加熟悉。

引言

前一章讲过了使用QOpenGLWidget进行纹理的加载,在QML下则需要其他方式实现,效果如下:
在这里插入图片描述

核心代码

void FrameBufferRenderer::render()
{
    // 背景颜色
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    m_shaderProgram.bind();

    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    m_wallTexture->bind();

    // 设定顶点属性指针
    glVertexAttribPointer(0 ,3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    glVertexAttribPointer(1 ,2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);

    // 绘制
    glDrawElements(GL_POLYGON, 4, GL_UNSIGNED_INT, nullptr);

    m_shaderProgram.release();
}

主要就是将原本的QOpenGLWidget中的paintGL代码,迁移到QQuickFramebufferObject::Renderer中的render函数中,其他的初始化可以放入构造函数中完成。

这里需要使用到两个对象QQuickFramebufferObject以及QQuickFramebufferObject::Renderer,QQuickFramebufferObject可以说是一个壳子,用于Qml中使用,实际gl的代码是在Renderer中实现,通过createRenderer返回渲染对象即可。

完整代码

#ifndef FRAMEBUFFEROBJECT_H
#define FRAMEBUFFEROBJECT_H

#include <QQuickItem>
#include <QQuickFramebufferObject>
#include <QOpenGLFunctions_3_3_Core>
#include <QOpenGLShaderProgram>

class FrameBufferObject : public QQuickFramebufferObject
{
    Q_OBJECT

public:
    FrameBufferObject(QQuickItem *parent = nullptr);

    QQuickFramebufferObject::Renderer *createRenderer() const override;
};

class QOpenGLTexture;
class FrameBufferRenderer : public QQuickFramebufferObject::Renderer, QOpenGLFunctions_3_3_Core
{
public:
    FrameBufferRenderer();
    ~FrameBufferRenderer();

    void render() override;

private:
    QOpenGLShaderProgram m_shaderProgram;

    QOpenGLTexture* m_wallTexture;
    QOpenGLTexture* m_faceTexture;

    QOpenGLShaderProgram program;
};

#endif // FRAMEBUFFEROBJECT_H

#include "framebufferobject.h"
#include <QOpenGLTexture>
#include <QOpenGLFramebufferObject>

FrameBufferObject::FrameBufferObject(QQuickItem *parent)
    : QQuickFramebufferObject(parent)
{

}

QQuickFramebufferObject::Renderer *FrameBufferObject::createRenderer() const
{
    return new FrameBufferRenderer;
}

static unsigned int VBO, VAO, EBO;

static float vertices[] = {
    0.5f, 0.5f, 0.0f, 1.0f, 0.0f,   // 右上角
    0.5f, -0.5f, 0.0f, 1.0f, 1.0f,  // 右下角
    -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, // 左下角
    -0.5f, 0.5f, 0.0f, 0.0f, 0.0f,  // 左上角
};

static unsigned int indices[] = {
    0, 1, 2, 3
};


FrameBufferRenderer::FrameBufferRenderer()
{
    initializeOpenGLFunctions();

    m_wallTexture = new QOpenGLTexture(QImage(":/skin/images/wall.jpg"));
    m_faceTexture = new QOpenGLTexture(QImage(":/skin/images/awesomeface.png"));

    m_shaderProgram.addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/shapes.vert");
    m_shaderProgram.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/shapes.frag");
    m_shaderProgram.link();

    m_shaderProgram.bind();

    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glGenBuffers(1, &EBO);

    // 绑定顶点数组对象
    glBindVertexArray(VAO);

    // 把我们的顶点数组复制到一个顶点缓冲中,供OpenGL使用
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    // 复制我们的索引数组到一个索引缓冲中,供OpenGL使用
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    m_shaderProgram.release();
}

FrameBufferRenderer::~FrameBufferRenderer()
{
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteBuffers(1, &EBO);
}

void FrameBufferRenderer::render()
{
    // 背景颜色
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    m_shaderProgram.bind();

    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    m_wallTexture->bind();

    // 设定顶点属性指针
    glVertexAttribPointer(0 ,3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    glVertexAttribPointer(1 ,2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);

    // 绘制
    glDrawElements(GL_POLYGON, 4, GL_UNSIGNED_INT, nullptr);

    m_shaderProgram.release();
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Arui丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值