纹理采样坐标以渲染精灵

时间:2012-07-12 17:33:41

标签: ios ios5 opengl-es sprite textures

假设我们有一个纹理(在这种情况下是8x8像素)我们想要用作精灵表。其中一个子图像(精灵)是纹理内部的4x3子区域,如下图所示:

enter image description here

(显示四个角的标准化纹理坐标)

现在,基本上有两种方法可以将纹理坐标分配给4px x 3px大小的四边形,以便它有效地成为我们正在寻找的精灵;第一个也是最直接的是在子区域的角落采样纹理:

enter image description here

// Texture coordinates

GLfloat sMin = (xIndex0                  ) / imageWidth;
GLfloat sMax = (xIndex0 + subregionWidth ) / imageWidth;
GLfloat tMin = (yIndex0                  ) / imageHeight;
GLfloat tMax = (yIndex0 + subregionHeight) / imageHeight;

虽然在第一次实施这种方法时, 2010年,我意识到精灵看起来有些“扭曲”。经过一番搜索后,我在cocos2d论坛上发现了一篇文章,解释了渲染精灵时采样纹理的“正确方法”是:

enter image description here

// 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 ES相关的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)坐标。我觉得这有什么可做的,特别是当宽度,高度或两者都不均匀时?

ADDENDUM 2

我也找到了这篇文章,但我还是想把它放在一起(这是凌晨4点) http://www.mindcontrol.org/~hplus/graphics/opengl-pixel-perfect.html

1 个答案:

答案 0 :(得分:9)

对于这张照片而言,与眼睛相比,纹理坐标不是纹理采样的唯一因素。在你的情况下,我相信蓝色可能是想要的。

您最终想要的是对中心的每个纹素进行采样。您不希望在两个纹素之间的边界上采样,因为它们要么将它们与线性采样相结合,要么随意选择 中的一个或者另一个,取决于浮点计算的方式。

话虽如此,您可能会认为您不希望在(0,0),(1,1)和其他角落处拥有您的texcoords,因为它们位于texel边界上。然而,需要注意的一点是,opengl会在片段的中心对纹理进行采样。

对于一个超级简单的例子,考虑一个2乘2像素的监视器,具有2 x 2像素纹理。

如果从(0,0)到(2,2)绘制四边形,则将覆盖4个像素。如果您对此四边形进行纹理贴图,则需要从纹理中获取4个样本。

如果您的纹理坐标从0变为1,那么opengl将对此进行插值并从每个像素的中心进行采样,左下方的texcoord从左下角的左下角开始。这将最终产生(0.25,0.25),(0.75,0.75),(0.25,0.75)和(0.75,0.25)的texcoord对。这样就可以将样本放在每个纹素的中间,这就是你想要的。

如果您将texcoords偏移半个像素,就像在红色示例中那样,那么它将不正确地插入,并且您最终将纹理从纹素的中心取样。

很长一段时间,您需要确保像素与您的纹素正确对齐(不要在非整数像素位置绘制精灵),并且不要以任意数量缩放精灵。

如果蓝色方块给你不好的结果,你能给出一个示例图像,或描述你如何绘制它吗?

图片说1000字:

img