我正在尝试从纹理图集中绘制一个由较小图块组成的基本2d地面网格(请注意1像素透明边框):
我使用以下代码将图块渲染为纹理四边形:
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, m_texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(2, GL_SHORT, 0, &m_coords[0]);
glTexCoordPointer(2, GL_FLOAT, 0, &m_uvs[0]);
glDrawArrays(GL_TRIANGLES, 0, m_coords.size() / 2);
glBindTexture(GL_TEXTURE_2D, 0);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
这些位置显然是整数坐标。拐角的UV坐标计算如下:
u0 = float(x) / float(texWidth);
v0 = float(y) / float(texHeight);
u1 = float(x+w) / float(texWidth);
v1 = float(y+h) / float(texHeight);
其中w和h是没有填充的图块的大小。
当模型视图变换捕捉到整数位置(右)时看起来很棒,但是当它开始移动时,我会在图块之间得到黑色东西(左):
根据我的理解,我应该使用半纹素偏移UV坐标以使其工作,但是如果我将UV计算更改为:
u0 = float(x+0.5f) / float(texWidth);
v0 = float(y+0.5f) / float(texHeight);
u1 = float(x+w-0.5f) / float(texWidth);
v1 = float(y+h-0.5f) / float(texHeight);
它仍然不起作用。这是正确的方法吗?我需要混合才能使用吗?如果我偏移了瓷砖以确保它们被捕捉到像素网格它可以工作,但这会使它在移动缓慢时快速捕捉。人们通常如何解决这个问题?
修改
我应该说它是在iphone上。
答案 0 :(得分:5)
您的边框不应该是透明的,而是每个子纹理相对侧的像素。例如,每个子纹理右侧的边框应该是最左边的像素行的副本,即它将环绕到的像素。
这就是你如何在边框上“欺骗”纹理采样器的包装。
答案 1 :(得分:2)
我的纹理图集有类似的问题。我通过将图像嵌入1.0 / TEXTURE_ATLAS_PIXELS_PER_SIDE * 1 / 128.0来修复它。您需要通过实验找出128号码。对我来说,好处是没有人会发现缺少第128个像素。我对发送到图形卡而不是着色器的纹理坐标进行了此修改。我没有像你一样尝试使用着色器中的纹素。我已经阅读了有关如何处理纹理渗色的不同信息,但对于纹理图集来说,这对我来说是最简单的解决方案。为我的纹理添加边框紧密包装并遵循两个规则的强大功能会让我有很多空白。
这对我在iPhone上有用。
答案 2 :(得分:0)
您可以随时将GL_TEXTURE_MIN/MAG_FILTER
切换为GL_NEAREST
:)
答案 3 :(得分:0)
尝试将GL_NEAREST用于GL_TEXURE_MIN / MAX_FILTER,并在绘制前翻译0.375f:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.375f, 0.375f, 0.0f);
答案 4 :(得分:-2)
我有同样的问题。我用它修好了。
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);