当前位置: 首页 > news >正文

OpenGL多纹理处理

一、纹理处理流程

  1. 纹理加载与配置
    通过QImage加载图片并生成纹理对象:

    QImage image(":/texture.jpg");
    image = image.convertToFormat(QImage::Format_RGBA8888);
    
    glGenTextures(1, &textureID);
    glBindTexture(GL_TEXTURE_2D, textureID);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 
                 0, GL_RGBA, GL_UNSIGNED_BYTE, image.bits());
    glGenerateMipmap(GL_TEXTURE_2D);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    

    2‌. 多纹理支持
    若需不同纹理,可创建多个纹理对象并使用glActiveTexture切换或者调用纹理对象bind(0)切换。

        // 绑定纹理
        m_texture->bind(0);
        m_program.setUniformValue("texture1", 0);
        // 绘制矩形
        glBindVertexArray(VAO[0]);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

二、代码 

#ifndef GLWIDGET_H
#define GLWIDGET_H

// 头文件 GLWidget.h
#include <QOpenGLWidget>
#include <QOpenGLFunctions_4_5_Core>
#include <QOpenGLShaderProgram>
#include <QOpenGLTexture>
#include <QPainter>

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

    };
    ~GLWidget(){
        makeCurrent();
          delete m_texture;
          delete m_texture_text;
          glDeleteBuffers(2, VBO);
          glDeleteBuffers(2, EBO);
          glDeleteVertexArrays(2, VAO);
          doneCurrent();
    };

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


    QImage createTextTexture(const QString& text, int width, int height);

private:
    QOpenGLShaderProgram m_program;
    QOpenGLTexture *m_texture;
    QOpenGLTexture *m_texture_text;
    GLuint VAO[2], VBO[2], EBO[2];
    QMatrix4x4 m_modelMatrix;
};

QImage GLWidget::createTextTexture(const QString& text, int width, int height) {
    QImage image(width, height, QImage::Format_ARGB32);
    image.fill(Qt::transparent);

    QPainter painter(&image);
    painter.setPen(Qt::white);
    painter.setFont(QFont("Arial", 24));
    painter.drawText(image.rect(), Qt::AlignCenter, text);
    painter.end();

    // OpenGL 纹理坐标系原点在左下角,需垂直翻转图像
    return image.mirrored(false, true);
}


// 实现文件 GLWidget.cpp
void GLWidget::initializeGL() {
    initializeOpenGLFunctions();
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);

    // 编译着色器
    m_program.addShaderFromSourceCode(QOpenGLShader::Vertex,
        "#version 450 core\n"
        "layout (location=0) in vec3 aPos;\n"
        "layout (location=1) in vec2 aTexCoord;\n"
        "out vec2 TexCoord;\n"
        "uniform mat4 model;\n"
        "void main() {\n"
        "  gl_Position = model * vec4(aPos, 1.0);\n"
        "  TexCoord = aTexCoord;\n"
        "}");

    m_program.addShaderFromSourceCode(QOpenGLShader::Fragment,
        "#version 450 core\n"
        "in vec2 TexCoord;\n"
         "in float vPosY;\n"
        "out vec4 FragColor;\n"
        "uniform sampler2D texture1;\n"
        "void main() {\n"
            "  FragColor = texture(texture1, TexCoord);\n"
        "}");
   bool b = m_program.link();
   if(!b){
    qDebug() << "Shader Error:" << m_program.log();
   }

    // 顶点数据(包含位置和纹理坐标)
    float vertices1[] = {
        // positions       // texture coords
        -0.8f, -0.8f, 0.0f, 0.0f, 0.0f,
         0.0f, -0.8f, 0.0f, 1.0f, 0.0f,
         -0.8f,  0.8f, 0.0f, 0.0f, 1.0f,
         0.0f,  0.8f, 0.0f, 1.0f, 1.0f
    };

    float vertices2[] = {
        // positions       // texture coords
         0.0f, -0.8f, 0.0f, 0.0f, 0.0f,
         0.8f, -0.8f, 0.0f, 1.0f, 0.0f,
         0.0f,  0.8f, 0.0f, 0.0f, 1.0f,
         0.8f,  0.8f, 0.0f, 1.0f, 1.0f
    };

    // 创建VBO和VAO
    glGenVertexArrays(2, VAO);
    glGenBuffers(2, VBO);
    glGenBuffers(2, EBO); // 可选(用于索引绘制)

    //配置VAO
    glBindVertexArray(VAO[0]);
    glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices1), vertices1, GL_STATIC_DRAW);

    // 将索引数据复制到 EBO(如果有)
    unsigned int indices1[] = {0, 1, 2,
                              1, 3, 2};
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO[0]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices1), indices1, GL_STATIC_DRAW);

    // 设置顶点属性指针
    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);

    //配置VAO
    glBindVertexArray(VAO[1]);
    glBindBuffer(GL_ARRAY_BUFFER, VBO[1]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices2), vertices2, GL_STATIC_DRAW);

    // 将索引数据复制到 EBO(如果有)
    unsigned int indices2[] = {0, 1, 2,
                              1, 3, 2};
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO[0]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices2), indices2, GL_STATIC_DRAW);

    // 设置顶点属性指针
    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);

    glBindVertexArray(0);

    // 加载纹理
    m_texture = new QOpenGLTexture(QImage(":/textures/wood.jpg").mirrored());
    m_texture->setWrapMode(QOpenGLTexture::Repeat);
    m_texture->setMinMagFilters(QOpenGLTexture::Linear, QOpenGLTexture::Linear);

    QImage textImage = createTextTexture("Hello OpenGL!", 256, 32);
    m_texture_text = new QOpenGLTexture(textImage);
    m_texture_text->setWrapMode(QOpenGLTexture::Repeat);
    m_texture_text->setMinMagFilters(QOpenGLTexture::Linear, QOpenGLTexture::Linear);
}

void GLWidget::paintGL() {
    glClear(GL_COLOR_BUFFER_BIT);
    m_program.bind();

    // 设置模型矩阵(平移变换)
    m_modelMatrix.setToIdentity();
    m_modelMatrix.translate(0.0f, 0.0f, 0.0f);
    m_program.setUniformValue("model", m_modelMatrix);

    // 绑定纹理
    m_texture->bind(0);
    m_program.setUniformValue("texture1", 0);
    // 绘制矩形
    glBindVertexArray(VAO[0]);
    //glDrawArrays(GL_TRIANGLE_STRIP,0,4);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

    // 绑定纹理
    m_texture_text->bind(0);
    m_program.setUniformValue("texture1", 0);
    // 绘制矩形
    glBindVertexArray(VAO[1]);
    //glDrawArrays(GL_TRIANGLE_STRIP,0,4);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

    m_program.release();
}

void GLWidget::resizeGL(int w, int h) {
    glViewport(0, 0, w, h);
}

#endif // GLWIDGET_H

相关文章:

  • 本地文生图使用插件(Stable Diffusion)
  • 【JavaWeb学校Day29】
  • 【QT5 多线程示例】信号量
  • Java面试黄金宝典13
  • 有价值的面试问题
  • MTK平台 Android12-Android13 默认搜狗输入法
  • 借壹起航东风,中国工厂出海开启新征程
  • C语言的总结分享
  • 深度解析「前缀和」与「差分法」:高效算法的基石
  • B站左神算法课学习笔记(P7):图
  • 自然数k次方的前n项和通项公式
  • 23种设计模式-解释器(Interpreter)设计模式
  • html5炫酷3D数字时钟项目开发实践
  • systemd-networkd的配置文件的优先级 笔记250325
  • 【MySQL】MySQL B+树的查询数据过程是怎样的?
  • 【数据可视化艺术·进阶篇】热力图探秘:用色彩演绎场馆和景区的人流奥秘
  • 【读论文】——基于高光谱成像技术测定玉米籽粒硬度
  • 基于 arco 的 React 和 Vue 设计系统
  • 3.0 Disruptor的使用介绍(一)
  • RocketMQ 详细知识点总结
  • 嘉兴建设局网站/哈尔滨seo整站优化
  • 为公司做网站要做什么准备/好用的磁力搜索引擎
  • 惠州营销网站建设公司/媒体发稿公司
  • 网站建设 asp 武汉/网站提交
  • 网站推广网站关键词排名怎么做/网站创建流程
  • 做赌博网站的代理算赌博罪吗/正规营销培训