2012-05-29 7 views
13

Ist es möglich, PNG Texturen und ziehen Strings in LWJGL ohne Verwendung der Slick-Framework zu laden?LWJGL Texturen und Streicher

Jedesmal, wenn ich google „wie PNG-Bilder in lwjgl zu laden“ Ich bekomme Antworten wie diese ->„hey benutzen Sie einfach die textureloader vom glatten Rahmen“.
Das Gleiche gilt für „wie Zeichenfolge in lwjgl ziehen“ ->„die TTFFont Klasse verwendet nur aus dem glatten Rahmen“

Aber ich will nicht diese auf halbem Weg-crossframework Design verwenden. Weil ich nicht denke, dass dies der beste Weg ist.

Gibt es Bibliotheken oder Erweiterungen für LWJGL, die für Texturen oder Strings nur gemacht werden?

Antwort

22

Grundsätzlich nehmen Sie ein BufferedImage, verwenden getRBG() die RGB jeden Pixel zu bekommen, dass die Daten nehmen und es in ein ByteBuffer (die Typdaten zur Eingabe von Bilddaten zu OpenGL verwendet), setzt einige Texturdaten und erstellen die GL_TEXTURE_2D.

Dieser Code von Krythic tut es:

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

diesen Code verwenden, tun Sie etwas wie folgt aus:

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

Sie können entweder die TextureID als final Variable (wenn die Textur speichern nie Änderungen), oder entladen Sie die Textur nach jedem Rendern mit GL11.glDeleteTextures(textureID);

Um Text zu erstellen, erstellen Sie einfach eine BufferedImage manuell und createGraphics() verwenden, um eine graphics2D() Instanz für das Bild zu bekommen. Dann verwenden drawString() auf die BufferedImage zu ziehen, laden sie in die TextureLoader, machen es auf dem Bildschirm, und entladen, die Textur über das Verfahren.

+4

Der obige Code ist mein, ich schrieb es vor einiger Zeit. Stellen Sie sich meine Überraschung vor, sie zufällig auf Stack Overflow zu finden! Ich fühle mich warm und verschwommen, um zu wissen, dass es sich im Internet herumgesprochen hat! = P – Krythic

+0

Ihr Code ist großartig. Ich benutze es jedes Mal. –

+1

Es sollte auch angemerkt werden, dass ich Dinnerbone den gleichen Ausschnitt gab, um ihm zu helfen, in Minecraft getöntes Glas zu schaffen. – Krythic

0

LWJGL enthält jetzt STB-Bindungen, die die bevorzugte Art und Weise des Laden von Bildern und Schriften sind, ohne Slick oder sogar AWT zu verwenden.

eine PNG laden:

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

Ausführlichere Beispiele für Bild Laden und Textdruck kann in LWJGL Quellcode gefunden werden:

org.lwjgl.demo.stb