Sign in to follow this  

GL_NEAREST seams

This topic is 4741 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Ok, I am creating a 2D tile map based game. I have a single texture loaded with all my tiles. I use GL_QUADS. Position texture coords for the correct tile. use glVertex2d for the screen coords. GL_LINEAR causes a problem: neighbouring tiles get factored into each other - effectively the tile map gets seams around the tiles. I thought GL_NEAREST would work perfectly. But - to my surprise this also creates seems. The behaviour is strange - I use glOrtho to scroll the tile map - when at 0,0 it looks nice - but seams appear and dissapear as it scrolls. Anyone understand why this is occuring? And, any suggestions? Thanks, Ruben

Share this post


Link to post
Share on other sites
Try GL_CLAMP or GL_CLAMP_TO_EDGE (latter is more likely to work). The problem has to do with both Nearest and Linear occasionally choosing the pixel from the other side of the texture map to sample from (sampling wraps around textures). Clamping will prevent that.

Share this post


Link to post
Share on other sites
No it won't, because he has many tiles in one texture. Just keep your map at integer coordinates, and if you have your viewport set up right then it will always sample from texel centers and these problems will go away.

Share this post


Link to post
Share on other sites
No I'm not using the wrong texture coordinates. That's the whole point of this thread. I don't know why this problem is happening.

I'll try experimenting with keeping the map fixed at integer coordinates and this might fix it... Otherwise I may have to split the tiles into seperate textures which seems terribly unnecessary and will be slower.

Share this post


Link to post
Share on other sites
Here is an excerpt from "The Red Book" Ch. 9 I had a look at:

"If you choose GL_NEAREST, the texel with coordinates nearest the center of the pixel is used for both magnification and minification. This can result in aliasing artifacts (sometimes severe)."

I'm not sure if these "aliasing artifacts" are the problem I'm having? I'm still quite sure why my problem is occuring though...

Here is the relevant snippet of code...


...

glBindTexture(GL_TEXTURE_2D, tex_id);

glBegin(GL_QUADS);
for (map_y = start_tile_y; map_y < end_tile_y; map_y++)
{
loc_y = map_y*tileHeight + bounds.bottom;

for (map_x = start_tile_x; map_x < end_tile_x; map_x++)
{
loc_x = map_x*tileWidth + bounds.left;

if(map_y >= 0 && map_y < mapHeight && map_x >= 0 && map_x < mapWidth)
tile = map[map_y*mapWidth + map_x];
else
tile = -1;

if (tile >= 0)
drawTile(loc_x, loc_y, tile);
}
}
glEnd();
}

//
// drawTile - Draws a single tile at a given location
//
void ScTilemap::drawTile(ScFloat x, ScFloat y, int tile)
{
static ScFloat tx1;
static ScFloat ty1;
static ScFloat tx2;
static ScFloat ty2;
static ScFloat x1;
static ScFloat y1;
static ScFloat x2;
static ScFloat y2;

tx1 = (tile % paletteWidth) * invPaletteWidth;
ty1 = (tile / paletteWidth) * invPaletteHeight;
tx2 = tx1 + (tileWidth * invTextureWidth);
ty2 = ty1 + (tileHeight * invTextureHeight);
x1 = x;
y1 = y;
x2 = x + tileWidth;
y2 = y + tileHeight;

glTexCoord2d(tx1, ty1); glVertex2d(x1, y1);
glTexCoord2d(tx2, ty1); glVertex2d(x2, y1);
glTexCoord2d(tx2, ty2); glVertex2d(x2, y2);
glTexCoord2d(tx1, ty2); glVertex2d(x1, y2);
}




Thanks,

Ruben

[Edited by - rzilibowitz on December 16, 2004 2:58:30 AM]

Share this post


Link to post
Share on other sites
no thats something else (u see it when u zoom in out of an image) its the reason for mipmapping,
try converting everything to floats
eg tile % paletteWidth now these to numbers are integers so cast the result to a float perhaps

Share this post


Link to post
Share on other sites
Well, I have made a big improvement by using glVertex2i instead of glVertex2d for drawing my tiles (see code snippet in above post). But it is still far from perfect. The seams have mostly dissapeared, although now the screen flickers (mainly top to bottom - in the order I draw my tiles) whilst scrolling. When not moving the picture looks pretty much perfect.

But, if I zoom in or out, faint seams start occuring again.

Sigh.

(edit)

As a additional point: if I use a 1 pixel border around each tile and use GL_LINEAR the problems pretty much go away. But the tradeoff is I lose 1 pixel around all my tiles. There is some screen flicker here too - why is this? But it is hardly noticeable as compared with GL_NEAREST.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
The flickering is actually a different issue -- you've got a single-buffered GL context, so GL is drawing directly to the screen. The reason you see it more with GL_LINEAR because it's slower to render. To fix this, you need to request a double-buffered context from whatever you're using (GLX, SDL, Win32, etc.). It's easy to fix; you just add the right flag in the right place.

Share this post


Link to post
Share on other sites
believe it or not, I am using double buffering. I think... I am fairly sure it is double buffered since I am making a call to SDL_GL_SwapBuffers after every draw.

Actually I said the problem was LESS with GL_LINEAR not worse. I know what you were saying about the double buffering but I actually think it is because of my original problem that the OpenGL texture coordinates are either innacurate or I'm am using them wrongly.

If anyone is interested I could even post a screenshot to show what is happening...

My problem can be summarised like this:

If I have a 256 by 256 texture. And I'm using GL_NEAREST. And I do the following for given doubles x and y:

glTexCoord2d(0, 0); glVertex2d(x, y);
glTexCoord2d(0, 0.0625); glVertex2d(x, y+16);
glTexCoord2d(0.0625, 0.0625); glVertex2d(x + 16, y + 16);
glTexCoord2d(0.0625, 0); glVertex2d(x + 16, y);

I should get ONLY the texels in the upper 16 by 16 block of my texture drawn to the screen. Am I correct in this assumption?

Because OpenGL is not doing this. Instead I am getting neighbouring texels in there - ie texels in columns 17 of my texture.

Hope that wasn't too terse, and made my point clearer.

Share this post


Link to post
Share on other sites
>>elieve it or not, I am using double buffering. I think... I am fairly sure it is double buffered since I am making a call to SDL_GL_SwapBuffers after every draw.<<

not necessary u specify doublebuffering when u create the window (+ even then u mightnt get it, u have to query it)
0..15 / 256 = 1/16 right
so try 15.0/255.0. if not check the spec theres also a pdf on nvidia site IIRC that explains filtering

Share this post


Link to post
Share on other sites
No, don't think that sounds right. You should be dividing by 256. Texel 0 is at 0/256. And texel 256 is at 255/256. That would be the upper left corner of the texels. So a span of 1 texel is [0..1/256] and a span of 16 would be [0..16/256].

Share this post


Link to post
Share on other sites
Probably float rounding errors since you're accessing the very edges of the texels. Try adjusting your texcoords to:
glTexCoord2d(0.001, 0.001);           glVertex2d(x, y);
glTexCoord2d(0.001, 0.0624); glVertex2d(x, y+16);
glTexCoord2d(0.0624, 0.0624); glVertex2d(x + 16, y + 16);
glTexCoord2d(0.0624, 0.001); glVertex2d(x + 16, y);

and see if it makes any difference.

Enigma

Share this post


Link to post
Share on other sites
Yeah, thats not a bad idea. I already tried that too, but a similar problem kept occuring. It is as though: when glOrtho is set at a particular position, the tiles get their textures shifted by 1 texel. Wierd. I have decided I need to put up a couple of screenshots to make it clear...

http://users.bigpond.net.au/rz/right.tiff
http://users.bigpond.net.au/rz/left.tiff

Sorry, they are tiffs, I know, but I think most people can view tiffs in their browsers. The two pictures are scrolled to *almost* the same position. right.tiff is a tiny minute bit to the right of left.tiff. And notice what happens!

nb: if people want I can convert them to jpegs but for some reason the tiffs are really well compressed...

Share this post


Link to post
Share on other sites
well, I have solved the problem. Hooray. It turns out that there were two problems I was having...

1) I used integer coordinates for glOrtho (I think someone might have suggested this above)
2) (1) solved half the problem, but I had terrible flicker. Turns out this was not caused by single buffering or anything - it seems to be something to do with an lcd display. On my iMac with a CRT display it looks perfect now.

I still don't know why it would dlicker like that on an lcd, but at least I know the problem isn't actually in my code...

Share this post


Link to post
Share on other sites

This topic is 4741 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this