Original Post
🔒 Locked
Tiling and seams
Advertisement
Nothing is wrong! It's the way OpenGL treats textures. When mapping texels to pixels is not 1-to-1, OpenGL blends adjacent texels. It is known as filtering. You probably know about GL_TEXTURE_MIN_FILTER and GL_TEXTURE_MAX_FILTER parameters of the function glTextureParameteri(). (If you don't take a look at pg. 411 of the OpenGL Programming Guide 6th Ed.)
When OpenGL tries to blend texels at the edge of the texture, obviously it has a problem, because there is nothing after the border to blend with. There are two ways to avoid such unpleasant artifacts:
1. to set texture-coordinate wrapping mode to GL_CLAMP_TO_EDGE (for both S and T texture coordinates), or
2. to create a border (1 pixel width), but then set 6th parameter of the function glTexlmage2D().
When OpenGL tries to blend texels at the edge of the texture, obviously it has a problem, because there is nothing after the border to blend with. There are two ways to avoid such unpleasant artifacts:
1. to set texture-coordinate wrapping mode to GL_CLAMP_TO_EDGE (for both S and T texture coordinates), or
2. to create a border (1 pixel width), but then set 6th parameter of the function glTexlmage2D().
Alright well I want to try using gl_clamp_to_edge but I think my opengl version is out of date since I am getting an undefined error.
I tried going to opengl.org but that website confused me on how to go about of updating.
Can you link me to how to update my header files?
I tried going to opengl.org but that website confused me on how to go about of updating.
Can you link me to how to update my header files?
Hm, obviously you are new to OpenGL. You don't have to download some SDK in order to use new functionality. As soon as you install new drivers you can access new functionality. But it cannot be access on "the standard way". To skip further explanation, I suggest you to read pages:
http://www.opengl.org/documentation/extensions/
and
http://www.opengl.org/resources/faq/technical/extensions.htm
After that you should download .h files from
http://www.opengl.org/registry/
and start coding. This is the hardest way! :o)
The second solution is to use some of libraries that replace all previous stuff. I suggest OpenGL Extension Wrangler Library which can be downloaded (and learned about) from
http://glew.sourceforge.net/
But I think it is even simpler for you to make textures wider than the portion that should be rendered (by coping one raw/column from adjacent textures) and use border.
http://www.opengl.org/documentation/extensions/
and
http://www.opengl.org/resources/faq/technical/extensions.htm
After that you should download .h files from
http://www.opengl.org/registry/
and start coding. This is the hardest way! :o)
The second solution is to use some of libraries that replace all previous stuff. I suggest OpenGL Extension Wrangler Library which can be downloaded (and learned about) from
http://glew.sourceforge.net/
But I think it is even simpler for you to make textures wider than the portion that should be rendered (by coping one raw/column from adjacent textures) and use border.
I assume you use a texture atlas where you read the tiles from (at least otherwise I could not explain why you have colored seams between the black tiles).
Thus I will base the following comment on that.
You can have pixel exact texture reads when using GL_NEAREST for GL_TEXTURE_MIN/MAG_FILTER.
However, the texture then looks blocky if magnified.
Like Aks9 said, OpenGL generally uses bilinear filtering for magnification, i.e. it averages the colors of the 4 texels around a location. To avoid the seams you should use the second method (since the first won't work for atlases). Additionally you should fill the border with opposite side values (unless you want hard edges between your tiles).
What I mean is, you fill the left border around the tile with the colors from the right border of the tile.
To make it clearer:
Asume the following tile setup:
rrgg
rrgg
rrgg
rrgg
Now add a border to the left:
g rrgg
g rrgg
g rrgg
g rrgg
You see that I added a green (g) border to the left of the tile, even if the leftmost pixels are red (r).
Why?
If you used a texture per tile, OpenGL would repeat the tiles like this:
rrgg rrgg
rrgg rrgg
rrgg rrgg
rrgg rrgg
Thus a the border between the two the colors would be blended between green and red. With the "mirrored" border you can replicate the same behavior for tiles in texture atlases.
Edit: As a side note, your grass texture doesn't seem to be tilable, so you might still get seams.
Thus I will base the following comment on that.
Quote:
Original post by Aks9
When OpenGL tries to blend texels at the edge of the texture, obviously it has a problem, because there is nothing after the border to blend with. There are two ways to avoid such unpleasant artifacts:
1. to set texture-coordinate wrapping mode to GL_CLAMP_TO_EDGE (for both S and T texture coordinates), or
2. to create a border (1 pixel width), but then set 6th parameter of the function glTexlmage2D().
You can have pixel exact texture reads when using GL_NEAREST for GL_TEXTURE_MIN/MAG_FILTER.
However, the texture then looks blocky if magnified.
Like Aks9 said, OpenGL generally uses bilinear filtering for magnification, i.e. it averages the colors of the 4 texels around a location. To avoid the seams you should use the second method (since the first won't work for atlases). Additionally you should fill the border with opposite side values (unless you want hard edges between your tiles).
What I mean is, you fill the left border around the tile with the colors from the right border of the tile.
To make it clearer:
Asume the following tile setup:
rrgg
rrgg
rrgg
rrgg
Now add a border to the left:
g rrgg
g rrgg
g rrgg
g rrgg
You see that I added a green (g) border to the left of the tile, even if the leftmost pixels are red (r).
Why?
If you used a texture per tile, OpenGL would repeat the tiles like this:
rrgg rrgg
rrgg rrgg
rrgg rrgg
rrgg rrgg
Thus a the border between the two the colors would be blended between green and red. With the "mirrored" border you can replicate the same behavior for tiles in texture atlases.
Edit: As a side note, your grass texture doesn't seem to be tilable, so you might still get seams.
Lord_Evil:
I am not using texture atlases right now, but I will look into that later on.
I don't want to add a border color to every texture image I want to use in the game.
Aks9:
And yes I am new, but I like to learn as I go along. My current goal is to make a working rpg town.
Anyways so let see if I understand extensions correctly. So visual c++ 2008 express edition only has opengl 1.1 standard.
Found in gl.h
but the current version is opengl 3.0.
But when I update my graphic cards drivers I should be able to use any of the extensions. Is that correct?
So clamp_to_edge was promoted to core in version 1.2. So all I need to do is update my .h files to gain access to clamp_to_edge?
I am not using texture atlases right now, but I will look into that later on.
I don't want to add a border color to every texture image I want to use in the game.
Aks9:
And yes I am new, but I like to learn as I go along. My current goal is to make a working rpg town.
Anyways so let see if I understand extensions correctly. So visual c++ 2008 express edition only has opengl 1.1 standard.
Found in gl.h
#define GL_VERSION_1_1 1but the current version is opengl 3.0.
But when I update my graphic cards drivers I should be able to use any of the extensions. Is that correct?
So clamp_to_edge was promoted to core in version 1.2. So all I need to do is update my .h files to gain access to clamp_to_edge?
Quote:Unless you have a DX10-level graphics card, and go through the hassle of setting up a 3.0 context, you will be limited to OpenGL 2.1. However, you can access further features using extensions.
Original post by Shadowwoelf
but the current version is opengl 3.0.
Quote:Yes. However, you will save yourself infinite headaches by using an extension library such as GLee, or the aforementioned GLEW.
So clamp_to_edge was promoted to core in version 1.2. So all I need to do is update my .h files to gain access to clamp_to_edge?
I tried to use glew, but the tutorial for installing and using it was to confusing.(telling me to move files that didn't exist) so I went with Glee instead.
I replaced all the gl.h,glu.h files with glee.h, and then everything compiled fine except for gluBuild2DMipmaps. After which I added glee.h, then glu.h but now its giving me an unreferenced external symbol.
So is there an alternative to glubuild2dmipmaps or did I do something wrong?
I replaced all the gl.h,glu.h files with glee.h, and then everything compiled fine except for gluBuild2DMipmaps. After which I added glee.h, then glu.h but now its giving me an unreferenced external symbol.
So is there an alternative to glubuild2dmipmaps or did I do something wrong?
Quote:gluBuild2DMipmaps() is an old (and deprecated) function, which had two main uses: resizing non-power-of-2 images, and building the mipmap chain.
Original post by Shadowwoelf
So is there an alternative to glubuild2dmipmaps or did I do something wrong?
Modern cards support non-power-of-2 texture dimensions natively, using the basic glTexImage2D function, as long as your GL_EXTENSIONS string contains the token ARB_texture_non_power_of_two - but beware that older cards (especially Intel integrated chipsets) are missing this extension.
As for building mipmaps, you should be using the GL_GENERATE_MIPMAP texture parameter - see here for an example.
Ah thanks I figured that it was deprecated, but googling got me nowhere!
Edit: From the site you gave me it says "In GL 3.0, it is recommended to forget about GL_GENERATE_MIPMAP and use glGenerateMipmap"
Edit 2:
Still am getting the same black lines even though I enabled GL_CLAMP_TO_EDGE.
Edit 4: Forgot to add that I should check what gl verison the user has, but still having lines pop up
[Edited by - Shadowwoelf on August 10, 2009 10:35:30 PM]
Edit: From the site you gave me it says "In GL 3.0, it is recommended to forget about GL_GENERATE_MIPMAP and use glGenerateMipmap"
Edit 2:
Still am getting the same black lines even though I enabled GL_CLAMP_TO_EDGE.
glGenTextures(1, &Textures); glBindTexture(GL_TEXTURE_2D, Textures); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); //The flag is set to TRUE glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ilGetInteger(IL_IMAGE_WIDTH), ilGetInteger(IL_IMAGE_HEIGHT), 0, ilGetInteger(IL_IMAGE_FORMAT), GL_UNSIGNED_BYTE, ilGetData());Edit 4: Forgot to add that I should check what gl verison the user has, but still having lines pop up
[Edited by - Shadowwoelf on August 10, 2009 10:35:30 PM]
Did you check that your textures are seamlessly tileable?
For example, you could open up your favorite drawing program (like Gimp or Photoshop) and either use a filter that moves the image and wraps around at the borders or just make a bigger version and manually place 4 tiles into it. If you do that, do you see those seams as well?
Edit: oh, and you might want to use GL_REPEAT instead of GL_CLAMP_TO_EDGE.
For example, you could open up your favorite drawing program (like Gimp or Photoshop) and either use a filter that moves the image and wraps around at the borders or just make a bigger version and manually place 4 tiles into it. If you do that, do you see those seams as well?
Edit: oh, and you might want to use GL_REPEAT instead of GL_CLAMP_TO_EDGE.
the textures are indeed seamless because I borrowed them from rpg maker (Which I plan on replacing later on). The only difference is that I made it into an rgba with a small empty box at 0,0 for tga(Bottom left). Also last week before I made major changes to my coding the seams weren't there.
Empty box coordinates. Size of sprite sheet:480x256
x,y,z
0,32,2 32,32,2
0,0,2 32,0,2
GL_repeat still has the seams in it.
Empty box coordinates. Size of sprite sheet:480x256
x,y,z
0,32,2 32,32,2
0,0,2 32,0,2
textures[id][loop][0]=((x%(int)(width/spritesize))/(width/spritesize)); textures[id][loop][1]=((y)/(height/spritesize)); textures[id][loop][2]=((x%(int)(width/spritesize))/(width/spritesize)); textures[id][loop][3]=((y+1)/(height/spritesize)); textures[id][loop][4]=((x%(int)(width/spritesize)+1)/(width/spritesize)); textures[id][loop][5]=((y+1)/(height/spritesize)); textures[id][loop][6]=((x%(int)(width/spritesize)+1)/(width/spritesize)); textures[id][loop][7]=((y)/(height/spritesize)); GL_repeat still has the seams in it.
I'm sorry, Shadowwoelf, if I have offended you. I didn't want that. There is nothing wrong if someone is new. I just supposed that you won't be angry if someone (e.g. me) gives you some basic advices.
Firstly, not 3.0, but 3.2 is current version of OpenGL, and if you have adequate hardware and drivers you only need, as you have already said, appropriate header files. For me it is the greatest benefit of using OpenGL that you don't have to wait for some SDK or something like that to start coding in the brand new API.
Secondly, don't be afraid to use OpenGL 3.x rendering context. It is not complicated at all. Look at
http://www.wikiscripts.net/#action=post&id=149
or
http://www.opengl.org/wiki/Tutorials.
I have also explained in this tutorial how to use GLEW with Visual Studio. Only 3 steps are required:
1. copy glew.h, wglew.h, glew32.lib and glew32.dll into appropriate folders, or into your project's folder
2. #include "glew.h"
#include "wglew.h"
#pragma comment(lib, "glew32.lib")
3. call glewInit()
That's all! It cannot be simpler.
Let's back to seamless textures. There is obviously transparent border (or edges) in your textures (I didn't get the stuff about empty box at (0,0).) I think that is why you still have seams although you've enabled GL_CLAMP_TO_EDGE (Although, only border can solve the problem completely. GL_CLAMP_TO_EDGE just minifies it.). To shorten the story and discard wrong guesses, try to change your texture coordinates on the quads you are rendering. Instead starting with (0,0) and ending with (1,1), try to start, for example, with (0.1, 0.1) for the lower left corner and end with (0.9, 0.9) for upper right. (Or you can calculate the texel size and shift for a texel or two, but previous example will serve the purpose to see what's happening).
Firstly, not 3.0, but 3.2 is current version of OpenGL, and if you have adequate hardware and drivers you only need, as you have already said, appropriate header files. For me it is the greatest benefit of using OpenGL that you don't have to wait for some SDK or something like that to start coding in the brand new API.
Secondly, don't be afraid to use OpenGL 3.x rendering context. It is not complicated at all. Look at
http://www.wikiscripts.net/#action=post&id=149
or
http://www.opengl.org/wiki/Tutorials.
I have also explained in this tutorial how to use GLEW with Visual Studio. Only 3 steps are required:
1. copy glew.h, wglew.h, glew32.lib and glew32.dll into appropriate folders, or into your project's folder
2. #include "glew.h"
#include "wglew.h"
#pragma comment(lib, "glew32.lib")
3. call glewInit()
That's all! It cannot be simpler.
Let's back to seamless textures. There is obviously transparent border (or edges) in your textures (I didn't get the stuff about empty box at (0,0).) I think that is why you still have seams although you've enabled GL_CLAMP_TO_EDGE (Although, only border can solve the problem completely. GL_CLAMP_TO_EDGE just minifies it.). To shorten the story and discard wrong guesses, try to change your texture coordinates on the quads you are rendering. Instead starting with (0,0) and ending with (1,1), try to start, for example, with (0.1, 0.1) for the lower left corner and end with (0.9, 0.9) for upper right. (Or you can calculate the texel size and shift for a texel or two, but previous example will serve the purpose to see what's happening).
aks9 I wasn't mad I was simply stating what my goal was, and I appreciate any advice because I understand that there is a lot more to learn(A lot more...).
Also I couldn't find the files that were supposed to be located for glew so I just ended up using glee.(Nothing in lib etc.)
Anyways I switched the place where my graphics is empty to another location. I still had the same lines, so I removed everything from a 1 pixel border around the area and the problem was fixed.
Then I turned off the top 2 layers of my program and everything was seamless as shown here.
(I moved the top empty box down in paint so thats why it might seem a bit off)

So the problem seems to just originate at my invisible box. And by invisible box I mean 1 tile that is completely transparent.
Also I couldn't find the files that were supposed to be located for glew so I just ended up using glee.(Nothing in lib etc.)
Anyways I switched the place where my graphics is empty to another location. I still had the same lines, so I removed everything from a 1 pixel border around the area and the problem was fixed.
Then I turned off the top 2 layers of my program and everything was seamless as shown here.
(I moved the top empty box down in paint so thats why it might seem a bit off)

So the problem seems to just originate at my invisible box. And by invisible box I mean 1 tile that is completely transparent.
I fixed the problem by splitting the 16x16 pixel texture into 4 8x8 sub textures. Then I simply used the top right 8x8 texture. Since the entire texture is invisible I don't have to worry about stretching the image out.
I prefer this method because now when I try to include more texture files I do not have to worry about forgetting to add a border to the image.
Later on I'll change the numbers into something that will allow me to use any texture size. e.g. 16= (y)/(height/spritesize));
So at least I learned a bit about extensions and updated my code to avoid using glutmipmaps
edit: Apparently all those calculations did was put the textures to 0. So I am assuming since that a point cannot have any textures then it is automatically transparent. I'll mess around with this more later on.
[Edited by - Shadowwoelf on August 12, 2009 3:33:57 AM]
I prefer this method because now when I try to include more texture files I do not have to worry about forgetting to add a border to the image.
if(x==0){ textures[id][loop][0]=1/60; textures[id][loop][1]=1/32; //Bottom left textures[id][loop][2]=1/60; textures[id][loop][3]=1/16; //Top Left textures[id][loop][4]=1/30; textures[id][loop][5]=1/16; //Top Right textures[id][loop][6]=1/30; textures[id][loop][7]=1/32; //Bottom Right }Later on I'll change the numbers into something that will allow me to use any texture size. e.g. 16= (y)/(height/spritesize));
So at least I learned a bit about extensions and updated my code to avoid using glutmipmaps
edit: Apparently all those calculations did was put the textures to 0. So I am assuming since that a point cannot have any textures then it is automatically transparent. I'll mess around with this more later on.
[Edited by - Shadowwoelf on August 12, 2009 3:33:57 AM]
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement
