12

假设我们有一个纹理(在本例中为 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;

虽然当第一次实现这个方法时,ca。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 推出前后,我开始觉得我的精灵看起来不太好。经过一些测试,我切换回“蓝色”方法(第二张图片),现在它们看起来不错,但并非总是如此

我是疯了,还是与 GL ES 纹理映射相关的 iOS 5 发生了一些变化?也许我做错了什么?(例如,顶点位置坐标略微偏离?错误的纹理设置参数?)但是我的代码库没有改变,所以也许我从一开始就做错了什么......?

我的意思是,至少在我的代码中,感觉好像“红色”方法过去是正确的,但现在“蓝色”方法给出了更好的结果。

现在,我的游戏看起来不错,但我觉得我迟早必须修复一些错误的东西......

有什么想法/经验/意见吗?

附录

为了渲染上面的精灵,我会在正交投影中绘制一个 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:00) http://www.mindcontrol.org/~hplus/graphics/opengl-pixel-perfect.html

4

1 回答 1

10

这张图片的内容比肉眼看到的要多一些,纹理坐标并不是纹理被采样的唯一因素。在你的情况下,我相信蓝色可能是你想要的。

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

话虽如此,您可能会认为您不想让您的纹理坐标位于 (0,0)、(1,1) 和其他角,因为它们位于纹理边界上。然而需要注意的重要一点是,opengl 在片段中心对纹理进行采样。

举一个超级简单的例子,考虑一个 2 x 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 对。这将样本放在每个纹素的中间,这就是你想要的。

如果您像红色示例中那样将纹理坐标偏移半个像素,那么它将错误地插值,并且您最终会从纹理像素的中心对纹理进行采样。

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

如果蓝色方块给你的结果不好,你能举个例子,或者描述一下你是怎么画的吗?

图片说1000字:

图像

于 2012-07-12T18:14:44.383 回答