OpenGL 2D渲染中的奇怪边缘

3

正如箭头所指出的那样,我的纹理旁边有一些奇怪的边缘。

这是我的OpenGL设置:

glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, WINDOW_WIDTH, 0, WINDOW_HEIGHT, 1, -1);
glMatrixMode(GL_MODELVIEW);

以下是我的渲染代码:

glPushMatrix();
    Color.white.bind();

    texture.bind();


    glTranslatef(position.x+size.width/2, position.y+size.height/2, 0f);
    glRotatef(rotation, 0f, 0f, 1f);
    glTranslatef(-size.width/2, -size.height/2, 0f);

    glBegin(GL_QUADS);
        glTexCoord2f(0, 1);
        glVertex2f(0, 0);

        glTexCoord2f(1, 1);
        glVertex2f(size.width-1, 0);

        glTexCoord2f(1, 0);
        glVertex2f(size.width-1, size.height-1);

        glTexCoord2f(0, 0);
        glVertex2f(0, size.height-1);
    glEnd();

glPopMatrix();

我看到OpenGL默认的模式是在物体比纹理大时重复纹理,但在我的情况下并不是这样。
编辑:
加载纹理的代码(我使用一个库来处理它(slick-util)):
texture = TextureLoader.getTexture(textureLocation.substring(0, textureLocation.lastIndexOf('.')), ResourceLoader.getResourceAsStream(textureLocation));

我需要在OpenGL设置完成后立即添加纹理参数,这样做正确吗?
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, WINDOW_WIDTH, 0, WINDOW_HEIGHT, 1, -1);
glMatrixMode(GL_MODELVIEW);

GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);

仍然存在舍入误差可能使文本坐标超出纹理范围,需要使用clamp。 - ratchet freak
@ratchetfreak 你能详细说明或发布一个答案吗? - Anubian Noob
你是指像这样吗?glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP); 我试过了,但它也不起作用。 - user1734282
1
“GL_CLAMP” 是错误的,加上线性插值后,当需要获取4个最近的纹理像素进行过滤时,如果没有边界纹理,它会绕到图像的另一侧。 “GL_CLAMP_TO_EDGE” 是你想要的,事实上,“GL_CLAMP” 和边界纹理在现代GL中甚至不存在。 - Andon M. Coleman
请在您加载纹理的代码处发布代码,即在glTexParameteri和所有相关内容的位置。 - Ryxuma
显示剩余2条评论
3个回答

2

我猜测你正在使用地图集(或精灵表)并且你的角色被其他精灵包围,导致出现这些边缘。为了防止这种情况发生,你应该在UV坐标中添加一个微小的偏移量。通常,四分之一像素就足以解决所有问题。这样做时,你应该知道必须考虑纹理的总宽度和高度,因为UV值处于(0,1)范围内。所以,在精灵内部将所有的UV坐标都按此偏移量进行偏移:

x-offset = 1.0 / (textureWidth * 4.0);
y-offset = 1.0 / (textureHeight * 4.0);

将纹理图集的填充增加1像素会更好。 - Kromster
@KromStern:看边缘在哪里,他用近30像素进行了填充。 - Martijn Courteaux
填充应该在UV坐标之外进行,而不是在内部。如果您有32x32的精灵,填充了30像素,但样本UV为92x92像素...那么,如果这些未填充,则会有相邻的精灵,这可能是那种情况。 - Kromster
@KromStern:确实是这样。他似乎经常填充它们,但通过使UV接触相邻的精灵,破坏了填充的想法。 - Martijn Courteaux

1
回答Martijin上面的通知:这实际上不是地图集纹理,只需要检查glTexCoord2f即可,它显示完整的纹理被用作四边形。
另外没有关于纹理类型的信息。它可能是带有一些伪影的jpg格式,混合或着色器可能会跳过一些纹理值,留下伪影。
如果是这样,请尝试使用带有alpha通道的tga或png格式。
拉伸也可能导致伪影。您的glViewport是否与glOrtho具有相同的大小?

-1

你在什么时候设置纹理参数?不知道是否有帮助,但我倾向于使用以下代码(这是 C 语言,但是转换到 Java 应该很简单)。

glGenTextures(2, node->textures);
GRL2_BindTexture(GL_TEXTURE1, GL_TEXTURE_2D, node->textures[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, 
                GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
             128, 128, 0, GL_RGB,
             GL_UNSIGNED_BYTE, (GLvoid*) node->colorMap);

简而言之,在创建和绑定纹理之后,但在上传之前,我设置了纹理参数。不知道这是否有帮助,但任何事情都有可能。
另一件要检查的事情是您的纹理大小。它是否是2的幂?有些图形卡对此非常严格。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接