精灵表纹理拾取相邻纹理的边缘


10

我有一个自定义的精灵例程(openGL 2.0),该例程使用一个简单的精灵表(我的纹理彼此水平排列)。

因此,例如,这是一个带有2个简单纹理的测试精灵表:

在此处输入图片说明

现在,我在创建openGL Sprite对象时要做的就是在其图集中指定帧的总数,并且在绘制时指定要绘制的帧。

然后计算出从何处获取纹理的方式:

将所需的帧数除以总帧数(以获得左坐标)

然后将1除以总帧数,然后将结果加到上面计算出的左手坐标上。

这似乎确实有效,但有时会遇到问题。比如说,我想在下面画X,我得到...........

在此处输入图片说明

我听说过在每个纹理之间放置1 px的“填充”,但是有人可以确切解释它是如何工作的吗?我的意思是,如果这样做,它肯定会取消获得纹理的计算。

如果我简单地在所拾取的纹理中包括填充(因此使用空白边框绘制精灵),那么这肯定会导致碰撞检测问题吗?(即,当透明零件发生碰撞时,使用边界框时,精灵可能会发生碰撞)。

如果有人可以解释,将不胜感激。


您正在使用GL_NEAREST还是GL_LINEAR用于渲染纹理?
MichaelHouse

我正在使用GL_Linear @ Byte56
BungleBonce

Answers:


15

使用纹理地图集和相邻纹理像素泄漏的问题与线性纹理过滤的工作方式有关。

对于纹理中未在纹理像素中心进行精确采样的任何点,线性采样将对4个相邻纹理像素进行采样,并在您要求的位置计算值作为所有4个像素的加权平均值(基于与采样点的距离)样品。

这是一个很好的可视化问题:

  

由于不能GL_CLAMP_TO_EDGE在纹理图集中使用类似的东西,因此需要在每个纹理的边缘周围创建边框纹理。这些边界纹素将防止来自图集中完全不同纹理的相邻样本通过上述加权插值来更改图像。

请注意,使用各向异性过滤时,可能需要增加边框的宽度。这是因为各向异性过滤将以极端角度增加样本邻域的大小。


为了说明通过在每个纹理的边缘周围使用边框来表示我的意思,请考虑OpenGL中可用的各种环绕模式。要特别注意CLAMP TO EDGE

  http://lucera-project.com/blog/wp-content/uploads/2010/06/wrap.png

尽管有一个名为“钳到边界”的模式,但实际上这并不是我们感兴趣的模式。该模式使您可以定义一种单色,以用作超出规范化[0.0]范围之外的任何纹理坐标的纹理边界-1.0]范围。

我们想要的是复制的行为CLAMP_TO_EDGE,其中,(子)纹理的适当范围之外的任何纹理坐标都将沿其超出范围的方向接收最后一个texel中心的值。因为您几乎可以完全控制在Atlas系统中,纹理坐标只能在纹理过滤的加权平均步骤中(有效)纹理坐标引用纹理之外的位置。

GL_LINEAR如上图所示,我们知道将对4个最近的邻居进行采样,因此我们只需要一个1-texel边框。如果使用各向异性过滤,则可能需要更宽的纹理像素边界,因为在某些条件下,它会增加样本邻域的大小。

这是一个纹理示例,可以更清楚地说明边框,但出于您的目的,您可以使边框宽1像素或2像素。

  

(注意:我指的边框不是图像所有四个边缘周围的黑色,而是棋盘格图案停止规则重复出现的区域)

如果您想知道,这就是为什么我不断提出各向异性过滤的原因。它会根据角度改变样品邻域的形状,并可能导致使用4个以上的纹理像素进行过滤:

  http://www.arcsynthesis.org/gltut/Texturing/ParallelogramDiag.svg

使用的各向异性程度越大,处理包含4个以上纹理像素的样本邻域的可能性就越大。2纹素边框对于大多数各向异性过滤情况应该足够了。


最后但并非最不重要的是,这是如何构建打包的纹理图集,该纹理图集将GL_CLAMP_TO_EDGE在存在GL_LINEAR纹理滤镜的情况下复制行为:

在黑色坐标中从X和Y减去1,我没有证明过要在发布前阅读图像。   

由于边界存储,在此图集中存储4 256x256纹理需要一个尺寸为516x516的纹理。根据在图集创建过程中如何以纹素数据填充边框,边框会采用颜色编码:

  • 红色=在下方直接替换为texel
  • 黄色=在上方直接替换为texel
  • 绿色=在左侧直接替换为texel
  • 蓝色=直接在右侧替换为texel

有效地在此压缩示例中,图集中的每个纹理都使用图集的258x258区域,但是您将生成映射到可见256x256区域的纹理坐标。仅在图集中纹理的边缘进行纹理过滤时,才使用边界纹理元素,并且它们的设计方式模仿GL_CLAMP_TO_EDGE行为。

如果您想知道,可以使用类似的方法来实现其他类型的环绕模式- GL_REPEAT可以通过交换纹理图集中的左/右和上/下边界纹理来实现,并且可以在模型中使用一些巧妙的纹理坐标数学来实现着色器。这有点复杂,所以暂时不用担心。由于您只处理精灵表,因此请限制为GL_CLAMP_TO_EDGE:)


感谢@AndonMColeman,您是否可以在图表中显示边框,因为我仍然不确定我是否理解它的工作原理-再次表示将纹理应用于我的对象时它将包括边框吗?我希望实际的纹理恰好到达我四边形的边缘-抱歉,如果我不能正确理解这一点-希望了解更多详细信息-谢谢
BungleBonce

@ user22241当然,此边框的工作方式是通过在纹理边缘复制纹理像素。
安东·科尔曼

@ user22241:否,在正常情况下该边框不可见。您将打包的纹理视为具有相同的尺寸以进行纹理坐标计算,只需对它们应用偏移量即可跳过边界。边框的全部目的是防止线性纹理采样超出和采样属于精灵表中单独图像的纹理像素。如果您使用最近的邻居采样,则没有必要,但是您会得到讨厌的别名精灵。
Andon M. Coleman

非常详细的答案-谢谢!如果可以的话,这只是最后一件事。如何计算添加到纹理坐标的“偏移”?我说对了,就是1 / widthOfTexture吗?
BungleBonce 2013年

@ user22241:是的,纹理图像的开始在X方向为+ 1 / widthOfTexture,在Y方向为+ 1 / heightOfTexture。您将在所有纹理周围都有一个边界。到您要计算第三个水平纹理的纹理坐标时,该纹理的打包位置实际上是+5像素(第一个纹理的边界为+2像素,第二个纹理的边界为+2,开始为+1以及其他2个纹理的宽度)。仅仅编写它似乎很复杂。如果需要,我可以为您绘制图表:)
Andon M. Coleman 2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.