Java openGL绘制纹理

时间:2012-07-20 17:48:39

标签: java opengl textures draw lwjgl

我尝试在LWJGL中绘制基本纹理,但我不能。

我的主要课程:

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的好书?

2 个答案:

答案 0 :(得分:3)

你不应该打电话给 渲染后的Display.swapBuffers()?

答案 1 :(得分: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
        }
    }

另外,如果你打算放置Alpha组件,你应该检查组件的数量,并且只在有4个时添加alpha,或者总是使用4.另外,执行GL_RGBA而不是GL_RGBA8。