QT框架下的OpenGL使用---复现篇---纹理

本篇文章的复现对应于LearnOpenGL教程的入门纹理教程。

使用OpenGL时经常需要在画面中显示2D的图像或是给3D的图形表面贴一张2D的图像,这个时候就会用到纹理贴图。具体的细节LearnOpenGL教程已经讲得很清楚了,这里就不再赘述。

不过,有一点比较神奇也可以说是反直觉的地方需要注意一下。在以前的认知中,图像一般要放在一个矩形框中进行显示,很多时候我们用QT或者MFC等界面库的时候也的确就是这么操作的。然而在OpenGL或者Direct这种渲染框架中贴图不是这样的,由于空间中3个点就能确定一个平面,因此为了空间精细度,我们贴图在大部分情况下是贴在三角形上的。

具体的实现本人已经转到Qt下了,代码如下:

MyOpenGLWidget.h
#ifndef MYOPENGLWIDGET_H
#define MYOPENGLWIDGET_H
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QOpenGLBuffer>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLShaderProgram>
#include <QElapsedTimer>
#include <QOpenGLTexture>
#include <QDebug>

class MyOpenGLWidget : public QOpenGLWidget
{
    Q_OBJECT
public:
    MyOpenGLWidget(QWidget *partent);
    ~MyOpenGLWidget();
protected:
    void initializeGL();//初始化函数,在Widget刚加载时被调用
    void paintGL();//绘图函数,每一次绘图请求产生,都会进行一次绘图
    void resizeGL(int w, int h);//用于处理窗口大小变化的情况

private:
    QOpenGLBuffer *m_vbo,*m_ebo;
    QOpenGLVertexArrayObject *m_vao;
    QOpenGLShaderProgram *m_shader;//渲染器程序对象
    QOpenGLFunctions *f;//OpenGL函数对象
    QOpenGLTexture *texture1 = nullptr;
    QOpenGLTexture *texture2 = nullptr;
};
#endif // MYOPENGLWIDGET_H
MyOpenGLWidget.cpp
#include <MyOpenGLWidget.h>

MyOpenGLWidget::MyOpenGLWidget(QWidget* parent):
    QOpenGLWidget (parent)
{

}
MyOpenGLWidget::~MyOpenGLWidget()
{
    //多线程调用保护
    makeCurrent();
    //对象释放
    m_vbo->destroy();
    m_ebo->destroy();
    m_vao->destroy();
    delete texture1;
    delete texture2;
    //退出保护
    doneCurrent();
}
void MyOpenGLWidget::initializeGL()
{
    f = this->context()->functions();
    f->glEnable(GL_DEPTH_TEST);   // 三维绘图的关键!
    m_shader = new QOpenGLShaderProgram();
    m_shader->addShaderFromSourceFile(QOpenGLShader::Vertex, "../Demo1/Vertex.vert");
    m_shader->addShaderFromSourceFile(QOpenGLShader::Fragment, "../Demo1/Fragment.frag");
    if (m_shader->link()) {
        qDebug("Shaders link success.");
    } else {
        qDebug("Shaders link failed!");
    }
    //VBO,VEO数据
    static const GLfloat vertices[] = {
        //位置                 //颜色              //纹理位置
         0.5f,  0.5f, 0.0f,   1.0f, 0.0f, 0.0f,   1.0f, 1.0f, // top right
         0.5f, -0.5f, 0.0f,   0.0f, 1.0f, 0.0f,   1.0f, 0.0f, // bottom right
        -0.5f, -0.5f, 0.0f,   0.0f, 0.0f, 1.0f,   0.0f, 0.0f, // bottom left
        -0.5f,  0.5f, 0.0f,   1.0f, 1.0f, 0.0f,   0.0f, 1.0f  // top left
    };
     static const GLint indices[] = {  // note that we start from 0!
        0, 1, 3,  // first Triangle
        1, 2, 3   // second Triangle
    };

    m_vao = new QOpenGLVertexArrayObject();
    m_vbo = new QOpenGLBuffer(QOpenGLBuffer::Type::VertexBuffer);
    m_ebo = new QOpenGLBuffer(QOpenGLBuffer::Type::IndexBuffer);
    m_vao->create();
    m_vao->bind();
    m_vbo->create();
    m_vbo->bind();
    m_vbo->allocate(vertices, 4*8*sizeof(GLfloat));
    m_ebo->create();
    m_ebo->bind();
    m_ebo->allocate(indices, 2*3*sizeof(GLint));

    int attr = -1;
    //顶点属性设置
    attr = m_shader->attributeLocation("aPos");
    m_shader->setAttributeBuffer(attr, GL_FLOAT, 0, 3, sizeof(GLfloat) * 8);
    m_shader->enableAttributeArray(attr);
    //颜色属性设置
    attr = m_shader->attributeLocation("aColor");
    m_shader->setAttributeBuffer(attr, GL_FLOAT, sizeof(GLfloat) * 3, 3, sizeof(GLfloat) * 8);
    m_shader->enableAttributeArray(attr);
    //纹理属性设置
    attr = m_shader->attributeLocation("aTexCoord");
    m_shader->setAttributeBuffer(attr, GL_FLOAT, sizeof(GLfloat) * 6, 2, sizeof(GLfloat) * 8);
    m_shader->enableAttributeArray(attr);

    m_vao->release();
    m_vbo->release();
    m_ebo->release();

    //纹理读取
    // texture 1
    texture1 = new QOpenGLTexture(QImage("container.jpg"), QOpenGLTexture::GenerateMipMaps);//直接生成绑定一个2d纹理, 并生成多级纹理MipMaps
    if(!texture1->isCreated()){
        qDebug() << "Failed to load texture";
    }
    //设置纹理对象的环绕
    texture1->setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::Repeat);
    texture1->setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::Repeat);
    //设置纹理对象的采样方式
    texture1->setMinificationFilter(QOpenGLTexture::Linear);//缩小
    texture1->setMagnificationFilter(QOpenGLTexture::Linear);//放大

    // texture 2
    texture2 = new QOpenGLTexture(QImage("1.jpeg"), QOpenGLTexture::GenerateMipMaps);
    if(!texture2->isCreated()){
        qDebug() << "Failed to load texture";
    }
    texture2->setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::Repeat);
    texture2->setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::Repeat);
    texture2->setMinificationFilter(QOpenGLTexture::Linear);
    texture2->setMagnificationFilter(QOpenGLTexture::Linear);

    //设置纹理对应的单元
    m_shader->bind();
    m_shader->setUniformValue("texture1", 0);
    m_shader->setUniformValue("texture2", 1);
    m_shader->release();
}
void MyOpenGLWidget::paintGL()
{
    //纹理绑定
    f->glActiveTexture(GL_TEXTURE0);
    texture1->bind();
    f->glActiveTexture(GL_TEXTURE1);
    texture2->bind();

    f->glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
    f->glClearColor(0.0f, 0.2f, 0.0f, 1.0f);
    m_vao->bind();
    m_shader->bind();

    f->glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);//绘制索引对象
    m_shader->release();
    m_vao->release();
    texture1->release();
    texture2->release();
}
void MyOpenGLWidget::resizeGL(int w, int h)
{
    f->glViewport(0, 0, w, h);
}
参考文章:

https://www.jianshu.com/p/273b7f960f3d

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值