OGL纹理之多维纹理/纹理数组/压缩纹理图像/drawcall优化
来源:互联网 发布:阿里云ecs翻墙 编辑:程序博客网 时间:2024/06/06 15:35
一维纹理
有时候用一维纹理就够了,例如带纹理的镶条。一维纹理就是高度为1的二维纹理图像,并且它的顶部和底部没有边框,左右可以有。所有二维纹理和子纹理所定义的函数都存在二维版本。如果有图像处理子集卷积操作,那么也会受影响,其它像素操作也会对纹理产生影响。
1.定义一维纹理函数:
glTexImage1D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
width大小是2^(m+b),m是任意整数,b是边框0或2.
可以提供mipmap level,纹理代理,和使用相同的过滤操作。
pixels是一维数组。
2.替换一维纹理的部分或全部
glTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
3.从帧缓存区创建一个新纹理:
glCopyTexImage1D (GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border);
4.从帧缓存区替换一个现有纹理的部分或全部:
glCopyTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
这些参数含义都和二维纹理的操作一样,只是heiht是1不用设置,width大小是2^(m+b),m是任意整数,b是边框0或2.这些一维纹理的操作都会受到glPixelStore*()和glPixelTransfer*()以及其它像素传输操作所设置模式的影响。
三维纹理
三维纹理主要应用于医学和地球科学领域的渲染,例如断层计算成像系统(CT)或核磁共振成像(MRI),岩石地层建模。三维纹理是一大类应用范畴的一部分,称为体渲染(volume rendering)。有些高级体渲染程序需要处理体纹理单元(voxel)。三维纹理可以看做由一层层的二维纹理图像矩形构成,在内存中,这些矩形按顺序排列在一起。图像处理子集并不存在三维卷积,但是二维卷积过滤器也可以作用于三维纹理图像。
绝大多数二维纹理和子纹理定义函数都具有对应的三维版本。
1.定义三维纹理函数:
glTexImage3D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
定义一个三维纹理或一个二维纹理数组,所有参数都和glTexImage2D有相同的意义。不过pixels是一个三维数组,增加了三维纹理的depth值,OGL2.0以下depth必须是2^(m+b),m是任意整数,b是边框0或2,OGL2.0后 没有这个限制。可以提供mipmap level,纹理代理,和使用相同的过滤操作。
实例:
#define iWidth 16
#define iHeight 16
#define iDepth 16
static GLubyte image[iDepth][iHeight][iWidth][3];
glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB, iWidth, iHeight,
iDepth, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
2.替换一维纹理的部分或全部
glTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
pixels是一个三维纹理数组。
3.从帧缓存区替换一个现有纹理的部分或全部:
glCopyTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
从GL_READ_BUFFER帧缓存读取。
由于帧缓存中读取的是二维图像,所以帧缓存的x,y开始,width height大小的图像数据只是能够替换3D纹理(volume texture)的位于xoffset,yoffset,zoffset指定的zoffset那片的纹理图像。
这些一维纹理的操作都会受到glPixelStore*()和glPixelTransfer*()以及其它像素传输操作所设置模式的影响。
三维纹理的像素存储模式,因为引入了第三维度,所以如果需要访问纹理的不同层,就要*SKIP_IMAGES类型的参数n传递给glTexImage3D,glTexSubImage3D参数使用表示生成或替换第n层开始的纹理图像,含义是跳过nx每层的字节数,图像数据毕竟还是内存数据都符合内存数据操作。
*IMAGE_HEIGHT是一个像素存储参数,定义了三维纹理其中一层的高度, 如果*IMAGE_HEIGHT的值为0,那么每个二维纹理图像的行数都是height。
纹理数组
纹理对象需要在OGL GPU中更新,每次都调用glBindTexture,可能会影响到应用程序的性能(因此,这可能是纹理存储资源的一个短处)。纹理数组允许把一维或二维纹理的一个集合组织起来,所有的纹理都具有相同的大小,都位于更高维度的一个纹理之中(二维是三维纹理的一部分)。直接用三维纹理会导致定位索引纹理太消耗性能,且在三维纹理中的两片纹理之间进行过滤会得到异常的过滤效果, 纹理数组允许在通过索引访问的纹理中进行合适的mipmap过滤,得到比较好的效果。所以用纹理数组定位会比较快,在纹理数组中进行二维纹理之间进行合适的过滤mipmap,是有优势的。
具体使用:类似手动创建mipmap一样使用就可以了。
压缩纹理图像
纹理图像在GPU 内存中可以用一种压缩格式存储,以减少它所使用的内存数量。纹理图像可以在加载时进行压缩,也可以直接以一种压缩格式加载, 例如pvr格式( 但pvr更加优秀,体积小,加载速度快,不需要转换为RGBA格式,不使用CPU内存,ios应该对pvr格式图片在硬件层做了优化)。
在加载时候进行压缩
当创建纹理,或进行像素存储模式或像素传输模式设置时候把internalFormat参数设置为其中一种GL_COMPRESSED_*枚举值,加载到GPU纹理内存中就是以压缩形式存储的。
查询纹理是否被压缩或压缩成的形式:
GLboolean compressed;
GLenum textureFormat;
GLsizei imageSize;
glGetTexLevelParameteriv(GL_TEXTURE_2D, GL_TEXTURE_COMPRESSED, &compressed);
if (compressed)
{
glGetTexLevelParameteriv(GL_TEXTURE_2D, GL_TEXTURE_INTERNAL_FORMAT, &textureFormat);
glGetTexLevelParameteriv(GL_TEXTURE_2D, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &imageSize);
}
加载经过压缩的纹理图像
每种OGL实现,都可以指定一组OGL拓展,实现一种特定的纹理压缩格式。因此需要验证下当前使用的OGL实现支持的纹理压缩格式。
为了加载一个压缩格式存储的纹理,可以使用glCompressedTexImage*()函数。
void glCompressedTexImage1D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *data);
void glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
void glCompressedTexImage3D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
internalformat必须是OGL实现支持的压缩格式之一,否则会报GL_INVALID_ENUM错误。
width,height,depth是和未压缩的参数大小一样。
OGL3.1中,glCompressedTexImage2D target是GL_TEXTURE_RECTANGLE或GL_PROXY_TEXTURE_RECTANGLE会产生GL_INVALID_ENUM错误。
另外就像未压缩的纹理一样,可以替换一个已经加载的纹理的全部或一部分。
void glCompressedTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *data);
void glCompressedTexSubImage2 (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
void glCompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
图像draw call优化
小图合并为大图,或使用纹理数组,都可以有效的在图像像素层减少draw call。顶点层,应该也是进行mesh的合并,将所有静态的物体合并为一个大的mesh,经过一次相同的顶点运算MVP,对于不同顶点运算的尽量合并为相同的顶点运算来减少draw call。
0 0
- OGL纹理之多维纹理/纹理数组/压缩纹理图像/drawcall优化
- OGL纹理之纹理代理
- OGL纹理之纹理替换glTexSubImage2D/glCopyTexSubImage2D/纹理矩形
- OGL纹理之纹理过滤器和多级渐进纹理mipmap
- 纹理
- 纹理
- 纹理
- 纹理
- 纹理
- 纹理
- 纹理
- 纹理
- 纹理
- 纹理
- 纹理
- 纹理
- 纹理
- 纹理
- 第32章 TIM—高级定时器—零死角玩转STM32-F429系列
- POJ 1948 DP
- java读取excel
- 第34章 IWDG—独立看门狗—零死角玩转STM32-F429系列
- 预编译#ifndef #define #endif
- OGL纹理之多维纹理/纹理数组/压缩纹理图像/drawcall优化
- 第33章 TIM—电容按键检测—零死角玩转STM32-F429系列
- RemoteViews的用处
- linux下C获取文件的大小
- 第35章 WWDG—窗口看门狗—零死角玩转STM32-F429系列
- 第36章 SDIO—SD卡读写测试—零死角玩转STM32-F429系列
- 第37章 基于SD卡的FatFs文件系统—零死角玩转STM32-F429系列
- 第38章 I2S—音频播放与录音输入—零死角玩转STM32-F429系列
- 第39章 ETH—Lwip以太网通信—零死角玩转STM32-F429系列