LWJGL Textures and Strings

后端 未结 2 1791
伪装坚强ぢ
伪装坚强ぢ 2020-12-09 04:32

Is it possible to load PNG Textures and draw Strings in LWJGL WITHOUT using the Slick Framework?

Everytime I google \"how to load png images in lwj

相关标签:
2条回答
  • 2020-12-09 05:28

    Basically, you take a BufferedImage, use getRGB() to get the RGB of each pixel, take that data and put it into a ByteBuffer (the data type used to input image data to OpenGL), set some texture data, and create the GL_TEXTURE_2D.

    This code by Krythic does it:

    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import java.nio.ByteBuffer;
    
    import javax.imageio.ImageIO;
    
    import org.lwjgl.BufferUtils;
    import org.lwjgl.opengl.GL12;
    
    import static org.lwjgl.opengl.GL11.*;
    
    public class TextureLoader {
        private static final int BYTES_PER_PIXEL = 4;//3 for RGB, 4 for RGBA
           public static int loadTexture(BufferedImage image){
    
              int[] pixels = new int[image.getWidth() * image.getHeight()];
                image.getRGB(0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth());
    
                ByteBuffer buffer = BufferUtils.createByteBuffer(image.getWidth() * image.getHeight() * BYTES_PER_PIXEL); //4 for RGBA, 3 for RGB
    
                for(int y = 0; y < image.getHeight(); y++){
                    for(int x = 0; x < image.getWidth(); x++){
                        int pixel = pixels[y * image.getWidth() + x];
                        buffer.put((byte) ((pixel >> 16) & 0xFF));     // Red component
                        buffer.put((byte) ((pixel >> 8) & 0xFF));      // Green component
                        buffer.put((byte) (pixel & 0xFF));               // Blue component
                        buffer.put((byte) ((pixel >> 24) & 0xFF));    // Alpha component. Only for RGBA
                    }
                }
    
                buffer.flip(); //FOR THE LOVE OF GOD DO NOT FORGET THIS
    
                // You now have a ByteBuffer filled with the color data of each pixel.
                // Now just create a texture ID and bind it. Then you can load it using 
                // whatever OpenGL method you want, for example:
    
              int textureID = glGenTextures(); //Generate texture ID
                glBindTexture(GL_TEXTURE_2D, textureID); //Bind texture ID
    
                //Setup wrap mode
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);
    
                //Setup texture scaling filtering
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    
                //Send texel data to OpenGL
                glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, image.getWidth(), image.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
    
                //Return the texture ID so we can bind it later again
              return textureID;
           }
    
           public static BufferedImage loadImage(String loc)
           {
                try {
                   return ImageIO.read(MainClass.class.getResource(loc));
                } catch (IOException e) {
                    //Error Handling Here
                }
               return null;
           }
    }
    

    To use this code, do something like this:

    BufferedImage image = TextureLoader.loadImage("/res/test.png");//The path is inside the jar file
    int textureID = TextureLoader.loadTexture(image);
    

    You can either save the textureID as a final variable(if the texture never changes), or unload the texture after each render using GL11.glDeleteTextures(textureID);

    To do text, just create a BufferedImage manually, and use createGraphics() to get a graphics2D() instance for the image. Then, use drawString() to draw onto the BufferedImage, load it into the TextureLoader, render it onscreen, and unload the texture using the method above.

    0 讨论(0)
  • 2020-12-09 05:35

    LWJGL now includes STB bindings, which is the preferred way of loading images and fonts, without having to use Slick or even AWT.

    To load a PNG :

    import static org.lwjgl.opengl.GL11.GL_REPEAT;
    import static org.lwjgl.opengl.GL11.GL_LINEAR;
    import static org.lwjgl.opengl.GL11.GL_RGBA;
    import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
    import static org.lwjgl.opengl.GL11.GL_TEXTURE_MAG_FILTER;
    import static org.lwjgl.opengl.GL11.GL_TEXTURE_MIN_FILTER;
    import static org.lwjgl.opengl.GL11.GL_TEXTURE_WRAP_S;
    import static org.lwjgl.opengl.GL11.GL_TEXTURE_WRAP_T;
    import static org.lwjgl.opengl.GL11.GL_UNPACK_ALIGNMENT;
    import static org.lwjgl.opengl.GL11.GL_UNSIGNED_BYTE;
    import static org.lwjgl.opengl.GL11.glBindTexture;
    import static org.lwjgl.opengl.GL11.glGenTextures;
    import static org.lwjgl.opengl.GL11.glPixelStorei;
    import static org.lwjgl.opengl.GL11.glTexImage2D;
    import static org.lwjgl.opengl.GL11.glTexParameteri;
    import static org.lwjgl.opengl.GL30.glGenerateMipmap;
    import static org.lwjgl.stb.STBImage.stbi_load_from_memory;
    import static org.lwjgl.system.MemoryStack.stackPush;
    import static org.lwjgl.demo.util.IOUtils.ioResourceToByteBuffer;
    
    import java.nio.ByteBuffer;
    import java.nio.IntBuffer;
    
    import org.lwjgl.system.MemoryStack;
    
    public class Texture{
        private int width;
        private int height;
        private int id;
    
        public Texture(String imagePath) {
            ByteBuffer imageData = ioResourceToByteBuffer(imagePath, 1024);
    
            try (MemoryStack stack = stackPush()) {
                IntBuffer w = stack.mallocInt(1);
                IntBuffer h = stack.mallocInt(1);
                IntBuffer components = stack.mallocInt(1);
    
                // Decode texture image into a byte buffer
                ByteBuffer decodedImage = stbi_load_from_memory(imageData, w, h, components, 4);
    
                this.width = w.get();
                this.height = h.get();
    
                // Create a new OpenGL texture 
                this.id = glGenTextures();
    
                // Bind the texture
                glBindTexture(GL_TEXTURE_2D, this.id);
    
                // Tell OpenGL how to unpack the RGBA bytes. Each component is 1 byte size
                glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    
                // Upload the texture data
                glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this.width, this.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, decodedImage);
    
                // Generate Mip Map
                glGenerateMipmap(GL_TEXTURE_2D);
            }
        }
    }
    

    More complete examples for image loading, and text printing can be found in LWJGL source code :

    org.lwjgl.demo.stb

    0 讨论(0)
提交回复
热议问题