首页 > 其他分享 >QT+OpenGL纹理与颜色混合

QT+OpenGL纹理与颜色混合

时间:2024-08-23 17:19:48浏览次数:10  
标签:颜色混合 1.0 QT OpenGL 0.0 void TEXTURE 纹理 GL

一、概述

  使用OpenGL将纹理与颜色混合输出。ps:此处并无实际的意义只是单纯的为了好玩。

  

  步骤:

  1.定义顶点坐标、颜色、纹理及顶点索引

float vertices[] = {
    //     ---- 位置 ----  -----颜色-----          - 纹理坐标 -
         1.0f,  1.0f, 0.0f,  1.0f, 0.0f, 0.0f,  1.0f, 1.0f,   // 右上
         1.0f, -1.0f, 0.0f,  0.0f, 1.0f, 0.0f, 1.0f, 0.0f,   // 右下
        -1.0f, -1.0f, 0.0f,  0.0f, 0.0f, 1.0f, 0.0f, 0.0f,   // 左下
        -1.0f,  1.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.创建及绑定VAO、VBO、EBO

//创建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);

  3.告知显卡应该如何解析vertices中定义的数据

////告知显卡顶点数据如何解析
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);

////告知显卡颜色坐标如何解析
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);

////告知显卡纹理坐标如何解析
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(2);

  4.创建纹理、绑定纹理、并将纹理数据发送给GPU

////创建纹理
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
//设置纹理环绕方式
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);

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

  5.定义顶点着色器及片元着色器代码

//顶点着色器
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoord;
out vec2 ourTexCoord;
out vec3 ourColor;
void main(void)
{
    gl_Position = vec4(aPos,1.0f);
    ourTexCoord = aTexCoord;
    ourColor = aColor;
}
//片元着色器
#version 330 core
out vec4 FragColor;
in vec2 ourTexCoord;
in vec3 ourColor;
uniform sampler2D ourTexture;
void main()
{
    FragColor = texture(ourTexture,ourTexCoord)*vec4(ourColor,1.0f);
}

  6.编译着色器代码

GLuint BaseOpenGLWindow::buildAttachShaderAndReturnProgramId(QString vertexResPath, QString fragmentResPath) {
    //编译顶点着色器和片元着色器
    GLuint vertexShader = getShaderId(GL_VERTEX_SHADER, vertexResPath);
    GLuint fragmentShader = getShaderId(GL_FRAGMENT_SHADER, fragmentResPath);
    GLuint programId = glCreateProgram();
    glAttachShader(programId, vertexShader);
    glAttachShader(programId, fragmentShader);
    glLinkProgram(programId);
    getLinkProgramErrorInfo(programId);

    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);
    return programId;
}
void BaseOpenGLWindow::getLinkProgramErrorInfo(GLuint programId) {
    int success;
    char infoLog[512];
    glGetProgramiv(programId, GL_LINK_STATUS, &success);
    if (!success) {
        glGetProgramInfoLog(programId, 512, NULL, infoLog);
        qDebug() << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog;
    }
}
GLuint BaseOpenGLWindow::getShaderId(GLenum shaderType, QString resPath) {
    //创建顶点着色器
    unsigned int shaderId = glCreateShader(shaderType);
    QFile vertexShaderFile(resPath);
    if (!vertexShaderFile.open(QIODevice::ReadOnly)) {
        qDebug() << "Cannot open vertex shader file for reading";
    }
    QString verQStr = vertexShaderFile.readAll();
    std::string verStdStr = verQStr.toStdString();
    const char* vertexStr = verStdStr.c_str();
    qDebug() << "vertexStr-------------" << vertexStr;
    vertexShaderFile.flush();
    vertexShaderFile.close();
    glShaderSource(shaderId, 1, &vertexStr, NULL);
    glCompileShader(shaderId);
    getCompileShaderErrorInfo(shaderId);
    return shaderId;
}
void BaseOpenGLWindow::getCompileShaderErrorInfo(GLuint shaderId) {
    int success;
    char infoLog[512];
    glGetShaderiv(shaderId, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(shaderId, 512, NULL, infoLog);
        qDebug() << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog;
    }
}

  7.绘制

void GLTextureColorWindow::paintGL() {

    glBindVertexArray(VAO);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture);
    glUseProgram(programId);
    //glUniform1i(glGetUniformLocation(programId, "ourTexture"), 0);

    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
}

 

二、完整代码示例

  1.GLTextureColorWindow.h

#pragma once
#include "BaseOpenGLWindow.h"
#ifndef STB_IMAGE_H
#define STB_IMAGE_H
#include "../../stb_image.h"
#endif // STB_IMAGE_H

class GLTextureColorWindow : public BaseOpenGLWindow
{
    Q_OBJECT

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

protected:
    virtual void initializeGL();//初始化OpenGL
    virtual void resizeGL(int w, int h);//ResizeWindow大小
    virtual void paintGL();//绘制OpenGL
private:
    unsigned int VAO, VBO, EBO;
    unsigned int texture, texture1, texture2;
    GLuint programId;
};

 

  2.GLTextureColorWindow.cpp

#include "GLTextureColorWindow.h"

GLTextureColorWindow::GLTextureColorWindow(QWidget *parent)
    : BaseOpenGLWindow(parent)
{
    this->setWindowTitle("贴图与颜色混合");
}
void GLTextureColorWindow::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, 0.0f, 0.0f,  1.0f, 1.0f,   // 右上
             1.0f, -1.0f, 0.0f,  0.0f, 1.0f, 0.0f, 1.0f, 0.0f,   // 右下
            -1.0f, -1.0f, 0.0f,  0.0f, 0.0f, 1.0f, 0.0f, 0.0f,   // 左下
            -1.0f,  1.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
    };
    //创建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, 8 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    ////告知显卡颜色坐标如何解析
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);

    ////告知显卡纹理坐标如何解析
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
    glEnableVertexAttribArray(2);


    ////创建纹理
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    //设置纹理环绕方式
    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);

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

    //小程序
    programId = buildAttachShaderAndReturnProgramId(":/QtForOpenCV4Tool/shader/texture_color.vert",
        ":/QtForOpenCV4Tool/shader/texture_color.frag");
}
void GLTextureColorWindow::resizeGL(int w, int h) {
    glViewport(0, 0, w, h);
}
void GLTextureColorWindow::paintGL() {

    glBindVertexArray(VAO);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture);
    glUseProgram(programId);
    //glUniform1i(glGetUniformLocation(programId, "ourTexture"), 0);

    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
}

GLTextureColorWindow::~GLTextureColorWindow()
{
}

 

标签:颜色混合,1.0,QT,OpenGL,0.0,void,TEXTURE,纹理,GL
From: https://www.cnblogs.com/tony-yang-flutter/p/18376618

相关文章

  • Qt实现画图板
    Qt实现画板基于QGraphicsView实现绘画曲线注意点_qgraphicsview绘制曲线图-CSDN博客Qt桌面白板工具其一(解决曲线不平滑的问题——贝塞尔曲线)_qt贝塞尔曲线-CSDN博客先实现一个最简单的不考虑任何优化的曲线画板我们知道鼠标移动时,会在其移动轨迹上留下一系列的点,我们可以将这......
  • 【Qt】Qt窗口 | QDialog 对话框
    文章目录一.对话框二.对话框的分类1.非模态对话框2.模态对话框3.混合属性对话框三.自定义对话框1.代码实现2.ui文件实现四.内置对话框1.QMessageBox消息对话框2.QColorDialog颜色对话框3.QFileDialog文件对话框4.QFontDialog字体对话框5.QInputDialo......
  • Qt5.14.2 多边形与多边形求交集
    利用Qt5.14.2中自带的QPolygonF类的intersected()函数求两个多边形的交集多边形。inlineQList<QPolygonF>getPolygonIntersectedWithPolygon(QPolygonFpolygon1,QPolygonFpolygon2){QList<QPolygonF>outval;//此处求出的intersection可能包含多个子......
  • qt5.14.2 MSVC opencv(不结合vs)路径添加问题 测试通过
     不换行写法1win32:CONFIG(release,debug|release):LIBS+=-LG:/opencv4.4.0/opencv4.4_vs_msvc19_qt6.5/x64/vc17/lib/-lopencv_aruco440-lopencv_bgsegm440-lopencv_bioinspired440-lopencv_calib3d440-lopencv_ccalib440-lopencv_core440-lopencv_cvv440-lopen......
  • Qt5.14.2 MinGW7.3.0_64 opencv helloworld
    路径配置.proINCLUDEPATH+=E:\Opencv\includeLIBS+=E:\Opencv\x64\mingw\lib\libopencv_*.a 点击按钮打开一张图片1#include"mainwindow.h"2#include"ui_mainwindow.h"3#include<QFileDialog>4#include<QMessageBox>5......
  • PyQt5简介
    PyQt是Qt框架的Python语言实现,由RiverbankComputing开发,是最强大的GUI库之一。PyQt提供了一个设计良好的窗口控件集合,每一个PyQt控件都对应一个Qt控件,因此PyQt的API接口与Qt的API接口很接近,但PyQt不再使用QMake系统和Q_OBJECT宏。PyQt5提供GPL版和商业版证书,自由开发者可以使用......
  • Qt Line Edit焦点丢失|Checkbox转移焦点丢失
    在我设计的一个界面中,用事件过滤器获取键盘方向键,通过键盘方向键转移控件的焦点,获取焦点的控件显示高亮,在从一个Checkbox控件转移焦点到一个LineEdit控件的时候,该获得焦点的控件并没有显示高亮,并且根据后续操作推测焦点消失了,通过qDebug调试发现转移焦点后的那一瞬间,LineEdit控......
  • Qt:Qt背景
    目录1.Qt解释2.Windows下开发GUI的方案3.框架4.Qt历史4.Qt支持的平台5.Qt版本6.Qt案例1.Qt解释        前端开发,分为网页前端开发(Web)、桌面应用开发(Windows、Linux)、移动应用开发(Android)。Qt一般用于客户端开发,这里的客户端是狭义的,指桌面应用开发。  ......
  • QT+OpenGL简单纹理贴图
    一、概述之前的文章都是绘制一些纯色的三角形和正方形以及控制他们的相对位置。在实际的开发中一般都需要给绘制出的图形贴上漂亮的纹理。纹理贴图步骤:1.创建纹理glGenTextures(1,&texture);//参数1:创建纹理的数量,参数2:用户定义的纹理id,一般为unsignedint......
  • QT+OpenGL从顶点着色器传递颜色数据给片元着色器
    一、概述目的:1.定义顶点数据和颜色数据,并将颜色数据通过顶点着色器传递给片元着色器2.对定义的三角形动态进行:平移、颠倒、镜像二、示例代码1.定义顶点坐标和颜色值。此处颜色和顶点是放到一块的。需要告知GPU如何解析数据,如:哪些是顶点,哪......