基于Qt的Opengl可编程管线学习——纹理(QOpenGLTexture使用)

纹理,简单说就是将图片展示在物体表面。可以将其类比为墙纸。纹理分为1D,2D,  3D 三类。这里只讨论2D纹理。先要记录一下比较基本的概念。

一、纹理坐标

纹理坐标起始于(0, 0),也就是纹理图片的左下角,终始于(1, 1),即纹理图片的右上角。和数学二维坐标一样。

二、纹理创建

Qt提供方便的纹理类——QOpenGLTexture。它使纹理操作变得非常简单。这样就创建了一个纹理对象了。和创建QImage对象类似。不过要注意坐标系(纹理坐标与绘制设备坐标)的不同原因。所以需进行镜像操作。

    m_texture = new QOpenGLTexture(QImage(":/images/side6.png").mirrored());

三、纹理映射与采样

就像贴墙纸一样,壁纸上的点要和墙面上点要对应起来。那就需要指定物体的每个顶点各自对应纹理的哪个部分。我们看到的壁纸上边有各种图案,图案实际是由每个颜色点组成。使用纹理坐标获取纹理颜色就是采样。

四、纹理过滤方式

这是s.t 两个坐标方向上的属性。暂时先记住结论性的一句话:“纹理被缩小的时候使用邻近过滤,被放大时使用线性过滤。”以后对它有深刻认识在深入讨论。

    m_texture->setMinificationFilter(QOpenGLTexture::Nearest);
    m_texture->setMagnificationFilter(QOpenGLTexture::Linear);

五、纹理的其他属性

纹理环绕方式,类似qss的border-img。通常设置为GL_REPEAT:

    m_texture->setWrapMode(QOpenGLTexture::Repeat);

六、编码

CPU端:

//

#pragma once


#include <QOpenGLShaderProgram>
#include <QOpenGLFunctions>
#include <QOpenGLWidget>
#include <QOpenGLFunctions_3_3_Core>
#include <QOpenGLTexture>
#include <QOpenGLBuffer>
#include <QOpenGLVertexArrayObject>

class OpenGLWidget : public QOpenGLWidget,
        private QOpenGLFunctions_3_3_Core /*QOpenGLFunctions*/
{
	Q_OBJECT

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

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

private:
    bool createSharderProgram();
    void makeObject();

private:
	QOpenGLShaderProgram *m_program;
    QOpenGLTexture *m_texture;
    QOpenGLBuffer m_vbo;
    int m_matrixUniform;
    QMatrix4x4 m_projectMat;
};


#include "opengl_widget.h"
#include <QVariant>

OpenGLWidget::OpenGLWidget(QWidget *parent)
	: QOpenGLWidget(parent),
    m_program(nullptr),
    m_texture(nullptr),
    m_vbo(QOpenGLBuffer::VertexBuffer),
    m_matrixUniform(0),
    m_projectMat()

{
}

OpenGLWidget::~OpenGLWidget()
{
    makeCurrent();
    m_vbo.destroy();
}

void OpenGLWidget::initializeGL()
{
	initializeOpenGLFunctions();
    createSharderProgram();

    m_vbo.create();
    makeObject();
}

void OpenGLWidget::resizeGL(int w, int h)
{
    float aspect = float(w)/float(h?h:1);
    float fov = 45.0f, zNear = 0.1f, zFar = 100.f;
    m_projectMat.setToIdentity();
    m_projectMat.perspective(fov, aspect, zNear, zFar);
}

void OpenGLWidget::paintGL()
{

    glClear(GL_COLOR_BUFFER_BIT);

    m_program->bind();

    QMatrix4x4 mvMat;
    mvMat.translate(0.0f, 0.0f, -3.0f);
    m_program->setUniformValue(m_matrixUniform, m_projectMat*mvMat);
    m_texture->bind();
    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
    m_texture->release();

    m_program->release();
}

bool OpenGLWidget::createSharderProgram()
{
    bool suc(false);
	m_program = new QOpenGLShaderProgram(this);
    suc = m_program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/vsharder.glsl");
    suc = m_program->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/first_texture.glsl");
	suc = m_program->link();

    suc = m_program->bind();
    if(!suc) {
        close();
        return suc;
    }

    m_matrixUniform = m_program->uniformLocation("mvpMat");

    return suc;
}

void OpenGLWidget::makeObject()
{
    m_texture = new QOpenGLTexture(QImage(":/images/side6.png").mirrored());
    m_texture->setMinificationFilter(QOpenGLTexture::Nearest);
    m_texture->setMagnificationFilter(QOpenGLTexture::Linear);
    m_texture->setWrapMode(QOpenGLTexture::Repeat);


    float arrVertex[] {
        // position           texture
        0.5f,  0.5f, 0.0f, 1.0f, 1.0f,
        0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
        -0.5f, -0.5f, 0.0f, 0.0f, 0.0f,
        -0.5f,  0.5f, 0.0f, 0.0f, 1.0f
    };

    m_vbo.bind();
    m_vbo.allocate(arrVertex, sizeof(arrVertex));

    int attr = -1;
    attr = m_program->attributeLocation("attrPos");
    m_program->setAttributeBuffer(attr, GL_FLOAT, 0,
        3, sizeof(float) * 5);
    m_program->enableAttributeArray(attr);

    attr = m_program->attributeLocation("attrTexCoord");
    m_program->setAttributeBuffer(attr, GL_FLOAT, 3 * sizeof(float),
        2, sizeof(float) * 5);
    m_program->enableAttributeArray(attr);

    m_vbo.release();
}

GPU端

v s

#ifdef GL_ES
// Set default precision to medium
precision mediump int;
precision mediump float;
#endif

uniform mat4 mvpMat;
attribute vec4 attrPos;
attribute vec2 attrTexCoord;
varying vec2 texture_coord;

void main()
{
    gl_Position = mvpMat * attrPos;
    texture_coord = attrTexCoord;
}


 f s

#ifdef GL_ES
// Set default precision to medium
precision mediump int;
precision mediump float;
#endif

varying vec2 texture_coord;
uniform sampler2D samp;

void main()
{
    gl_FragColor = texture2D(samp, texture_coord);
}

 

  • 1
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值