Search code examples
javabindingtextureslwjgl

Java LWJGL / Slick-Util texture.bind() binds the same texture everytime


I've been programming for a few years now and wanted to try Java LWJGL, and people recommended using the Slick-Util library so I set all of it up, etc. and I've been working on several projects, never encountering this problem. However, I've encountered a problem where when binding a texture to openGL, the same incorrect texture is instead bound every time. I ran into this problem first with a project with a bunch of classes etc, and chose to try to condense the problem into one jar file.

So before I show the code, I wanna explain how the example file works. Basically, there are four PNG's within my project. They are contained in res/textures/character/texturesHere. The names of the PNG's consist as: char_d.png, char_u.png, char_l.png, char_r.png. I've checked all four and all four have different textures of the character's direction, as it should be. This is to prove that the resources of the project are NOT the problem. Here is the entire problem condensed into a "Main" class file.

package main_p;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.*;
import org.newdawn.slick.opengl.Texture;
import org.newdawn.slick.opengl.TextureLoader;

import static org.lwjgl.opengl.GL11.*;

public class Main
{

    public final int srcWidth = 1280;
    public final int srcHeight = 720;

    public float x = 150;
    public float y = 150;
    public float w = 40;
    public float h = 40;

    public Texture char_down;
    public Texture char_right;
    public Texture char_left;
    public Texture char_up;

    public Main()
    {
        try
        {
            Display.setTitle("Escape Alpha v0.0.1");
            Display.setDisplayMode(new DisplayMode(srcWidth, srcHeight));
            Display.create();
        }
        catch (LWJGLException e)
        {
            e.printStackTrace();
        }

        initGL();
        initTextures();
        loop();
    }

    public void loop()
    {
        glClear(GL_COLOR_BUFFER_BIT);

        while (!Display.isCloseRequested())
        {
            glBegin(GL_QUADS);

                char_left.bind();
                glTexCoord2f(0, 0);
                glVertex2f(x, y);
                glTexCoord2f(1, 0);
                glVertex2f(x + w, y);
                glTexCoord2f(1, 1);
                glVertex2f(x + w, y + h);
                glTexCoord2f(0, 1);
                glVertex2f(x, y + h);

            glEnd();

            Display.update();
            Display.sync(60);
        }

        Display.destroy();
    }

    public void initGL()
    {
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(0, srcWidth, srcHeight, 0, 1, -1);
        glMatrixMode(GL_MODELVIEW);
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    }

    public void initTextures()
    {
        char_down = loadTextureFrom("character/char_d.png");
        char_up = loadTextureFrom("character/char_u.png");
        char_left = loadTextureFrom("character/char_l.png");
        char_right = loadTextureFrom("character/char_r.png");
    }

    public Texture loadTextureFrom(String path)
    {
        try
        {
            return TextureLoader.getTexture("PNG", new FileInputStream(new File("res/textures/" + path)));
        }
        catch (FileNotFoundException e)
        {
            e.printStackTrace();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }

        return null;
    }

    public static void write(Object ob)
    {
        System.out.println(ob);
    }

    public static void main(String[] args)
    {
        new Main();
    }
}

One thing I've noticed is that within the initTextures() method, if I change the LAST loaded texture, ANY texture I bind will end up rendering the last texture loaded in initTextures()

In this example I bind Texture char_left, but instead it uses char_right, because it was the last one loaded in my initTextures() method. I can prove this because if I change whichever texture is LAST loaded in my initTextures() method, it ends up rendering that one instead, again disregarding the texture I tell it to bind. Like I said, I've checked all of my PNG's multiple times, and they all look good, and show the character facing the correct direction. My loadTextureFrom(String path) method is as any other texture loader. Nothing special about it really. I actually am using this exact method in 90% of my 2D projects for Java LWJGL / Slick-Util, and I've only recently started running into this problem. I'm at a loss for words, and have never ran into this problem before. Any help is greatly appreciated. :)

Edit 1:

I just did an important test. I checked the HashCode of all four textures, AFTER loading them within the initTextures() method.

public void initTextures()
{
    char_left = loadTextureFrom("character/char_l.png");
    char_right = loadTextureFrom("character/char_r.png");
    char_down = loadTextureFrom("character/char_d.png");
    char_up = loadTextureFrom("character/char_u.png");

    write(System.identityHashCode(char_left));
    write(System.identityHashCode(char_right));
    write(System.identityHashCode(char_down));
    write(System.identityHashCode(char_up));
}

It returned this:

1364345882
1878339755
1246651385
1619367563

I think this truly proves that the initTextures() method isn't the problem. Once again, any help is appreciated! This kind of 100% holds me back from doing any more work on any projects :/ Thanks! :)


Solution

  • I know this is an old post but I don't want anyone who sees this to go answerless. Basically, the texture bind call has to be outsde the "glBegin". That's all the problem is. You cannot bind textures inside of the glBegin call. If you don't do this, gl will just bind the last texture loaded.