(通过这个问题,我试图研究解决另一个问题的想法)
如果我有一个标准的二维数组,其尺寸为宽度和高度,存储在内存中,我可以将其转换为长度为宽度*高度的一维数组,然后通过index=x+y*width进行索引。当为数组分配和释放内存时,这种映射非常有用,因为内存管理器不需要担心将结构以2D方式打包,只需要关注以1D表示的每个分配数组的总长度。
我正在尝试查看是否可以将此方法用于OpenGL纹理的图像内存管理。根据上面链接的问题所描述的思路是:通过将许多所需的纹理组合成一个更大的纹理,通过装箱(即将它们绘制在一起)到大纹理中。这有助于在渲染期间最小化昂贵的纹理绑定操作。
假设我的大纹理是8×8像素(即64个像素总数):
8x8 texture: 5x5 image: 4x5 image:
| 0 1 2 3 4 5 6 7 | 0 1 2 3 4 | 0 1 2 3
---+----------------- ---+----------- ---+---------
0 | . . . . . . . . 0 | A B C D E 0 | a b c d
1 | . . . . . . . . 1 | F G H I J 1 | e f g h
2 | . . . . . . . . 2 | K L M N O 2 | i j k l
3 | . . . . . . . . 3 | P Q R S T 3 | m n o p
4 | . . . . . . . . 4 | U V W X Y 4 | q r s t
5 | . . . . . . . .
6 | . . . . . . . .
7 | . . . . . . . .
我想在一个8×8的纹理中存储一个5×5的图像和一个4×5的图像(即总共45个像素)。从技术上讲,我有足够的像素可用,但我无法将这些图像放在大纹理旁边,因为这需要至少一个方向上的最小尺寸为9,另一个方向上为5。
如果我可以将我的8×8纹理简单地视为64个连续像素的内存,并将两个图像映射到其中的一维内存块中,我可以按照以下方式在纹理内排列图像: 8x8纹理:
| 0 1 2 3 4 5 6 7
---+-----------------
0 | A B C D E F G H
1 | I J K L M N O P
2 | Q R S T U V W X
3 | Y a b c d e f g
4 | h i j k l m n o
5 | p q r s t . . .
6 | . . . . . . . .
7 | . . . . . . . .
如果我以1:1的比例绘制所有图像,即任何地方都没有分数像素坐标和不需要任何线性过滤或其他像素混合,那么是否可能想出一个转换矩阵,以便使用此纹理绘制4×5图像?
使用顶点和片元着色器,这看起来可能相当容易(除非我忘了什么;我还没有尝试):
- 顶点着色器将要绘制的图像的四个角映射到表示为64×1图像的纹理上: - a:(0, 0) → (0 + 0*4 + 25, 0) = (25, 0),其中25是4×5图像的偏移量 - d:(3, 0) → (3 + 0*4 + 25, 0) = (28, 0) - q:(0, 4) → (0 + 4*4 + 25, 0) = (41, 0) - t:(3, 4) → (3 + 4*4 + 25, 0) = (44, 0) 其他纹理内部坐标的插值应该也应该在整数坐标下沿着这条线映射到正确的偏移量。 - 片元着色器通过简单地取模和除法的商和余数将64×1坐标转换为最终的8×8坐标,例如: - a:(0, 25) → (25 % 8, 25 / 8) = (1, 3) - d:(0, 28) → (28 % 8, 28 / 8) = (4, 3) - k:(0, 35) → (35 % 8, 35 / 8) = (3, 4) - q:(0, 41) → (41 % 8, 41 / 8) = (1, 5) - t:(0, 44) → (44 % 8, 44 / 8) = (4, 5)
不幸的是,自定义着色器需要OpenGL ES v2.0或更高版本,这并非所有设备都支持。
是否可以通过OpenGL ES 1.1提供的矩阵变换仅实现此映射?