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

    xiaoxiao2023-11-22  182

    纹理,简单说就是将图片展示在物体表面。可以将其类比为墙纸。纹理分为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); }

     

    最新回复(0)