随笔 - 632  文章 - 17  评论 - 54  阅读 - 93万

Qt+OpenGL混合两个纹理,并可以改变纹理透明度

QT+OpenGL基础:

  1. QT+OpenGL创建一个三角形并动态改变三角形颜色
  2. OpenGL中的VAO、VBO、EBO
  3. QT+OpenGL 使用VAO、VBO、EBO结合绘制一个正方形
  4. QT+OpenGL使用一组顶点绘制两个三角形
  5. QT+OpenGL通过两个VAO来管理两个三角形
  6. QT+Opengl使用两个Shader绘制两个不同颜色的三角形
  7. QT+OpenGL从顶点着色器传递颜色数据给片元着色器
  8. QT+OpenGL简单纹理贴图
  9. QT+OpenGL纹理与颜色混合
  10. Qt+OpenGL混合两个纹理,并可以改变纹理透明度

 

一、概述

  需求:

    1.将两纹理进行融合,改变其中一个透明度让其渐渐显示或隐藏

    2.控制x轴像素互换,让笑脸达到向左看或向右看的目的。

  

   大部分的代码都是常规代码。还是那一套流程:

    1.定义顶点、纹理、顶点索引坐标。

    2.创建并绑定VAO、VBO、EBO。

    3.告知显卡顶点解析方式。

    4.定义顶点着色器及片元着色器,编译程序。

    5.创建纹理。

    6.开始绘制

    这里面最主要的是顶点即纹理的定义、着色器的传参、绘制代码

  步骤:

  1.定义顶点、纹理坐标

复制代码
float vertices[] = {
    //     ---- 位置 ----          - 纹理坐标 -
         1.0f,  1.0f, 0.0f,   1.0f, 1.0f,   // 右上
         1.0f, -1.0f, 0.0f,   1.0f, 0.0f,   // 右下
        -1.0f, -1.0f, 0.0f,   0.0f, 0.0f,   // 左下
        -1.0f,  1.0f, 0.0f,    0.0f, 1.0f    // 左上
};
unsigned int indices[] = {
   0, 1, 3, // first triangle
   1, 2, 3  // second triangle
};
复制代码

  2.着色器的定义

复制代码
//顶点着色器
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;
out vec2 ourTexCoord;
void main(void)
{
    gl_Position = vec4(aPos.x,aPos.y,aPos.z,1.0f);
    ourTexCoord = aTexCoord;
}

//片元着色器
#version 330 core
out vec4 FragColor;
in vec2 ourTexCoord;
uniform float maxScale;
uniform float flip_x;
uniform sampler2D ourTexture1;
uniform sampler2D ourTexture2;
void main()
{
    FragColor = mix(texture(ourTexture1,ourTexCoord),texture(ourTexture2,vec2(ourTexCoord.x*flip_x,ourTexCoord.y)),maxScale);
}
复制代码

  3.给定义的着色器传参(绘制)

glUniform1f(glGetUniformLocation(programId, "flip_x"), flip_x);
glUniform1f(glGetUniformLocation(programId, "maxScale"), mixScale);
//指定纹理单元编号
GLint ourTextureLocation = glGetUniformLocation(programId, "ourTexture1");
glUniform1i(ourTextureLocation, 0);
GLint ourTexture1Location = glGetUniformLocation(programId, "ourTexture2");
glUniform1i(ourTexture1Location, 1);

 

二、完整代码示例

  1.GLTextureMixWindow.h

复制代码
#pragma once

#include "BaseOpenGLWindow.h"
#ifndef STB_IMAGE_H
#define STB_IMAGE_H
#include "../../stb_image.h"
#endif // STB_IMAGE_H
#include <qmatrix4x4.h>
#include <qvector3d.h>
#include <QRectF>

class GLTextureMixWindow : public BaseOpenGLWindow
{
    Q_OBJECT

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

protected:
    virtual void initializeGL();//初始化OpenGL
    virtual void resizeGL(int w, int h);//ResizeWindow大小
    virtual void paintGL();//绘制OpenGL
public:
    GLuint buildTexture(QString textureFileName, GLint imageColorType);
    void setMixScale(float mix);
    void flipToX();
private:
    unsigned int VAO, VBO, EBO;
    unsigned int texture, texture1, texture2;
    GLuint programId;
    float mixScale = 0.5f;
    float flip_x = 1.0f;
};
复制代码

 

  2.GLTextureMixWindow.cpp

复制代码
#include "GLTextureMixWindow.h"

GLTextureMixWindow::GLTextureMixWindow(QWidget* parent)
    : BaseOpenGLWindow(parent)
{
    this->setWindowTitle("纹理融合");
    QHBoxLayout* hLayout = new QHBoxLayout(this);
    QPushButton* btnRed = new QPushButton(this);
    btnRed->setText("融合系数增大(+)");
    QPushButton* btnGreen = new QPushButton(this);
    btnGreen->setText("融合系数减小(-)");
    QPushButton* btnFlipX = new QPushButton(this);
    btnFlipX->setText("x轴像素位置互换");
    hLayout->addWidget(btnRed);
    hLayout->addWidget(btnGreen);
    hLayout->addWidget(btnFlipX);
    hLayout->setAlignment(Qt::AlignTop);

    connect(btnRed, &QPushButton::clicked, [this]() {
        this->mixScale += 0.1f;
        if (this->mixScale >= 1.0f) this->mixScale = 1.0f;
        setMixScale(mixScale);
        });

    connect(btnGreen, &QPushButton::clicked, [=]() {
        this->mixScale -= 0.1f;
        if (this->mixScale < 0.0f) this->mixScale = 0.0f;
        setMixScale(mixScale);
        });

    connect(btnFlipX, &QPushButton::clicked, [=]() {
        flipToX();
        });

}
void GLTextureMixWindow::initializeGL() {
    this->initializeOpenGLFunctions();
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    float vertices[] = {
        //     ---- 位置 ----          - 纹理坐标 -
             1.0f,  1.0f, 0.0f,   1.0f, 1.0f,   // 右上
             1.0f, -1.0f, 0.0f,   1.0f, 0.0f,   // 右下
            -1.0f, -1.0f, 0.0f,   0.0f, 0.0f,   // 左下
            -1.0f,  1.0f, 0.0f,    0.0f, 1.0f    // 左上
    };
    //float vertices[] = {
    //    //     ---- 位置 ----          - 纹理坐标 -
    //         1.0f,  1.0f, 0.0f,   4.0f, 4.0f,   // 右上
    //         1.0f, -1.0f, 0.0f,   4.0f, 0.0f,   // 右下
    //        -1.0f, -1.0f, 0.0f,   0.0f, 0.0f,   // 左下
    //        -1.0f,  1.0f, 0.0f,    0.0f, 4.0f    // 左上
    //};
    unsigned int indices[] = {
       0, 1, 3, // first triangle
       1, 2, 3  // second triangle
    };
    //创建VAO、VBO、EBO
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glGenBuffers(1, &EBO);
    glBindVertexArray(VAO);

    ////顶点数据存入缓冲区
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    ////EBO
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, 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);

    stbi_set_flip_vertically_on_load(true);
    texture = buildTexture("E:/tony/demo/visualstudio_workspace/QtForOpenCV4Tool/QtForOpenCV4Tool/bin/images/flowers.jpeg",
        GL_RGB);
    texture1 = buildTexture("E:/tony/demo/visualstudio_workspace/QtForOpenCV4Tool/QtForOpenCV4Tool/bin/images/similing_face.png",
        GL_RGBA);

    //小程序
    programId = buildAttachShaderAndReturnProgramId(":/QtForOpenCV4Tool/shader/texture_mix.vert",
        ":/QtForOpenCV4Tool/shader/texture_mix.frag");
}
GLuint GLTextureMixWindow::buildTexture(QString textureFileName, GLint imageColorType) {
    GLuint mTexture;
    ////创建纹理
    glGenTextures(1, &mTexture);
    glBindTexture(GL_TEXTURE_2D, mTexture);
    //设置纹理环绕方式
    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_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    //生成纹理
    int width, height, mChannels;
    //QString path = getTexturePath(textureFileName);
    //qDebug() << path.toStdString().c_str();
    unsigned char* data = stbi_load(textureFileName.toStdString().c_str(), &width, &height, &mChannels, 0);
    if (data) {
        qDebug() << "图片加载成功,width=" << width << ",height=" << height;
        glTexImage2D(GL_TEXTURE_2D, 0, imageColorType, width, height, 0, imageColorType, GL_UNSIGNED_BYTE, data);
        glGenerateMipmap(GL_TEXTURE_2D);
    }
    else {
        qDebug() << "图像数据加载失败";
    }
    stbi_image_free(data);

    return mTexture;
}
void GLTextureMixWindow::resizeGL(int w, int h) {
    glViewport(0, 0, w, h);
}
void GLTextureMixWindow::paintGL() {
    glBindVertexArray(VAO);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture);
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, texture1);
    glUseProgram(programId);
    glUniform1f(glGetUniformLocation(programId, "flip_x"), flip_x);
    glUniform1f(glGetUniformLocation(programId, "maxScale"), mixScale);
    //指定纹理单元编号
    GLint ourTextureLocation = glGetUniformLocation(programId, "ourTexture1");
    glUniform1i(ourTextureLocation, 0);
    GLint ourTexture1Location = glGetUniformLocation(programId, "ourTexture2");
    glUniform1i(ourTexture1Location, 1);

    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
}
void GLTextureMixWindow::setMixScale(float mix) {
    this->mixScale = mix;
    update();
}
void GLTextureMixWindow::flipToX() {
    this->flip_x = -this->flip_x;
    update();
}
GLTextureMixWindow::~GLTextureMixWindow()
{
}
复制代码

 

posted on   飘杨......  阅读(139)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
历史上的今天:
2023-08-23 社区版idea实现热部署
2013-08-23 Android使用AsyncTask设置请求超时的注意事项
2013-08-23 Android源代码下载以及异常查找网站推荐
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示