首页 > 其他分享 >QT+OpenGL简单纹理贴图

QT+OpenGL简单纹理贴图

时间:2024-08-22 16:50:35浏览次数:3  
标签:贴图 1.0 QT OpenGL TEXTURE 纹理 2D programId GL

一、概述

  之前的文章都是绘制一些纯色的三角形和正方形以及控制他们的相对位置。

  在实际的开发中一般都需要给绘制出的图形贴上漂亮的纹理。

  纹理贴图步骤:

  1.创建纹理

glGenTextures(1, &texture);//参数1:创建纹理的数量,参数2:用户定义的纹理id,一般为unsigned int

  2.绑定纹理

glBindTexture(GL_TEXTURE_2D, texture);//参数1:目标,2d纹理,参数2:上面创建的纹理对象

  3.设置纹理环绕方式

//设置纹理环绕方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

  4.设置纹理过滤方式(当纹理放大或缩小时应该如何采样)

//设置纹理过滤方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

  5.创建纹理并将纹理数据copy给GPU

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);

   6.加载纹理图像使用的是stb_image.h,如果不太清楚的可以上网查一下,资料一大堆

 

 

二、代码示例

  1.定义顶点数据和纹理数据(此处定义到一块,通过VBO一次性copy给GPU)

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    // 左上
};

  2.定义索引缓冲数组,用于顶点数据的索引(绘制正方形)

unsigned int indices[] = {
   0, 1, 3, // first triangle
   1, 2, 3  // second triangle
};

  3.创建VAO、VBO、EBO,同时将顶点、纹理、缓冲区数据copy给GPU。ps:VBO和EBO是挂在VAO下的,VAO是管理者

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

  4.告知GPU如何解析顶点数据和纹理数据

////告知显卡顶点数据如何解析
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);

  5.创建纹理并将纹理数据传递给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);

  6.定义顶点着色器和片元着色器

//定点着色器
#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,1.0f);
    ourTexCoord = aTexCoord;
}
//片元着色器
#version 330 core
out vec4 FragColor;
in vec2 ourTexCoord;
uniform sampler2D ourTexture;
void main()
{
    FragColor = texture(ourTexture,ourTexCoord);
}

  7.编译、连接顶点着色器和片元着色器

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;
    }
}
programId = buildAttachShaderAndReturnProgramId(":/QtForOpenCV4Tool/shader/girl_face.vert",
    ":/QtForOpenCV4Tool/shader/girl_face.frag");

  9.将纹理贴上去

glBindVertexArray(VAO);
glActiveTexture(GL_TEXTURE0);//几乎第一个纹理
glBindTexture(GL_TEXTURE_2D, texture);//绑定第一个纹理
glUseProgram(programId);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

 

  

标签:贴图,1.0,QT,OpenGL,TEXTURE,纹理,2D,programId,GL
From: https://www.cnblogs.com/tony-yang-flutter/p/18374242

相关文章

  • QT+OpenGL从顶点着色器传递颜色数据给片元着色器
    一、概述目的:1.定义顶点数据和颜色数据,并将颜色数据通过顶点着色器传递给片元着色器2.对定义的三角形动态进行:平移、颠倒、镜像二、示例代码1.定义顶点坐标和颜色值。此处颜色和顶点是放到一块的。需要告知GPU如何解析数据,如:哪些是顶点,哪......
  • Qt键盘事件检测不到方向键|阻止控件截取键盘事件
    做项目二次开发的时候遇到一个问题,在自己新建的界面中放了很多控件,需要通过键盘方向键来控制焦点在不同控件间的转移,之前用键盘事件检测上下键没有问题,后来加上左右键发现没有反应,查了资料了解到是控件吞掉了左右方向键的信号,因为Qt中本身就有一些处理事件的函数,控件会获取键盘左......
  • QT+OpenGL通过两个VAO来管理两个三角形
    一、概述需求:通过两个VAO来管理VBO,从而控制两个三角形此需求和单独通过VAO绘制一个三角形有较大的不同,此处创建两个VAO,同时需要管理两个VBO。在绘制图形的时候需要分别绑定这两个VAO才能正确的绘制出三角形。效果:二、代码示例1.定义顶点数据(两个三角形......
  • QT+OpenGL使用一组顶点绘制两个三角形
    一、概述需求:使用一组顶点坐标绘制两个三角形。ps:此需求和绘制一个三角形并没有什么不同,只是把顶点坐标由三个改成了6个。依次类推,如果想要绘制多边形或者更多的三角形,只需要定义不同的顶点就行了。效果:二、代码示例1.定义顶点floatvertices[18]={......
  • QT自定义结构体的传递
    方法1:使用Q_DECLARE_METATYPE(TestResult)进行声明1.1声明#ifndefTESTRESULT_H#defineTESTRESULT_H#include<QDateTime>#include<QString>#include<QMetaType>//用于测试时更新内容,作为结果导出的依据classTestResult{public:int_nid=0;int_coun......
  • 【python】PyQt5中的QFrame控件,控制图形的边框样式、阴影效果、形状等属性
    ✨✨欢迎大家来到景天科技苑✨✨......
  • qt静态编译 全自动编译qt静态库 qt5 windows安装qt (2024.2.23)
    全自动编译qt5静态库(2024.2.23)本教程是从无到有配置qt.io和vcpkg实现全自动编译qt5的静态库,使得您可以静态编译qt项目0.安装VisualStudio2022这个我就不多解释了,直接去官网下载社区版本,勾选使用C++的桌面开发安装好就行1.安装qt.io的开发环境1.1下载在线安装包并且配......
  • 【嵌入式裸机开发】智能家居入门7:最新ONENET,MQTT协议接入,最全最新(微信小程序、MQTT协
    智能家居入门7前言一、ONENET云平台创建产品与设备二、STM32端连接服务器前的准备三、STM32端实现四、微信小程序端连接服务器前的准备五、微信小程序端实现六、最终测试前言本篇文章介绍最新ONENET云平台的MQTT协议接入方法,在STM32上实现数据上云与服务器下发数据......
  • VS2022+QT6.7.2 定时器的使用(两种方法)
    目录一、继承QObject定时器事件二、QTimer类三、具体实现一、继承QObject定时器事件  所有继承自QObject的类,都会有一个timerEvent(QTimerEvent*event)的纯虚函数,startTimer()设定定时间隔并启动,再重载这个函数以处理自己的定时任务,多个定时任务用timeId区分,结束后......
  • 解决lazarus 3.xx后在linux编译为Qt出错方法
    今天用lazarus3.4在银河麒麟将应用编译为Qt5出现以下错误信息:Warning:linker:/usr/bin/ld.bfd:/home/lb/fpcupdeluxe34/lazarus/lcl/units/aarch64-linux/qt5/qtint.o:infunction`QTINT$_$TQTWIDGETSET_$__$$_CREATE$$TQTWIDGETSET':Error:qtint.pp:(.text.n_qtint$_$t......