2012-07-20 141 views
0

我嘗試在LWJGL中繪製基本紋理,但是我不能。Java openGL繪製紋理

我的主類:

package worldofportals; 

import java.io.IOException; 
import java.util.logging.FileHandler; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import org.lwjgl.LWJGLException; 
import org.lwjgl.Sys; 
import org.lwjgl.input.Keyboard; 
import org.lwjgl.input.Mouse; 
import org.lwjgl.opengl.Display; 
import org.lwjgl.opengl.DisplayMode; 
import org.lwjgl.opengl.GL11; 
import static org.lwjgl.opengl.GL11.*; 
import static org.lwjgl.util.glu.GLU.*; 
import worldofportals.texture.TextureLoader; 

/** 
* Initialize the program, handle the rendering, updating, the mouse and the 
* keyboard events. 
* 
* @author Laxika 
*/ 
public class WorldOfPortals { 

    /** 
    * Time at the last frame. 
    */ 
    private long lastFrame; 
    /** 
    * Frames per second. 
    */ 
    private int fps; 
    /** 
    * Last FPS time. 
    */ 
    private long lastFPS; 
    public static final int DISPLAY_HEIGHT = 1024; 
    public static final int DISPLAY_WIDTH = 768; 
    public static final Logger LOGGER = Logger.getLogger(WorldOfPortals.class.getName()); 
    int tileId = 0; 

    static { 
     try { 
      LOGGER.addHandler(new FileHandler("errors.log", true)); 
     } catch (IOException ex) { 
      LOGGER.log(Level.WARNING, ex.toString(), ex); 
     } 
    } 

    public static void main(String[] args) { 
     WorldOfPortals main = null; 
     try { 
      main = new WorldOfPortals(); 
      main.create(); 
      main.run(); 
     } catch (Exception ex) { 
      LOGGER.log(Level.SEVERE, ex.toString(), ex); 
     } finally { 
      if (main != null) { 
       main.destroy(); 
      } 
     } 
    } 

    /** 
    * Create a new lwjgl frame. 
    * 
    * @throws LWJGLException 
    */ 
    public void create() throws LWJGLException { 
     //Display 
     Display.setDisplayMode(new DisplayMode(DISPLAY_WIDTH, DISPLAY_HEIGHT)); 
     Display.setFullscreen(false); 
     Display.setTitle("World of Portals FPS: 0"); 
     Display.create(); 

     //Keyboard 
     Keyboard.create(); 

     //Mouse 
     Mouse.setGrabbed(false); 
     Mouse.create(); 

     //OpenGL 
     initGL(); 
     resizeGL(); 

     getDelta(); // call once before loop to initialise lastFrame 
     lastFPS = getTime(); 

     glEnable(GL_TEXTURE_2D); //Enable texturing 
     tileId = TextureLoader.getInstance().loadTexture("img/tile1.png"); 
    } 

    /** 
    * Destroy the game. 
    */ 
    public void destroy() { 
     //Methods already check if created before destroying. 
     Mouse.destroy(); 
     Keyboard.destroy(); 
     Display.destroy(); 
    } 

    /** 
    * Initialize the GL. 
    */ 
    public void initGL() { 
     //2D Initialization 
     glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 
     glDisable(GL_DEPTH_TEST); 
     glDisable(GL_LIGHTING); 
    } 

    /** 
    * Handle the keyboard events. 
    */ 
    public void processKeyboard() { 
    } 

    /** 
    * Handle the mouse events. 
    */ 
    public void processMouse() { 
    } 

    /** 
    * Handle the rendering. 
    */ 
    public void render() { 
     glPushMatrix(); 
     glClear(GL_COLOR_BUFFER_BIT); 

     for (int i = 0; i < 30; i++) { 
      for (int j = 30; j >= 0; j--) { // Changed loop condition here. 
       glBindTexture(GL_TEXTURE_2D, tileId); 
       // translate to the right location and prepare to draw 
       GL11.glTranslatef(20, 20, 0); 
       GL11.glColor3f(0, 0, 0); 

       // draw a quad textured to match the sprite 
       GL11.glBegin(GL11.GL_QUADS); 
       { 
        GL11.glTexCoord2f(0, 0); 
        GL11.glVertex2f(0, 0); 
        GL11.glTexCoord2f(0, 64); 
        GL11.glVertex2f(0, DISPLAY_HEIGHT); 
        GL11.glTexCoord2f(64, 64); 
        GL11.glVertex2f(DISPLAY_WIDTH, DISPLAY_HEIGHT); 
        GL11.glTexCoord2f(64, 0); 
        GL11.glVertex2f(DISPLAY_WIDTH, 0); 
       } 
       GL11.glEnd(); 
      } 
     } 

     // restore the model view matrix to prevent contamination 
     GL11.glPopMatrix(); 
    } 

    /** 
    * Resize the GL. 
    */ 
    public void resizeGL() { 
     //2D Scene 
     glViewport(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT); 

     glMatrixMode(GL_PROJECTION); 
     glLoadIdentity(); 
     gluOrtho2D(0.0f, DISPLAY_WIDTH, 0.0f, DISPLAY_HEIGHT); 
     glPushMatrix(); 

     glMatrixMode(GL_MODELVIEW); 
     glLoadIdentity(); 
     glPushMatrix(); 
    } 

    public void run() { 
     while (!Display.isCloseRequested() && !Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) { 
      if (Display.isVisible()) { 
       processKeyboard(); 
       processMouse(); 

       update(getDelta()); 
       render(); 
      } else { 
       if (Display.isDirty()) { 
        render(); 
       } 
      } 
      Display.update(); 
      Display.sync(60); 
     } 
    } 

    /** 
    * Game update before render. 
    */ 
    public void update(int delta) { 
     updateFPS(); 
    } 

    /** 
    * Get the time in milliseconds 
    * 
    * @return The system time in milliseconds 
    */ 
    public long getTime() { 
     return (Sys.getTime() * 1000)/Sys.getTimerResolution(); 
    } 

    /** 
    * Calculate how many milliseconds have passed since last frame. 
    * 
    * @return milliseconds passed since last frame 
    */ 
    public int getDelta() { 
     long time = getTime(); 
     int delta = (int) (time - lastFrame); 
     lastFrame = time; 

     return delta; 
    } 

    /** 
    * Calculate the FPS and set it in the title bar 
    */ 
    public void updateFPS() { 
     if (getTime() - lastFPS > 1000) { 
      Display.setTitle("World of Portals FPS: " + fps); 
      fps = 0; 
      lastFPS += 1000; 
     } 
     fps++; 
    } 
} 

我的質地裝載機:

package worldofportals.texture; 

import java.awt.image.BufferedImage; 
import java.io.File; 
import java.io.IOException; 
import java.nio.ByteBuffer; 
import javax.imageio.ImageIO; 
import org.lwjgl.BufferUtils; 
import static org.lwjgl.opengl.GL11.*; 
import org.lwjgl.opengl.GL12; 

public class TextureLoader { 

    private static final int BYTES_PER_PIXEL = 4;//3 for RGB, 4 for RGBA 
    private static TextureLoader instance; 

    private TextureLoader() { 
    } 

    public static TextureLoader getInstance() { 
     if (instance == null) { 
      instance = new TextureLoader(); 
     } 
     return instance; 
    } 

    /** 
    * Load a texture from file. 
    * 
    * @param loc the location of the file 
    * @return the id of the texture 
    */ 
    public int loadTexture(String loc) { 
     BufferedImage image = loadImage(loc); 
     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(); 

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

    /** 
    * Load an image from disc. 
    * 
    * @param loc the location of the image 
    * @return the image 
    */ 
    private BufferedImage loadImage(String loc) { 
     try { 
      return ImageIO.read(new File(loc)); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     return null; 
    } 
} 

這不是一個實際的遊戲,只是一個測試學習和實踐的java openGL的。也有人可以建議我一本關於OpenGL的好書嗎?

+0

請更詳細地描述您的實際問題。 – Tim 2012-07-20 18:11:32

+0

我嘗試渲染render()方法的東西,但沒有改變,我不知道爲什麼。 – 2012-07-20 19:40:02

+0

您的代碼是否在不綁定紋理的情況下工作?也就是說,你能渲染一個平坦的彩色圖元嗎? – Tim 2012-07-20 20:31:32

回答

2

你試過:

BufferedImage image = loadImage(loc); 
    image.getRGB(0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth()); 

    ByteBuffer buffer = BufferUtils.createByteBuffer(image.getWidth() * image.getHeight() * 4); 
    Color c; 

    for (int y = 0; y < image.getHeight(); y++) { 
     for (int x = 0; x < image.getWidth(); x++) { 
      c = new Color(image.getRGB(x, y)); 
      buffer.put((byte) c.getRed());  // Red component 
      buffer.put((byte) c.getGreen());  // Green component 
      buffer.put((byte) c.getBlue());    // Blue component 
      buffer.put((byte) c.getAlpha()); // Alpha component. Only for RGBA 
     } 
    } 

此外,如果你打算把阿爾法組件,您應該檢查組件的數量,並添加字母只有在有4,或總是使用4此外,請執行GL_RGBA而不是GL_RGBA8。

+0

謝謝!用你的代替裝載代碼是有幫助的。現在它工作正常。 :) Upwoted Simak也是,swapbuffers也是需要的。 – 2012-07-23 07:35:21

+0

試試LWJGL提供的漂亮的庫。它比使用字節緩衝區簡單得多。 – 2012-09-08 17:11:15

3

你不應該在渲染後調用 Display.swapBuffers()嗎?

+1

這就是我想知道的,但由於我不熟悉這個LWJGL的東西,我不確定Display.update是否已經這樣做:/ – Tim 2012-07-20 20:29:32

+1

是的,我看到另一個問題,你的紋理座標不應該從0到64,但從0到1 – 2012-07-20 20:36:19

+0

他確實啓用了換行。 – Tim 2012-07-21 15:35:49