Search code examples
javaopengllwjgl

Load a texture within OpenGL and LWJGL3 in Java


I'm following a tutorial about rendering text on the screen, and I can't seem to find a working way to load the font's texture. I tried the slick library, but it's outdatet: it uses methods of lwjgl2, not existing anymore in lwjgl3, so it throws a java.lang.NoSuchMethodError. In the internet I found that glfw (which is integrated in lwjgl) has a method called glfwLoadTexture2D, but it looks like it is only available in the C++ version of glfw. I also found a method in the openGL utils called gluBuild2DMipmaps, but it doesn't look like lwjgl has it: classes GLUtil and GLUtils exist, but they don't have any similar method, really they are almost blank.

I'm looking for something that loads the texture and give me back the texture's ID for further use, possibly without using external library.


Solution

  • LWJGL3 does not have such ready to use texture loading functions like it did with slick before. But you can use png images quite easily and all you need is PNGLoader you can find it here: https://mvnrepository.com/artifact/org.l33tlabs.twl/pngdecoder/1.0

    (Slicks PNG decoder also based on it)

    A fully functional method to use it

    public static Texture loadTexture(String fileName){
    
        //load png file
        PNGDecoder decoder = new PNGDecoder(ClassName.class.getResourceAsStream(fileName));
    
        //create a byte buffer big enough to store RGBA values
        ByteBuffer buffer = ByteBuffer.allocateDirect(4 * decoder.getWidth() * decoder.getHeight());
    
        //decode
        decoder.decode(buffer, decoder.getWidth() * 4, PNGDecoder.Format.RGBA);
    
        //flip the buffer so its ready to read
        buffer.flip();
    
        //create a texture
        int id = glGenTextures();
    
        //bind the texture
        glBindTexture(GL_TEXTURE_2D, id);
    
        //tell opengl how to unpack bytes
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    
        //set the texture parameters, can be GL_LINEAR or GL_NEAREST
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    
        //upload texture
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, decoder.getWidth(), decoder.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
    
        // Generate Mip Map
        glGenerateMipmap(GL_TEXTURE_2D);
    
        return new Texture(id); 
    }
    

    This method assumes a simple Texture class like:

    public class Texture{
    
        private int id;
    
        public Texture(int id){
            this.id = id;
        }
    
        public int getId(){
            return id;
        }
    }
    

    If you want width, height fields decoder.getWidth() decoder.getHeight() will returns you them.

    Finally you create a texture like:

    Texture texture = ClassName.loadTexture("/textures/texture.png");
    

    and

    texture.getId();
    

    will give you the corresponding texture id.