OpenGL超级宝典学习笔记:纹理

news2024/11/28 14:51:44
前言
本篇在讲什么

本篇章记录对OpenGL中纹理使用的学习
本篇适合什么

适合初学OpenGL的小白
本篇需要什么

C++语法有简单认知
OpenGL有简单认知
最好是有OpenGL超级宝典蓝宝书
依赖Visual Studio编辑器

本篇的特色

具有全流程的图文教学
重实践,轻理论,快速上手
提供全流程的源码内容


★提高阅读体验★

👉 ♠ 一级标题 👈

👉 ♥ 二级标题 👈

👉 ♣ 三级标题 👈

👉 ♦ 四级标题 👈


目录

  • ♠ 纹理
    • ♥ 创建并初始化纹理
    • ♥ 更新纹理数据
    • ♥ 纹理目标和类型
    • ♥ 读取纹理数据
    • ♥ 采样器类型
    • ♥ 演示示例
    • ♥ 从文件载入纹理
    • ♥ 案例分析
  • ♠ 推送
  • ♠ 结语


♠ 纹理

纹理是一种结构化的存储形式,可供着色器读写,常用于存储图像数据,我们常见的png、jpg等图片存储的也是图像数据,只不过是经过编码的数据,不能直接被GPU使用,而纹理格式可以直接被GPU读取渲染


♥ 创建并初始化纹理

在下面的代码中我们对一个纹理进行生成、初始化和绑定的操作

// The type used for names in OpenGL is GLuint
GLuint texture;

// Generate a name for the texture
glGenTextures(1, &texture);

// Now bind it to the context using the GL_TEXTURE_2D binding point
glBindTexture(GL_TEXTURE_2D, texture);

// Specify the amount of storage we want to use for the texture
glTexStorage2D(GL_TEXTURE_2D,    // 2D texture
               1,                // 1 mipmap level
               GL_RGBA32F,       // 32-bit floating-point RGBA data
               256, 256);        // 256 x 256 texels

要点1:通过glGenTextures接口创建一个纹理
要点2:通过glBindTexture将纹理绑定到上下文
要点3:通过glTexStorage2D分配纹理的格式和需要的内存空间


♥ 更新纹理数据

在纹理初始化完成后,我们为其更新数据

// Define some data to upload into the texture
float * data = new float[256 * 256 * 4];

// generate_texture() is a function that fills memory with image data
generate_texture(data, 256, 256);

// Assume the texture is already bound to the GL_TEXTURE_2D target
glTexSubImage2D(GL_TEXTURE_2D,  // 2D texture
                0,              // Level 0
                0, 0,           // Offset 0, 0
                256, 256,       // 256 x 256 texels, replace entire image
                GL_RGBA,        // Four channel data
                GL_FLOAT,       // Floating point data
                data);          // Pointer to data

// Free the memory we allocated before - \GL now has our data
delete [] data;

要点1:通过generate_texture用图像数据填充内存
要点2:通过glTexSubImage2D更新纹理数据


♥ 纹理目标和类型

在上文中我们展示了通过GL_TEXTURE_2D来创建和绑定2D纹理目标,其实还有更多的类型,例如可以通过GL_TEXTURE_2DGL_TEXTURE_3D创建一维和三维纹理,下图展示纹理目标类型

纹理目标(GL_TEXTURE_*)说明
1D一维纹理
2D二维纹理
3D三维纹理
RECTANGLE矩形纹理
1D_ARRAY一维数组纹理
2D_ARRAY二维数组纹理
CUBE_MAP立方体贴图纹理
CUBE_MAP_ARRAY立方体贴图数组纹理
BUFFER缓冲纹理
2D_MULTISAMPLE二维多重采样纹理
2D_MULTISAMPLE_ARRAY二维数组多重采样纹理

♥ 读取纹理数据

存储数据后我们就可以读取数据,用于着色片段,着色器中的纹理以采样器变量形式存在,通用以取样器类型声明统一变量与外界相连接

表示二维纹理的采样器类型为sampler2D即对应我们上文绑定的目标GL_TEXTURE_2D,下列片段着色器代码演示如何读取纹理

"#version 430 core                                                              \n"
"                                                                               \n"
"uniform sampler2D s;                                                           \n"
"                                                                               \n"
"out vec4 color;                                                                \n"
"                                                                               \n"
"void main(void)                                                                \n"
"{                                                                              \n"
"    color = texture(s, gl_FragCoord.xy / textureSize(s, 0));                   \n"
"}   

要点1:采样器类型sampler2D是二维纹理类型
要点2:内置函数texture从纹理中抓取颜色数据


♥ 采样器类型

如前文所述,纹理的每个维度都有一个目标点用于绑定纹理对象,每个目标都有对应的采样器类型,下面列表展示目标点和其对应的采样器类型

纹理目标采样器类型
GL_TEXTURE_1Dsample1D
GL_TEXTURE_2Dsample2D
GL_TEXTURE_3Dsample3D
GL_TEXTURE_RECTANGLEsample2Drect
GL_TEXTURE_1D_ARRAYsample1Darray
GL_TEXTURE_2D_ARRAYsample2Darray
GL_TEXTURE_CUBE_MAPsampleCube
GL_TEXTURE_CUBE_MAP_ARRAYsampleCubeArray
GL_TEXTURE_BUFFERsampleBuffer
GL_TEXTURE_2D_MULTISAMPLEsample2DMS
GL_TEXTURE_2D_MULTISAMPLE_ARRAYsample2DMSArray

♥ 演示示例

全文代码这里粘了,具体参考OpenGL蓝宝书官方演示示例simpletexture,示例内包含和上文相同的代码,下图为效果图

在这里插入图片描述


♥ 从文件载入纹理

在上文我们已经学习到了通过编码生成纹理数据,但这并不符合实际应用中的情况,现实中我们往往是通过文件载入纹理数据,这一块,我们学习如何通过加载.ktx文件,显示纹理

#include <sb7ktx.h>

// generate_texture() is a function that fills memory with image data
//generate_texture(data, 256, 256);

texture = sb7::ktx::file::load("media/textures/pattern1.ktx");

在这里插入图片描述

这里我们只需要通过sb7::ktx::file::load方法加载ktx文件即可,返回值附加给我们的texture

注意:上述代码修改自超级宝典第七版例子simpletexture,generate_texture生成纹理数据替换成文件加载,就可以得到上图所示的效果,我们文件的纹理填充到三角形里面了


♥ 案例分析

官方提供了一个加载外星人图片的例子alienrain,运行效果如下图所示,我们简单分析一下

在这里插入图片描述

  • 随机的速度、角度、偏移
for (int i = 0; i < 256; i++)
{
    droplet_x_offset[i] = random_float() * 2.0f - 1.0f;
    droplet_rot_speed[i] = (random_float() + 0.5f) * ((i & 1) ? -3.0f : 3.0f);
    droplet_fall_speed[i] = random_float() + 0.2f;
}

给数组内生成了一组随机的速度、角度、偏移值,并绑定到统一变量的缓存内

  • 从本地加载外星人纹理
tex_alien_array = sb7::ktx::file::load("media/textures/aliens.ktx");
glBindTexture(GL_TEXTURE_2D_ARRAY, tex_alien_array);

从本地ktx文件内加载一组外星人纹理数据,绑定到纹理缓存数据内

  • 顶点着色器
"layout (location = 0) in int alien_index;    

用来从纹理数组取数据的下标

out VS_OUT                                                   
{                                                            
    flat int alien;                                          
    vec2 tc;                                                
} vs_out;                           

记录外星人纹理数据的下标

layout (std140) uniform droplets         
{                                        
    droplet_t droplet[256];              
};             

存储随机数值的统一变量

  • 片段着色器
layout (location = 0) out vec4 color;                                            
in VS_OUT                                               
{                                                           
    flat int alien;                                           
    vec2 tc;  
} fs_in;                                                               
uniform sampler2DArray tex_aliens;                                     
void main(void)                                               
{                                                             
    color = texture(tex_aliens, vec3(fs_in.tc, float(fs_in.alien)));   
}                       

根据顶点着色器传过来的外星人纹理数据的下标,从纹理数据缓存里取对应的纹理数据显示

  • 创建外星人纹理
int alien_index;
for (alien_index = 0; alien_index < 256; alien_index++)
{
    glVertexAttribI1i(0, alien_index);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}

在render方法里没帧都会循环给alien_index赋0-255的值,对应顶点着色器里的外星人的alien_index,所以没帧都会有255个外星人生成


♠ 推送

  • Github
https://github.com/KingSun5

♠ 结语

若是觉得博主的文章写的不错,不妨关注一下博主,点赞一下博文,另博主能力有限,若文中有出现什么错误的地方,欢迎各位评论指摘。

👉 本文属于原创文章,转载请评论留言,并在转载文章头部著名作者出处👈

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

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

相关文章

MP4文件播放不了是什么原因?原因及解决办法分享!

为什么mp4文件播放不了&#xff1f;常见的有三种原因&#xff0c;可能是由于视频流或音频流不兼容导致&#xff0c;可能是由于视频文件损坏&#xff0c;也可能是因为电脑上缺乏编解码器。下面小编根据mp4文件无法播放的三种可能进行针对性解答。 原因一&#xff1a;视频流或音频…

基于SSM的学生竞赛模拟系统

基于SSM的学生竞赛模拟系统 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&#x…

DPU54国产全速USB1.1HUB控制器芯片替代AU9254

目录DPU54简介结构框图DPU54主要特性性能特点典型应用领域DPU54简介 DPU54是高性能、低功耗4口全速 USB1.1 HUB 控制器芯片&#xff0c;上行端口兼容全速 12MHz 模式&#xff0c;4 个下行端口兼容全速 12MHz、低速 1.5MHz 两种模式。 DPU54采用状态机单事务处理架构&#xff0…

windows 11系统,通过ip地址远程连接连接ubuntu 22.04系统(共同局域网下,另一台主机不需要联网)

windows 11系统&#xff0c;通过ip地址远程连接连接ubuntu 22.04系统&#xff08;不需要联网&#xff09;问题来源问题分析解决方案问题来源 自己搭建了一台ubuntu系统作为深度学习的机器&#xff0c;但是学校的网络问题&#xff0c;一个账号只能同时登录3台设备。通过远程连接…

C#完全掌握控件之-combbox

无论是QT还是VC&#xff0c;这些可视化编程的工具&#xff0c;掌握好控件的用法是第一步&#xff0c;C#的控件也不例外&#xff0c;尤其这些常用的控件。常见控件中较难的往往是这些与数据源打交道的&#xff0c;比如CombBox、ListBox、ListView、TreeView、DataGridView. 文章…

JUC并发编程之HashMap(jdk1.7版本)-底层源码探究

目录 JUC并发编程之HashMap(jdk1.7版本)-底层源码探究 HashMap底层源码 - jdk1.7 基本概念 -采取层层递进&#xff0c;问答式 存储Key-Value的结构 常量和成员变量 构造方法 put方法 inflateTable方法 hash方法 indexFor方法 addEntry方法 resize方法 createEntry…

JVM 运行时数据区(数据区组成表述,程序计数器,java虚拟机栈,本地方法栈)

JVM 运行时数据区JVM 运行时数据区3.1运行时的数据区组成概述3.1.1程度计数器3.1.2java虚拟机栈3.1.3本地方法栈3.1.4java堆3.1.5方法区3.2程序计数器3.3java虚拟机栈3.4本地方法栈JVM 运行时数据区 堆,方法区(元空间) 主要用来存放数据 是线程共享的. 程序计数器,本地方法栈…

Leetcode.1590 使数组和能被 P 整除

题目链接 Leetcode.1590 使数组和能被 P 整除 Rating &#xff1a; 2039 题目描述 给你一个正整数数组 nums&#xff0c;请你移除 最短 子数组&#xff08;可以为 空&#xff09;&#xff0c;使得剩余元素的 和 能被 p整除。 不允许 将整个数组都移除。 请你返回你需要移除的…

Java中IO流中字节流(FileInputStream(read、close)、FileOutputStream(write、close、换行写、续写))

IO流&#xff1a;存储和读取数据的解决方案 纯文本文件&#xff1a;Windows自带的记事本打开能读懂 IO流体系&#xff1a; FileInputStream&#xff1a;操作本地文件的字节输入流&#xff0c;可以把本地文件中的数据读取到程序中来 书写步骤&#xff1a;①创建字节输入流对象 …

cento7安装docker

1.环境说明 root用户&#xff0c;centos7内核版本&#xff1a;3.10.0-1160.88.1.el7.x86_64 可通过一下命令查看当前内核版本 [rootlocalhost ~]# uname -r 3.10.0-1160.88.1.el7.x86_64 这里内核版本为3.10&#xff0c;Linux版本为centos7。 2.使用root命令更新yum包 注意​ …

Redis高频面试题汇总(中)

目录 1.什么是redis事务&#xff1f; 2.如何使用 Redis 事务&#xff1f; 3.Redis 事务为什么不支持原子性 4.Redis 事务支持持久性吗 5.Redis事务基于lua脚本的实现 6.Redis集群的主从复制模型是怎样的&#xff1f; 7.Redis集群中&#xff0c;主从复制的数据同步的步骤 …

有没有好用的设备管理系统推荐?不妨看看这6款

有没有好用的设备管理系统推荐&#xff1f;不妨看看这6款&#xff01; 在现代社会中&#xff0c;软件已经成为了企业信息化、设备管理等方面必不可少的工具。而设备管理系统是将信息化了设备技术信息与现代化管理相结合&#xff0c;是实现研究级管理信息化的先导。 对于设备管…

p79 Python 开发-sqlmapapiTamperPocsuite

数据来源​​​​​​本文仅用于信息安全学习&#xff0c;请遵守相关法律法规&#xff0c;严禁用于非法途径。若观众因此作出任何危害网络安全的行为&#xff0c;后果自负&#xff0c;与本人无关。 # 知识点&#xff1a; Request 爬虫技术&#xff0c;Sqlmap 深入分析&#x…

一文梳理深度学习算法演进

分享一篇深度学习算法演进史的纯干货文章&#xff0c;涉及语音、图像、nlp、强化学习、隐私保护、艺术创作、目标检测、医疗、压缩序列、推荐排序等方向。文章较长&#xff0c;干货满满&#xff0c;建议收藏1. 前言如果说高德纳的著作奠定了第一代计算机算法&#xff0c;那么传…

Vue3.0导出数据为自定义样式Excel

前言当下开发web应用系统的时候&#xff0c;我们往往会遇到需要把网页上面的数据导出到excel这样的需求&#xff0c;真实的企业项目里对应一些导出财务报表、员工信息、交易记录、考勤打卡记录…等等需求&#xff0c;本文将对此做探讨。开始前补充&#xff1a; 网上是有些牛人已…

【IoT】项目管理:如何做好端到端的项目管理?

今天主要来谈谈项目管理这个话题。 首先来看一个我在网络上看到的一个关于项目管理的案例或者是段子。 将项目管理的作用及意义非常直观地展示了出来。 有一个植树搞绿化的企业&#xff0c;在公司内部设置有五个部门&#xff0c;分别是&#xff1a; 运输部门&#xff1b;挖坑部…

nginx 平滑升级

背景介绍 因为一些原因&#xff0c;比如说 Nginx 发现漏洞、应用一些新的模块等等&#xff0c;想对 Nginx 的版本进行更新&#xff0c;最简单的做法就是停止当前的 Nginx 服务&#xff0c;然后开启新的 Nginx 服务。但是这样会导致在一段时间内&#xff0c;用户是无法访问服务…

2023/3/10 Vue核心知识的学习- Vue - v-model双向绑定原理

https://www.jianshu.com/p/2682b5a26869 定义&#xff1a;vue中双向绑定就是指v-model指令&#xff0c;可以绑定一个响应式数据到视图&#xff0c;同时视图中变化能同步改变该值。 通过Object.defineProperty( )对属性设置一个set函数&#xff0c;当数据改变了就会来触发这个…

索引设计的一些小技巧(上)

文章目录 主键索引为频繁查询的字段建立索引避免为"大字段"建立索引选择区分度大的列作为索引尽量为ORDER BY 和 GROUP BY 后面的字段建立索引不要在条件中使用函数不要建立太多的索引频繁增删改的字段不要建立索引索引失效的常见场景主键索引 大家在设计主键的时候…

数据安全—数据完整性校验

1、数据安全保障三要素即 保密性 完整性、可用性机密性&#xff1a;要求数据不被他人轻易获取&#xff0c;需要进行数据加密。完整性&#xff1a;要求数据不被他人随意修改&#xff0c;需要进行签名技术可用性&#xff1a;要求服务不被他人恶意攻击&#xff0c;需要进行数据校验…