2012-05-29 16 views
13

¿Es posible cargar texturas PNG y dibujar cadenas en LWJGL SIN usar Slick Framework?LWJGL Texturas y cadenas

Cada vez que google "cómo cargar imágenes PNG en lwjgl" recibo respuestas como esto ->"oye sólo tiene que utilizar el TextureLoader del marco resbaladiza".
Lo mismo para "cómo dibujar cadenas en lwjgl" ->"sólo tiene que utilizar la clase TTFFont del marco resbaladiza"

Pero yo no quiero utilizar este diseño a mitad de camino-crossframework. Porque no creo que esta sea la mejor manera.

¿Hay Bibliotecas o Extensiones para LWJGL que solo están hechas para Texturas o Cuerdas?

Respuesta

22

Básicamente, se toma un BufferedImage, utilice getRBG() para obtener el RGB de cada píxel, tomar esos datos y ponerlo en un (tipo de datos utilizado para los datos de imagen de entrada a OpenGL) ByteBuffer, establecer algunos datos de textura, y crear el GL_TEXTURE_2D.

Este código por Krythic lo hace:

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

Para utilizar este código, hacer algo como esto:

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

Puede guardar la textureID como final variable (si la textura no cambios), o descargue la textura después de cada renderizado usando GL11.glDeleteTextures(textureID);

Para hacer texto, simplemente cree un BufferedImage manualmente, y use createGraphics() para obtener una instancia de graphics2D() para la imagen. Luego, use drawString() para dibujar en BufferedImage, cárguelo en TextureLoader, renderícelo en pantalla y descargue la textura usando el método anterior.

+4

El código anterior es mío, he escrito hace algún tiempo. ¡Imagina mi sorpresa al encontrarlo aleatoriamente en Stack Overflow! Me hace sentir cálido y confuso al saber que ha estado haciendo su camino por Internet. = P – Krythic

+0

Tu código es increíble. Lo uso cada vez –

+1

También se debe tener en cuenta que di este mismo fragmento a Dinnerbone para ayudarlo a crear Tinted Glass en Minecraft. – Krythic

0

LWJGL ahora incluye enlaces STB, que es la forma preferida de cargar imágenes y fuentes, sin tener que usar Slick o incluso AWT.

Para cargar un archivo 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); 
     } 
    } 
} 

Ejemplos más completas para la carga de imágenes, y la impresión de texto se pueden encontrar en el código fuente LWJGL:

org.lwjgl.demo.stb

Cuestiones relacionadas