广州智能建站,北京网站推广排名,教育网站制作定制,wordpress搭建技术论坛前言 本篇在讲什么 本篇章记录对OpenGL中纹理使用的学习 本篇适合什么 适合初学OpenGL的小白 本篇需要什么 对C语法有简单认知 对OpenGL有简单认知 最好是有OpenGL超级宝典蓝宝书 依赖Visual Studio编辑器 本篇的特色 具有全流程的图文教学 重实践#xff0c;轻理… 前言 本篇在讲什么 本篇章记录对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 texture1, // 1 mipmap levelGL_RGBA32F, // 32-bit floating-point RGBA data256, 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 texture0, // Level 00, 0, // Offset 0, 0256, 256, // 256 x 256 texels, replace entire imageGL_RGBA, // Four channel dataGL_FLOAT, // Floating point datadata); // 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_2D和GL_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
{ \ncolor texture(s, gl_FragCoord.xy / textureSize(s, 0)); \n
} 要点1采样器类型sampler2D是二维纹理类型 要点2内置函数texture从纹理中抓取颜色数据 ♥ 采样器类型
如前文所述纹理的每个维度都有一个目标点用于绑定纹理对象每个目标都有对应的采样器类型下面列表展示目标点和其对应的采样器类型
纹理目标采样器类型GL_TEXTURE_1Dsample1DGL_TEXTURE_2Dsample2DGL_TEXTURE_3Dsample3DGL_TEXTURE_RECTANGLEsample2DrectGL_TEXTURE_1D_ARRAYsample1DarrayGL_TEXTURE_2D_ARRAYsample2DarrayGL_TEXTURE_CUBE_MAPsampleCubeGL_TEXTURE_CUBE_MAP_ARRAYsampleCubeArrayGL_TEXTURE_BUFFERsampleBufferGL_TEXTURE_2D_MULTISAMPLEsample2DMSGL_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
注意上述代码修改自超级宝典第七版例子simpletexturegenerate_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♠ 结语
若是觉得博主的文章写的不错不妨关注一下博主点赞一下博文另博主能力有限若文中有出现什么错误的地方欢迎各位评论指摘。 本文属于原创文章转载请评论留言并在转载文章头部著名作者出处