qt QOpenGLTexture详解

news2025/3/24 12:49:05
1. 概述

QOpenGLTexture 是 Qt5 提供的一个类,用于表示和管理 OpenGL 纹理。它封装了 OpenGL 纹理的创建、分配存储、绑定和设置像素数据等操作,简化了 OpenGL 纹理的使用。

2. 重要函数
  • 构造函数

    • QOpenGLTexture(const QImage &image, QOpenGLTexture::MipMapGeneration genMipMaps = GenerateMipMaps)

    • QOpenGLTexture(QOpenGLTexture::Target target)

  • 纹理配置

    • void allocateStorage()

    • void allocateStorage(QOpenGLTexture::PixelFormat pixelFormat, QOpenGLTexture::PixelType pixelType)

    • void setFormat(QOpenGLTexture::TextureFormat format)

    • void setLayers(int layers)

    • void setSize(int width, int height = 1, int depth = 1)

  • 绑定和解绑

    • void bind()

    • void bind(uint unit, QOpenGLTexture::TextureUnitReset reset = DontResetTextureUnit)

    • void release()

    • void release(uint unit, QOpenGLTexture::TextureUnitReset reset = DontResetTextureUnit)

  • 设置像素数据

    • void setData(int mipLevel, QOpenGLTexture::PixelFormat sourceFormat, QOpenGLTexture::PixelType sourceType, const void *data, const QOpenGLPixelTransferOptions *const options = nullptr)

    • void setData(const QImage &image, QOpenGLTexture::MipMapGeneration genMipMaps = GenerateMipMaps)

  • 生成 Mipmaps

    • void generateMipMaps()

    • void generateMipMaps(int baseLevel, bool resetBaseLevel = true)

  • 获取纹理属性

    • int width() const

    • int height() const

    • int depth() const

    • GLuint textureId() const

3. 常用枚举类型
  • BindingTarget:纹理绑定目标,如 BindingTarget2DBindingTargetCubeMap 等。

  • ComparisonFunction:深度和模板比较函数。

  • ComparisonMode:比较模式,如 CompareRefToTexture

  • CubeMapFace:立方体贴图的各个面,如 CubeMapPositiveX

  • DepthStencilMode:深度和模板模式。

  • Feature:纹理特性,如 TextureRectangleTextureArrays

  • Filter:纹理过滤方式,如 NearestLinear

  • MipMapGeneration:是否生成 Mipmaps,GenerateMipMapsDontGenerateMipMaps

  • PixelFormat:像素格式,如 RGBA8888

  • PixelType:像素类型,如 UnsignedByte

  • SwizzleComponent:颜色通道,如 SwizzleRed

  • SwizzleValue:颜色值,如 RedValue

  • Target:纹理目标,如 Target2D

  • TextureFormat:纹理格式,如 RGB8_UNorm

  • WrapMode:纹理环绕模式,如 RepeatClampToEdge

#include "widget.h"

float vertices[] = {
    // positions          // colors           // texture coords
     0.5f,  0.5f, 0.0f,   1.0f, 0.0f, 0.0f,   1.0f, 1.0f, // top right
     0.5f, -0.5f, 0.0f,   0.0f, 1.0f, 0.0f,   1.0f, 0.0f, // bottom right
    -0.5f, -0.5f, 0.0f,   0.0f, 0.0f, 1.0f,   0.0f, 0.0f, // bottom left
    -0.5f,  0.5f, 0.0f,   1.0f, 1.0f, 0.0f,   0.0f, 1.0f  // top left
};
unsigned int indices[] = {
    0, 1, 3, // first triangle
    1, 2, 3  // second triangle
};


MyGLWidget::MyGLWidget(QWidget *parent) : QOpenGLWidget(parent)
{

}

MyGLWidget::~MyGLWidget()
{
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteBuffers(1, &EBO);
}

void MyGLWidget::initializeGL()
{
    initializeOpenGLFunctions(); // 初始化 OpenGL 函数

    bool success;
    m_shaderProgram.addShaderFromSourceFile(QOpenGLShader::Vertex,":/shader/shader.vert");
    m_shaderProgram.addShaderFromSourceFile(QOpenGLShader::Fragment,":/shader/shader.frag");
    success=m_shaderProgram.link();
    if(!success) qDebug()<<"ERR:"<<m_shaderProgram.log();

    //创建、绑定VAO
    glGenVertexArrays(1, &VAO);
    glBindVertexArray(VAO);

    //创建、绑定VBO + 填充数据
    glGenBuffers(1, &VBO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    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);

    //解绑缓冲区和 VAO
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

    //创建、绑定纹理
    m_diffuseTex = new QOpenGLTexture(QImage(":/img/container.png").mirrored());
    m_specularTex = new QOpenGLTexture(QImage(":/img/awesomeface.png").mirrored());
    m_shaderProgram.bind();
    m_shaderProgram.setUniformValue("texture1", 0);
    m_shaderProgram.setUniformValue("texture2", 1);;
}

void MyGLWidget::paintGL()
{
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT); // 清除颜色缓冲区

    m_shaderProgram.bind();
    m_diffuseTex->bind(0);
    m_specularTex->bind(1);

    glBindVertexArray(VAO);
    //glDrawArrays(GL_TRIANGLES, 0, 3);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

    glBindVertexArray(0);
}

void MyGLWidget::resizeGL(int w, int h)
{
    glViewport(0, 0, w, h); // 设置视口大小
}

unsigned int MyGLWidget::loadTexture(const char *fileName, bool alpha)
{
    unsigned int texture;
    glGenTextures(1, &texture); // 生成纹理 ID
    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_LINEAR_MIPMAP_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
#if 0
    // 加载图片并转换为 OpenGL 格式
    QImage image;
    if (!image.load(fileName))
    {
        qWarning() << "Failed to load texture image";
        return 0;
    }
    image = QGLWidget::convertToGLFormat(image); // 转换为 OpenGL 格式
    unsigned char *data = image.bits();
    // 生成纹理
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
    glGenerateMipmap(GL_TEXTURE_2D); // 生成多级渐远纹理
#else

    QFile file(fileName);
    file.copy(file.fileName(), QFileInfo(file).fileName());

    int width, height, nrChannels;
    stbi_set_flip_vertically_on_load(true); // tell stb_image.h to flip loaded texture's on the y-axis.
    unsigned char *data = stbi_load(QFileInfo(file).fileName().toStdString().c_str(), &width, &height, &nrChannels, 0);
    if (data)//awesomeface  container
    {
        if(alpha)
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
        else
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
        glGenerateMipmap(GL_TEXTURE_2D);
    }
    else
    {
        std::cout << "Failed to load texture1" << std::endl;
    }
    stbi_image_free(data);
#endif
    return texture;
}

觉得有帮助的话,打赏一下呗。。

           

需要商务合作(定制程序)的欢迎私信!! 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2300208.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Deepseek-R1推理模型API接入调用指南 ChatGPT Web Midjourney Proxy 开源项目接入Deepseek教程

DeepSeek-R1和OpenAI o1模型都属于推理任务模型&#xff0c;两个模型各有优点&#xff1a;DeepSeek-R1 在后训练阶段大规模使用了强化学习技术&#xff0c;在仅有极少标注数据的情况下&#xff0c;极大提升了模型推理能力。在数学、代码、自然语言推理等任务上&#xff0c;性能…

蓝耘智算携手DeepSeek,共创AI未来

&#x1f31f; 各位看官号&#xff0c;我是egoist2023&#xff01; &#x1f30d; 种一棵树最好是十年前&#xff0c;其次是现在&#xff01; &#x1f680; 今天来学习如何通过蓝耘智算使用DeepSeek R1模型 &#x1f44d; 如果觉得这篇文章有帮助&#xff0c;欢迎您一键三连&a…

【网络编程】之数据链路层

【网络编程】之数据链路层 数据链路层基本介绍基本功能常见协议 以太网什么是以太网以太网协议帧格式数据链路层的以太网帧报文如何封装/解封装以及分用以太网通信原理传统的以太网与集线器现代以太网与交换机碰撞域的概念 Mac地址基本概念为什么要使用Mac地址而不是使用IP地址…

EasyExcel 复杂填充

EasyExcel ​Excel表格中用{}或者{.} 来表示包裹要填充的变量&#xff0c;如果单元格文本中本来就有{、}左右大括号&#xff0c;需要在括号前面使用斜杠转义\{ 、\}。 ​代码中被填充数据的实体对象的成员变量名或被填充map集合的key需要和Excel中被{}包裹的变量名称一致。 …

通过VSCode直接连接使用 GPT的编程助手

GPT的编程助手在VSC上可以直接使用 选择相应的版本都可以正常使用。每个月可以使用40条&#xff0c;超过限制要付费。 如下图对应的4o和claude3.5等模型都可以使用。VSC直接连接即可。 配置步骤如下&#xff1a; 安装VSCODE 直接&#xff0c;官网下载就行 https://code.vis…

【算法与数据结构】并查集详解+题目

目录 一&#xff0c;什么是并查集 二&#xff0c;并查集的结构 三&#xff0c;并查集的代码实现 1&#xff0c;并查集的大致结构和初始化 2&#xff0c;find操作 3&#xff0c;Union操作 4&#xff0c;优化 小结&#xff1a; 四&#xff0c;并查集的应用场景 省份…

Java 集合数据处理技巧:使用 Stream API 实现多种操作

​ 在 Java 开发中&#xff0c;对集合数据进行处理是非常常见的需求&#xff0c;例如去重、排序、分组、求和等。Java 8 引入的 Stream API 为我们提供了一种简洁、高效的方式来处理集合数据。本文将详细介绍如何使用 Stream API 实现多种集合数据处理操作&#xff0c;并给出相…

OSI 参考模型和 TCP/IP 参考模型

数据通信是很复杂的&#xff0c;很难在一个协议中完成所有功能。因此在制定协议时经常采用的思路是将复杂的数据通信功能由若干协议分别完成&#xff0c;然后将这些协议按照一定的方式组织起来。最典型的是采用分层的方式来组织协议&#xff0c;每一层都有一套清晰明确的功能和…

SD NAND 的 SDIO在STM32上的应用详解(上篇)

目录 上篇&#xff1a; 一.SDIO简介 二.SD卡简介/内部结构 1.SD卡/SD NAND引脚 2.SD卡寄存器 3.FLASH存储器 三.SDIO总线拓扑 中篇&#xff1a; 四.SDIO功能框图(重点) 1.SDIO适配器 2.控制单元 3.命令通道(重点) 4.数…

基于图像处理的裂缝检测与特征提取

一、引言 裂缝检测是基础设施监测中至关重要的一项任务,尤其是在土木工程和建筑工程领域。随着自动化技术的发展,传统的人工巡检方法逐渐被基于图像分析的自动化检测系统所取代。通过计算机视觉和图像处理技术,能够高效、精确地提取裂缝的几何特征,如长度、宽度、方向、面…

执行pnpm run dev报错:node:events:491 throw er; // Unhandled ‘error‘ event的解决方案

vite搭建的vue项目&#xff0c;使用pnpm包管理工具&#xff0c;执行pnpm run dev&#xff0c;报如下错误&#xff1a; 报错原因&#xff1a; pnpm依赖安装不完整&#xff0c;缺少esbuild.exe文件&#xff0c;导致无法执行启动命令。 解决方案&#xff1a; 根据错误提示中提到…

「软件设计模式」建造者模式(Builder)

深入解析建造者模式&#xff1a;用C打造灵活对象构建流水线 引言&#xff1a;当对象构建遇上排列组合 在开发复杂业务系统时&#xff0c;你是否经常面对这样的类&#xff1a;它有20个成员变量&#xff0c;其中5个是必填项&#xff0c;15个是可选项。当用户需要创建豪华套餐A&…

uniapp 安卓10+ 选择并上传文件

plus.io.chooseFile({title: 选择文件,filetypes: [mp3], // 允许的文件类型multiple: false, // 是否允许多选}, (res) > {console.log(虚拟路径666&#xff1a;, res);var arr[{name: files,uri: res.files[0],}]let obj {"tableName": "mingmen_daily_mi…

【第1章:深度学习概览——1.6 深度学习框架简介与选择建议】

嘿,各位老铁们,今天咱们来一场深度学习框架的深度探索之旅。在这个充满无限可能的深度学习时代,深度学习框架就像是连接理论与实践的桥梁,帮助我们从算法设计走向实际应用。随着技术的飞速发展,深度学习框架的选择变得越来越多样化,每一种框架都有其独特的优势和适用场景…

网页制作02-html,css,javascript初认识のhtml的文字与段落标记

用一首李白的将进酒,对文字与段落标记进行一个简单的介绍演示&#xff1a; 目录 一、标题字 1、标题字标记h 2、标题字对其属性align 二、文本基本标记 1、字体属性face 2、字号属性size 3、颜色属性 Color 三、文本格式化标记 1、粗体标记 b &#xff0c;strong 2、…

一.数据治理理论架构

1、数据治理核心思想&#xff1a; 数据治理理论架构图描绘了一个由顶层设计、管控机制、核心领域和管理系统四个主要部分组成的数据治理框架。它旨在通过系统化的方法&#xff0c;解决数据治理机制缺失引发的业务和技术问题&#xff0c;并最终提升企业的数据管理水平。 数据治…

PHP基础部分

但凡是和输入、写入相关的一定要预防别人植入恶意代码! HTML部分 语句格式 <br> <hr> 分割符 <p>插入一行 按住shift 输入! 然后按回车可快速输入html代码(VsCode需要先安装live server插件) html:<h1>标题 数字越大越往后</h1> <p…

人工智能 - 主动视觉可能就是你所需要的:在双臂机器人操作中探索主动视觉

AV-ALOHA 系统使用用于 AV 的 VR 耳机实现直观的数据收集&#xff0c;并且 用于作的 VR 控制器或引线臂。这有助于捕捉全身和头部 远程作我们的真实和模拟系统的运动&#xff0c;记录来自 6 个的视频 不同的摄像头&#xff0c;并为我们的 AV 仿制学习策略提供训练数据。 加州大…

DeepSeek 助力 Vue 开发:打造丝滑的日期选择器(Date Picker),未使用第三方插件

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 Deep…

Kafka偏移量管理全攻略:从基础概念到高级操作实战

#作者&#xff1a;猎人 文章目录 前言&#xff1a;概念剖析kafka的两种位移消费位移消息的位移位移的提交自动提交手动提交 1、使用--to-earliest重置消费组消费指定topic进度2、使用--to-offset重置消费offset3、使用--to-datetime策略指定时间重置offset4、使用--to-current…