假设我们有一张纹理(这种情况下是8x8像素),我们想要将其用作精灵表。其中一个子图像(精灵)是纹理内的4x3子区域,就像这张图片中所示:
(显示了四个角的规范化纹理坐标)
现在,基本上有两种方法可以为一个4px x 3px大小的四边形分配纹理坐标,使其有效地成为我们要寻找的精灵; 第一种最直接的方法是在子区域的角落采样纹理:
// Texture coordinates
GLfloat sMin = (xIndex0 ) / imageWidth;
GLfloat sMax = (xIndex0 + subregionWidth ) / imageWidth;
GLfloat tMin = (yIndex0 ) / imageHeight;
GLfloat tMax = (yIndex0 + subregionHeight) / imageHeight;
尽管在最初实现这种方法时(大约在2010年左右),我意识到精灵看起来略微“扭曲”。经过一番搜索,我看到了一个在cocos2d论坛上的帖子,解释了渲染精灵时采样纹理的“正确方法”:
// Texture coordinates
GLfloat sMin = (xIndex0 + 0.5) / imageWidth;
GLfloat sMax = (xIndex0 + subregionWidth - 0.5) / imageWidth;
GLfloat tMin = (yIndex0 + 0.5) / imageHeight;
GLfloat tMax = (yIndex0 + subregionHeight - 0.5) / imageHeight;
我修复了代码后,感到满意了一段时间。但是在某个时候,我开始觉得我的精灵看起来不好,我相信这可能与iOS 5的引入有关。经过一些测试,我切换回“蓝色”方法(第二张图片),现在它们似乎看起来不错,但并非总是如此。
我是不是疯了,或者iOS 5有什么变化与GL ES纹理映射有关?也许我还做错了其他事情?(例如,顶点位置坐标略微偏移?错误的纹理设置参数?)但我的代码库没有改变,所以也许我从一开始就错了……
我的意思是,至少对于我的代码来说,“红色”方法曾经是正确的,但现在“蓝色”方法给出了更好的结果,这让我感觉很奇怪。
现在,我的游戏看起来还可以,但我觉得有些地方必须尽快解决……
有什么想法/经验/意见吗?
补充说明
要渲染上面的精灵,我会在正交投影中绘制一个4x3的四边形,每个顶点分配了在之前提到的代码中暗示的纹理坐标,如下所示:
// Top-Left Vertex
{ sMin, tMin };
// Bottom-Left Vertex
{ sMin, tMax };
// Top-Right Vertex
{ sMax, tMin };
// Bottom-right Vertex
{ sMax, tMax };
原始的四边形从(-0.5, -0.5)到(+0.5, +0.5)创建; 即它是屏幕中心的单位正方形,然后缩放到子区域的大小(在这种情况下为4x3),并将其中心定位于整数(x,y)坐标。我闻到了这个也有关系,特别是当宽度、高度或两者都不是偶数时?
附录2
我也发现了这篇文章,但我还在努力理解(这里是凌晨4点) http://www.mindcontrol.org/~hplus/graphics/opengl-pixel-perfect.html