PDA

View Full Version : 2D texture problem - lines between textures?



chinchi11a
06-15-2009, 06:49 PM
Hello there.
I'm having a problem: mysterious abnormalities appear along the edges of where two of my tile graphics meet (the edges of the colored portions of two neighboring tiles). To give you an idea of what I mean, here first is my tile.

http://img517.imageshack.us/img517/3279/tileart.png
I've colored the transparent background black for visual purposes. Also, the tile isn't at the exact position it would be in the 64x64 texture within my engine, but close so you get the idea. (middle, bottom - the bottom side of an isometric cube)

Now here's what I get when I try to tile them (the problem)

http://img517.imageshack.us/img517/8601/tilesexample.png
Just a snippet of a larger screen (640 x 480) from the game. The tile image should tile perfectly using the coordinates that I give it in-game. Each tile is placed 30 left/right of tiles next to it, and 15 above / below tiles above or below it. What this means is: 1. there is no horizontal overlap, 2. the tile below is fitted exactly in-between the two above it and overlaps them by one pixel vertically (forming an overlap line that is two-across, one-down style.
Anyways, sorry for that lengthy description but I want to provide the information in case anyone would like it.

So as you can see, there are darkened pixels along lines of adjacent tiles.

What I don't know is whether this is caused by some kind of non-pixel-perfect problem with my OpenGL view, texture options, positioning, etc...
or with some kind of texture overlay problem... like multiplying instead of replacing or something to that effect.

To provide you with some information (this is the stuff that kind of boggles my mind when I try to think about it too much...) here is my OpenGL setup code.



glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glViewport(0, 0, 640, 480);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();

glOrtho(1000.0f, 1640, 1480, 1000.0f, -1.0f, 1.0f);

glMatrixMode(GL_MODELVIEW); // I officially don't even know what's going on here... annyways.
glLoadIdentity();

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_TEXTURE2D)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

and here is the function that draws textures, including the tiles...


void VideoManager::DrawGraph(float PX, float PY, Graphicality* Graph)
{
// PX & PY are offsets based on the camera's position
float X = Graph->X; // coords of the object to be drawn
float Y = Graph->Y;
int Width = Graph->Width; // 64 ("width" of texture)
int Height = Graph->Height; // 0 (represents height in iso-land)
int Depth = Graph->Depth; // 64 ("height" of texture)
Graph->CurrentTex->Bind();
glColor4f(1.0,1.0,1.0,1.0);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(X-Width/2+PX, Y+Depth/4+PY, 1.0f); // Bottom left
glTexCoord2f(1.0f, 0.0f); glVertex3f(X+Width/2+PX, Y+Depth/4+PY, 1.0f); // Bottom Right
glTexCoord2f(1.0f, 1.0f); glVertex3f(X+Width/2+PX, Y-3*Depth/4+PY, 1.0f); // Top Right
glTexCoord2f(0.0f, 1.0f); glVertex3f(X-Width/2+PX, y-3*Depth/4+PY, 1.0f); // Top Left
glEnd();
}


Just to note, I have tried casting various floats to ints (like all of them..) and I have also made sure via debugging that the coordinates of the tiles (X and Y in the draw function) are what they should be, as described up above.

Anyways forgive my retyping so much code.. I don't want to simplify too much since I'm not sure where the problem is.

So if anyone has any idea what I'm doing wrong (or any pointers for anything else you see that I should work on) then please post :D

matchStickMan
06-15-2009, 11:15 PM
Add these two lines just after your "glEnable(GL_TEXTURE2D)" and you'll be fine. :)

glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );

matchStickMan
06-15-2009, 11:24 PM
My reference:

http://www.talisman.org/opengl-1.1/Reference/glTexParameter.html

Some excerpts:

GL_TEXTURE_WRAP_S
Sets the wrap parameter for texture coordinate s to GL_CLAMP, GL_REPEAT, GL_CLAMP_TO_BORDER_EXT, or GL_CLAMP_TO_EDGE_EXT.

GL_CLAMP causes s coordinates to be clamped to the range [0, 1] and is useful for preventing wrapping artifacts when mapping a single image onto an object.

GL_REPEAT causes the integer part of the s coordinate to be ignored; the GL uses only the fractional part, thereby creating a repeating pattern.

GL_CLAMP_TO_BORDER_EXT causes s coordinates to be clamped to a range 1/2 texel outside [0, 1]; this prevents the "half border, half edge" color artifact.

GL_CLAMP_TO_EDGE_EXT causes s coordinates to be clamped to a range 1/2 texel inside [0, 1]; this prevents any border colors from showing up in the image. Border texture elements are accessed only if wrapping is set to GL_CLAMP or GL_CLAMP_TO_BORDER_EXT.

Initially, GL_TEXTURE_WRAP_S is set to GL_REPEAT.




GL_TEXTURE_WRAP_T
Sets the wrap parameter for texture coordinate t to GL_CLAMP, GL_REPEAT, GL_CLAMP_TO_BORDER_EXT, or GL_CLAMP_TO_EDGE_EXT.

See the discussion under GL_TEXTURE_WRAP_S.

Initially, GL_TEXTURE_WRAP_T is set to GL_REPEAT.

remdul
06-16-2009, 07:44 AM
matchStickMan, I don't see how texture wrapping has anything to do with this problem, as the edges run diagonally. The poster is just rendering 2d sprites, not a 3d textured quad.

Because you are alpha-blending, overlapping edges will not add up to 100% opacity. Technically, it should if you get 1:1 texel vs pixel rasterization, but this is not always possible to achieve in reality, due to driver optimizations, floating point in-accuracy etc.
You should first try to render a single tile, take a screenshot and see it if matches up in PhotoShop or such, to make sure your texture coordinates and vertex positions are correct. You'll want this to be accurate down to a single pixel!

1) If that doesn't help, try this for texture filtering:

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

This will disable bi-linear filtering on the textures.

2) If you want to keep soft texture filtering, the alternative is to 'flood fill' the pixels in the tiles 'outward', so the black pixels (where the tile is transparant) will take the color of the nearest visible pixel.

I would suggest the 2nd method, as this is more robust as it will look correct with varying driver optimizations/setting (things like FSAA, anisotropic filtering) which may override texture filtering, display resolution etc.

Xmas
06-16-2009, 09:06 AM
2) If you want to keep soft texture filtering, the alternative is to 'flood fill' the pixels in the tiles 'outward', so the black pixels (where the tile is transparant) will take the color of the nearest visible pixel.
It's better to keep the transparent pixels black and simply change the blend factors to (GL_ONE, GL_ONE_MINUS_SRC_ALPHA). This corresponds to premultiplied alpha pixel data.

chinchi11a
06-16-2009, 05:32 PM
Hey guys! Thanks a bunch.

matchStick, I tried yours out first, it didn't fix this problem but I had been reading about those options and your explanation was way more helpful than what I had read :]

remdul, I changed it to GL_NEAREST and it ended up working :D So happy.
I'm going to try your suggestion out this evening, Xmas, because I would like to keep the bi-linear filtering (if I'm understanding that correctly).

matchStickMan
06-16-2009, 08:45 PM
I thought it was an edge blending issue. Anyways I'm glad your problem is fixed. :)