LWJGL Forum

Programming => Lightweight Java Gaming Library => Topic started by: Bingo90 on September 02, 2013, 08:03:42

Title: LWJGL/Slick texture wrapping
Post by: Bingo90 on September 02, 2013, 08:03:42
When using the drawing code below, some pixels seem to wrap from the back to the front of a texture. I don't know how to fix this, is there a solution?    

public class MainDisplay
{
public void run() throws LWJGLException
{
Game.init();

int width = 800, height = 600;

Display.setDisplayMode(new DisplayMode(800,600));
Display.setTitle("2D Game Java Test");
    Display.create();

glEnable(GL11.GL_TEXTURE_2D);

glEnable(GL11.GL_BLEND);
glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
glViewport(0, 0, width, height);
glMatrixMode(GL11.GL_MODELVIEW);

glMatrixMode(GL11.GL_PROJECTION);
glLoadIdentity();
glOrtho(0, width, height, 0, 1, -1);
glMatrixMode(GL11.GL_MODELVIEW);

init();

long time = System.nanoTime();

while (!Display.isCloseRequested())
{

float deltaSeconds = ((float)(System.nanoTime()-time))/1000000000f;
time = System.nanoTime();
Game.update(deltaSeconds);


Game.draw();  //In there's the drawing code.
                           


try
{
Thread.sleep(1000/500);
} catch (InterruptedException e)
{
e.printStackTrace();
}

Display.update();
}

Display.destroy();
}
public void init()
{
TextureManager.loadContent();
}
}



public static void drawTexture(Texture texture, Vector2f position, Vector2f translation, Vector2f origin,Vector2f scale,float rotation, Color color, FlipState flipState)
{
texture.setTextureFilter(GL11.GL_NEAREST);


color.bind();
texture.bind();


       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);

GL11.glTranslatef((int)position.x, (int)position.y, 0);
GL11.glTranslatef(-(int)translation.x, -(int)translation.y, 0);
GL11.glRotated(rotation, 0f, 0f, 1f);

GL11.glScalef(scale.x, scale.y, 1);

GL11.glTranslatef(-(int)origin.x, -(int)origin.y, 0);


GL11.glBegin(GL11.GL_QUADS);
GL11.glTexCoord2f(0,0);
GL11.glVertex2f(0,0);
GL11.glTexCoord2f(1,0);
GL11.glVertex2f(texture.getTextureWidth(),0);
GL11.glTexCoord2f(1,1);
GL11.glVertex2f(texture.getTextureWidth(),texture.getTextureHeight());
GL11.glTexCoord2f(0,1);
GL11.glVertex2f(0,texture.getTextureHeight());

GL11.glEnd();

GL11.glLoadIdentity();
}


The wrapping mentioned above:

(http://i.imgur.com/6TQu9oQ.png)
Title: Re: LWJGL/Slick texture wrapping
Post by: Fool Running on September 04, 2013, 12:34:20
You need to specify the GL_CLAMP_TO_EDGE when you create the texture, not when you use it.
Title: Re: LWJGL/Slick texture wrapping
Post by: Bingo90 on September 04, 2013, 16:49:21
Okay I'm using this method to load a texture

public static Texture loadTexture(String fileName)
{


Texture texture = null;
try
{
InputStream stream = ClassLoader.getSystemResourceAsStream(fileName);

if(stream!=null)
{
texture = TextureLoader.getTexture("PNG",stream);
System.out.println("Texture loaded: " + fileName+" Width: "+texture.getImageWidth()+" Height: "+texture.getImageHeight());
}
else
{
System.out.println(String.format("File \"%s\" doesn't exist and wasn't loaded.",fileName));
}
}
catch (Exception e)
{
System.out.println(String.format("Error loading %s: %s",fileName,e.toString()));
}


return texture;
}
Title: Re: LWJGL/Slick texture wrapping
Post by: Fool Running on September 05, 2013, 12:37:19
I shouldn't try help people when I'm tired. You can change the texture wrapping at any time. :-[

I should have said what I was going to, originally:
I can't see the picture. Are you saying that you are seeing the texture image on the back and the front of the polygon, or that the texture is repeating itself over the polygon? Is your texture a power-of-two size (on the x and y axis)?
Title: Re: LWJGL/Slick texture wrapping
Post by: Bingo90 on September 05, 2013, 14:09:40
I don't know why the image isn't showing up on the first post :/ Well here's a link to the image showing the problem http://i.imgur.com/6TQu9oQ.png
Title: Re: LWJGL/Slick texture wrapping
Post by: Fool Running on September 05, 2013, 17:25:39
Well, nothing is jumping out at me as being wrong with your code. What happens if you use GL11.GL_CLAMP instead of GL12.GL_CLAMP_TO_EDGE?
Title: Re: LWJGL/Slick texture wrapping
Post by: Bingo90 on September 06, 2013, 13:34:32
Nothing.
Title: Re: LWJGL/Slick texture wrapping
Post by: Bingo90 on September 14, 2013, 08:59:53
Updated the code. Maybe the MainDisplay class could help. Also, I fixed the link to the image.
Title: Re: LWJGL/Slick texture wrapping
Post by: quew8 on September 14, 2013, 10:11:40
My solution to this problem is just to add a 1 pixel, 0 alpha border on the top and right edges. It's not a pretty solution but it gets the job done. If your worried about file sizes of your images you can even add it in when you load it in software.
Title: Re: LWJGL/Slick texture wrapping
Post by: Bingo90 on September 14, 2013, 10:36:29
Besides the code I've shown I've got a lot of other code and I don't want to change it because of this. Isn't there another way?
Title: Re: LWJGL/Slick texture wrapping
Post by: quew8 on September 14, 2013, 11:03:27
For the record, this effect is called texture bleeding so if you don't like my answer, search that and you'll get thousands of solutions.

Firstly, I just want to check that you aren't using mipmapping. You're are in 2D so it doesn't make any sense to, but some people do out of force of habit or just because they haven't thought it through (which is understandable). As I've said I just add a border and be done with it, but the best solution I've heard of, off the top of my head, is half pixel correction.

Normally your tex coords are actually on the border between to pixels. Imagine a 100 pixel wide (1D for simplicity) texture. You sprite starts at the 7th pixel, so your tex coord is 0.07 right? But that position is actually the start of the 7th pixel which in reality is the border between the 6th and 7th pixel. So when OpenGL wants to sample at 0.07, it blends the 6th and 7th pixels together. The solution is to set the tex coord to the centre of the 7th pixel rather than the start. So 7.5 / 100 = 0.075. So a general formula for the nth pixel in an w wide texture (still 1D) is (n + 0.5) / w, right?

But what if the end of you sprite is the 19th pixel, then (19 + 0.5) / 100 is 0.195. Except that is the centre of the 20th pixel. It should be (19 - 0.5) / 100 is 0.185. So you see the problem with this method. When you work out the tex coords (this is mainly a problem for dynamic texture atlases), you need to know where in the sprite that tex coord comes from. Not a massive problem, just watch out for it.
Title: Re: LWJGL/Slick texture wrapping
Post by: Bingo90 on September 14, 2013, 12:00:02
I tried to turn mipmapping off but it didn't work (I haven't turned it on anywhere so it seems to be off by default). But why doesn't the clamping work? Shouldn't it fix the problem?
Title: Re: LWJGL/Slick texture wrapping
Post by: quew8 on September 14, 2013, 14:05:12
All clamp does is clamp the texture coords. So if your tex coords are (0, 0), (0, 1), (1, 1), and (1, 0), then it will make absolutely no difference. And as I explained above tex coord 1 is a blend between the last texel and the first texel.

Mipmapping is only used if you have GL_MIN_FILTER or GL_MAX_FILTER set to GL_(NEAREST | LINEAR)_MIPMAP_(NEAREST | LINEAR). If you use one of those then you have to either explicitly generate mipmaps or explicitly turn on auto generated mipmaps. So from your response I'm guessing you don't use them, which for 2D is good (99% of the time).

You could set the MIN and MAG filters to GL_NEAREST which would work some of them time, but assuming it rounds up (which it probably does), this wouldn't solve this problem. You could try it but it is NOT a 100% solution. At most it is a 50% solution.
Title: Re: LWJGL/Slick texture wrapping
Post by: Bingo90 on September 14, 2013, 15:54:07
Okay I'll try that.

EDIT:

Didn't work :-\ What'd be the best way that works without texture editing? What changes should I make to the code?
Title: Re: LWJGL/Slick texture wrapping
Post by: Cornix on September 14, 2013, 16:04:11
Have you tried enabling a border for the texture with an invisible border color?
You could then use "clamp_to_border" as the horizontal wrap mode.

I personally have never used border color, but I guess this is the kind of situation it would be used for.
Title: Re: LWJGL/Slick texture wrapping
Post by: Bingo90 on September 14, 2013, 16:37:58
CLAMP_TO_BORDER didn't do anything.
Title: Re: LWJGL/Slick texture wrapping
Post by: Cornix on September 14, 2013, 17:01:14
You need to define a border color in order to make CLAMP_TO_BORDER work.
Without a border color you need to use CLAMP_TO_EDGE.
Title: Re: LWJGL/Slick texture wrapping
Post by: Bingo90 on September 15, 2013, 06:28:52
CLAMP_TO_EDGE didn't do anything like CLAMP. How do I define a border color?
Title: Re: LWJGL/Slick texture wrapping
Post by: quew8 on September 15, 2013, 10:16:32
What about my half-pixel correction? You need to change the way you assign texture coordinates to your sprite as I showed in the previous post.
Title: Re: LWJGL/Slick texture wrapping
Post by: Cornix on September 15, 2013, 11:00:06
You specify the border color like this:
GL11.glTexParameter(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_BORDER_COLOR, someFloatBuffer);
But you have to also increase the width and height of your texture by 2 (the border is 1 pixel in size).
int borderSize = 1;
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, width + 2, height + 2, borderSize, GL11.GL_RGBA, GL11.GL_FLOAT, someFloatBuffer);
Title: Re: LWJGL/Slick texture wrapping
Post by: Bingo90 on September 15, 2013, 11:28:47
I'll try the pixel correction thing. I don't use LWJGL directly to load a texture.

EDIT:

What should I change? I not sure what in my code should be 0.5 higher/lower
Title: Re: LWJGL/Slick texture wrapping
Post by: quew8 on September 16, 2013, 16:22:07
The texture coordinates of the sprite.
Title: Re: LWJGL/Slick texture wrapping
Post by: Bingo90 on September 17, 2013, 12:49:32
OK I'll try that

Edit:

I tried it but it didn't work. I used 0.5f/(float)texture.getTextureWidth() and 0.5f/(float)texture.getTextureHeight(), is this right?

GL11.glBegin(GL11.GL_QUADS);
GL11.glTexCoord2f(0.5f/(float)texture.getTextureWidth(), 0.5f/(float)texture.getTextureHeight());
GL11.glVertex2f(0,0);
GL11.glTexCoord2f(1-0.5f/(float)texture.getTextureWidth(),0.5f/(float)texture.getTextureHeight());
GL11.glVertex2f(texture.getTextureWidth(),0);
GL11.glTexCoord2f(1-0.5f/(float)texture.getTextureWidth(),1-0.5f/(float)texture.getTextureHeight());
GL11.glVertex2f(texture.getTextureWidth(),texture.getTextureHeight());
GL11.glTexCoord2f(0.5f/(float)texture.getTextureWidth(),1-0.5f/(float)texture.getTextureHeight());
GL11.glVertex2f(0,texture.getTextureHeight());

GL11.glEnd();
Title: Re: LWJGL/Slick texture wrapping
Post by: quew8 on September 17, 2013, 18:53:00
Provided that

1-0.5f/(float)texture.getTextureWidth();

is the same as

1 - ( 0.5f/(float)texture.getTextureWidth() );

I always use brackets everywhere to avoid any ambiguity whatsoever the result of which is I don't actually know the operator precedence in Java.

Also something that I think I forget to mention before, GL_TEXTURE_MAG_FILTER and GL_TEXTURE_MIN_FILTER should really be set to GL_NEAREST really.

If the above is the case and it still isn't working, then if you say what is happening (as opposed to just "it didn't work") then we will be in a position to help.
Title: Re: LWJGL/Slick texture wrapping
Post by: Bingo90 on September 18, 2013, 12:52:59
Okay the drawing method looks like this now:

public static void drawTextureN(Texture texture, Vector2f position, Vector2f translation, Vector2f origin,Vector2f scale,float rotation, Color color, FlipState flipState)
{
texture.setTextureFilter(GL11.GL_NEAREST);


color.bind();
texture.bind();


        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);
   
    GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
    GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);

GL11.glTranslatef((int)position.x, (int)position.y, 0);
GL11.glTranslatef(-(int)translation.x, -(int)translation.y, 0);
GL11.glRotated(rotation, 0f, 0f, 1f);

GL11.glScalef(scale.x, scale.y, 1);

GL11.glTranslatef(-(int)origin.x, -(int)origin.y, 0);


GL11.glBegin(GL11.GL_QUADS);
GL11.glTexCoord2f(0.5f/(float)texture.getTextureWidth(), 0.5f/(float)texture.getTextureHeight());
GL11.glVertex2f(0,0);
GL11.glTexCoord2f(1-0.5f/(float)texture.getTextureWidth(),0.5f/(float)texture.getTextureHeight());
GL11.glVertex2f(texture.getTextureWidth(),0);
GL11.glTexCoord2f(1-0.5f/(float)texture.getTextureWidth(),1-0.5f/(float)texture.getTextureHeight());
GL11.glVertex2f(texture.getTextureWidth(),texture.getTextureHeight());
GL11.glTexCoord2f(0.5f/(float)texture.getTextureWidth(),1-0.5f/(float)texture.getTextureHeight());
GL11.glVertex2f(0,texture.getTextureHeight());

GL11.glEnd();

GL11.glLoadIdentity();
}


But the "pixel lines" are still the same as on the first post.
Title: Re: LWJGL/Slick texture wrapping
Post by: Bingo90 on September 19, 2013, 12:57:26
Seems to be difficult to fix :(
EDIT: By the way I don't think I've mentioned, that the textures are seperate files not one image.
Title: Re: LWJGL/Slick texture wrapping
Post by: Bingo90 on September 22, 2013, 13:13:35
OK, I couldn't solve it  by myself. Have you got any more advices?
Title: Re: LWJGL/Slick texture wrapping
Post by: quew8 on September 22, 2013, 19:01:37
As I said before, its called texture bleeding. I've given you two solutions already so I think the best thing now would be to look through the various solutions for yourself. If you have issues with or want clarification on a method then we can help but this really is a matter of personal preference.
Title: Re: LWJGL/Slick texture wrapping
Post by: Bingo90 on September 23, 2013, 16:38:34
Well, I'm not sure if you answered if my try to do the half pixel correction is right.
Title: Re: LWJGL/Slick texture wrapping
Post by: quew8 on September 26, 2013, 21:29:21
It looks right to me. But as I've said I've never done any of this. I just add a border around my textures where its needed. That is built into my texture loading code so once its loaded I just forget about it. If nothing else works then it really isn't that bad a solution.
Title: Re: LWJGL/Slick texture wrapping
Post by: Bingo90 on September 27, 2013, 14:32:31
Well, I just found out, that GL12.GL_CLAMP_TO_EDGE does the same that the half pixel correction does. The problem is I can't change the texture loading code because I'm loading the textures with slick.