🔒 Locked
GL_NEAREST seams
Advertisement
Original Post
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
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.
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.
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...
Thanks,
Ruben
[Edited by - rzilibowitz on December 16, 2004 2:58:30 AM]
"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]
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.
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.
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:
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.
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.
>>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
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
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].
Probably float rounding errors since you're accessing the very edges of the texels. Try adjusting your texcoords to:
and see if it makes any difference.
Enigma
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
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...
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...
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...
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...
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement