如何将NEHE Lesson07中的DevIL转换为Slick库?

时间:2011-12-02 05:55:53

标签: java opengl lwjgl devil

我正在尝试学习如何使用LWJGL库。让我永远找到教训。我最终偶然发现了在许多编程语言中教授OpenGL的NEHE课程。我下载了Lesson07的LWJGL版本并注意到它正在使用DevIL来处理图像。 我之前在这里问了一个关于我应该使用什么而不是DevIL的问题,一位信息丰富的用户建议我选择Slick。经过一段时间的调整后,我已经过了Lesson06,但现在我严重陷入Lesson07。

具体在这里:

private int[] loadTexture(String path) {
    IntBuffer image = ByteBuffer.allocateDirect(4).order(ByteOrder.nativeOrder()).asIntBuffer();
    IL.ilGenImages(1, image);
    IL.ilBindImage(image.get(0));
    IL.ilLoadImage(path);
    IL.ilConvertImage(IL.IL_RGB, IL.IL_BYTE);
    ByteBuffer scratch = ByteBuffer.allocateDirect(IL.ilGetInteger(IL.IL_IMAGE_WIDTH) * IL.ilGetInteger(IL.IL_IMAGE_HEIGHT) * 3);
    IL.ilCopyPixels(0, 0, 0, IL.ilGetInteger(IL.IL_IMAGE_WIDTH), IL.ilGetInteger(IL.IL_IMAGE_HEIGHT), 1, IL.IL_RGB, IL.IL_BYTE, scratch);

    // Create A IntBuffer For Image Address In Memory
    IntBuffer buf = ByteBuffer.allocateDirect(12).order(ByteOrder.nativeOrder()).asIntBuffer();
    GL11.glGenTextures(buf); // Create Texture In OpenGL

    GL11.glBindTexture(GL11.GL_TEXTURE_2D, buf.get(0));
    // Typical Texture Generation Using Data From The Image

    // Create Nearest Filtered Texture
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, buf.get(0));
    GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
    GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
    GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGB, IL.ilGetInteger(IL.IL_IMAGE_WIDTH), 
            IL.ilGetInteger(IL.IL_IMAGE_HEIGHT), 0, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, scratch);

    // Create Linear Filtered Texture
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, buf.get(1));
    GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
    GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
    GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGB, IL.ilGetInteger(IL.IL_IMAGE_WIDTH), 
            IL.ilGetInteger(IL.IL_IMAGE_HEIGHT), 0, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, scratch);

    // Create MipMapped Texture
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, buf.get(2));
    GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
    GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR_MIPMAP_NEAREST);
    GLU.gluBuild2DMipmaps(GL11.GL_TEXTURE_2D, 3, IL.ilGetInteger(IL.IL_IMAGE_WIDTH), 
            IL.ilGetInteger(IL.IL_IMAGE_HEIGHT), GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, scratch);

  return new int[]{ buf.get(0), buf.get(1), buf.get(2) };     // Return Image Addresses In Memory
}

我试图让它工作,尝试用Slick代替,但我尝试的所有都已经崩溃或导致黑屏。

使用Slick执行此操作的最佳方法是什么?

2 个答案:

答案 0 :(得分:1)

您可能需要调整代码以使用标准的LWJGL图像/纹理加载功能,至少在glBindTexture()调用之前。在那之后我认为你应该没问题,从那时起它就是非常标准的OpenGL。

这里有一些相当不错的示例代码可以演示您需要做什么:

http://lwjgl.org/wiki/index.php?title=Slick-Util_Library_-_Part_1_-_Loading_Images_for_LWJGL

我认为您需要的关键代码行是:

import org.newdawn.slick.opengl.Texture;
import org.newdawn.slick.opengl.TextureLoader;
...   
Texture texture = TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream("res/image.png"));
...
GL11.glBind(texture.getTextureID());

换句话说,我认为它实际上比使用DevIL更简单。

答案 1 :(得分:1)

这个很烦人。我认为转换比第06课更容易,但那可能是因为我至少比06年更习惯它。它仍然花了我一整夜才能让它工作,我没想到它但直到早上。

这是我的整个代码。线条被评论最烦人的部分,以及一些评论的CODE,以显示什么不起作用。放在评论中的任何此类代码可能都非常分散,所以我不确定您是否理解我想要做什么,但无论如何我都把它留了下来。我被困在的两个地方是两个有帮助的评论和链接的地方。

package LWJGLTest2;

import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferInt;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.util.glu.GLU.*;

import java.io.IOException;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;

import org.lwjgl.util.glu.GLU;
import org.newdawn.slick.opengl.Texture;
import org.newdawn.slick.opengl.TextureLoader;
import org.newdawn.slick.util.ResourceLoader;
/**
 *
 * @author Jay
 */
public class LWJGLTest2 {
    public static final int WIDTH = 640;
    public static final int HEIGHT = 480;
    public static final Logger LOGGER = Logger.getLogger(LWJGLTest2.class.getName());
    float xrot;
    float yrot;
    float xspeed;
    float yspeed;
    float zpos = -5f;
    boolean lp;
    boolean fp;
    boolean light;
    final float[] AMBIENT = {.5f, .5f, .5f, 1f};
    final float[] DIFFUSE = {1f, 1f, 1f, 1f};
    final float[] LPOSITION = {0f, 0f, 2f, 1f};
    int filter;
    BufferedImage textureImage;
    Texture texture[] = new Texture[3];

    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) {
        LWJGLTest2 main = null;

        try {
            main = new LWJGLTest2();
            main.create();
            main.run();
        } catch (Exception ex) {
            LOGGER.log(Level.SEVERE, ex.toString(), ex);
        } finally {
            if (main != null) {
                main.destroy();
            }
        }
    }

    public void create() throws LWJGLException {
        // Display
        Display.setDisplayMode(new DisplayMode(WIDTH, HEIGHT));
        Display.setFullscreen(false);
        Display.setTitle("LWJGL Test");
        Display.create();

        // Keyboard
        Keyboard.create();

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

        // OpenGL
        initGL();
        resizeGL();
    }

    public void destroy() {
        Mouse.destroy();
        Keyboard.destroy();
        Display.destroy();
    }

    public void initGL() {
        try {
            loadTextures();
        } catch (IOException ex) {
            System.err.println(ex); System.exit(0);
        }

        glEnable(GL_TEXTURE_2D);
        glShadeModel(GL_SMOOTH);
        glClearColor(0f, 0f, 0f, 0.5f);
        glClearDepth(1f);
        glEnable(GL_DEPTH_TEST);
        glDepthFunc(GL_LEQUAL);
        glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);



        //FloatBuffer scratch = BufferUtils.createFloatBuffer(8);  // 4 for the values and 4 for the extra buffer
        //scratch.put(AMBIENT);
        ByteBuffer scratch = ByteBuffer.allocateDirect(16);
        scratch.order(ByteOrder.nativeOrder());
        //scratch.put(AMBIENT);
        glLight(GL_LIGHT1, GL_AMBIENT, (FloatBuffer)scratch.asFloatBuffer().put(AMBIENT).flip());  // 3rd argument used to be only scratch
        //scratch = ByteBuffer.allocateDirect(32).asFloatBuffer();    // reset the buffer to prevent an overflow
        //scratch.put(DIFFUSE);
        glLight(GL_LIGHT1, GL_DIFFUSE, (FloatBuffer)scratch.asFloatBuffer().put(AMBIENT).flip());
        //scratch = ByteBuffer.allocateDirect(32).asFloatBuffer();
        //scratch.put(LPOSITION);
        glLight(GL_LIGHT1, GL_POSITION, (FloatBuffer)scratch.asFloatBuffer().put(AMBIENT).flip());
        glEnable(GL_LIGHT1);
    }

    public void resizeGL() {
        glViewport(0, 0, WIDTH, HEIGHT);

        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(45f, (float)WIDTH/(float)HEIGHT, 0.1f, 100f);

        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
    }

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

                render();
                Display.update();
            }
        }
    }

    public void checkInput() {
        if (Keyboard.isKeyDown(Keyboard.KEY_L) && !lp) {
            lp = true;
            light = !light;

            if (light)
                glEnable(GL_LIGHTING);
            else
                glDisable(GL_LIGHTING);
        }
        if (!Keyboard.isKeyDown(Keyboard.KEY_L))
            lp = false;

        if (Keyboard.isKeyDown(Keyboard.KEY_F) && !fp) {
            fp = true;
            filter = (filter + 1) % 3;
        }
        if (!Keyboard.isKeyDown(Keyboard.KEY_F))
            fp = false;

        if (Keyboard.isKeyDown(Keyboard.KEY_PRIOR))
            zpos -= 0.02f;
        if (Keyboard.isKeyDown(Keyboard.KEY_NEXT))
            zpos += 0.02f;

        if (Keyboard.isKeyDown(Keyboard.KEY_UP))
            xspeed -= 0.001f;
        if (Keyboard.isKeyDown(Keyboard.KEY_DOWN))
            xspeed += 0.001f;
        if (Keyboard.isKeyDown(Keyboard.KEY_RIGHT))
            yspeed -= 0.001f;
        if (Keyboard.isKeyDown(Keyboard.KEY_LEFT))
            yspeed += 0.001f;
    }

    public void render() {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glLoadIdentity();
        glTranslatef(0f, 0f, zpos);

        glRotatef(xrot, 1f, 0f, 0f);
        glRotatef(yrot, 0f, 1f, 0f);

        texture[filter].bind();

        glBegin(GL_QUADS);
            // Front Face
            glNormal3f(0f, 0f, 1f);
            glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);  // Bottom Left Of The Texture and Quad
            glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);  // Bottom Right Of The Texture and Quad
            glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);  // Top Right Of The Texture and Quad
            glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);  // Top Left Of The Texture and Quad
            // Back Face
            glNormal3f(0f, 0f, -1f);
            glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);  // Bottom Right Of The Texture and Quad
            glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);  // Top Right Of The Texture and Quad
            glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);  // Top Left Of The Texture and Quad
            glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);  // Bottom Left Of The Texture and Quad
            // Top Face
            glNormal3f(0f, 1f, 0f);
            glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);  // Top Left Of The Texture and Quad
            glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,  1.0f,  1.0f);  // Bottom Left Of The Texture and Quad
            glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,  1.0f,  1.0f);  // Bottom Right Of The Texture and Quad
            glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);  // Top Right Of The Texture and Quad
            // Bottom Face
            glNormal3f(0f, -1f, 0f);
            glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f);  // Top Right Of The Texture and Quad
            glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f);  // Top Left Of The Texture and Quad
            glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);  // Bottom Left Of The Texture and Quad
            glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);  // Bottom Right Of The Texture and Quad
            // Right face
            glNormal3f(1f, 0f, 0f);
            glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);  // Bottom Right Of The Texture and Quad
            glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);  // Top Right Of The Texture and Quad
            glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);  // Top Left Of The Texture and Quad
            glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);  // Bottom Left Of The Texture and Quad
            // Left Face
            glNormal3f(-1f, 0f, 0f);
            glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);  // Bottom Left Of The Texture and Quad
            glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);  // Bottom Right Of The Texture and Quad
            glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);  // Top Right Of The Texture and Quad
            glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);  // Top Left Of The Texture and Quad
        glEnd();

        xrot += xspeed;
        yrot += yspeed;
    }

    public void loadTextures() throws IOException {
        //textureImage = ImageIO.read(this.getClass().getResourceAsStream("Crate.png"));
        texture[0] = TextureLoader.getTexture("BMP", this.getClass().getResourceAsStream("Crate.bmp"), true, GL_NEAREST);
        texture[1] = TextureLoader.getTexture("BMP", this.getClass().getResourceAsStream("Crate.bmp"), true, GL_LINEAR);
        texture[2] = TextureLoader.getTexture("BMP", this.getClass().getResourceAsStream("Crate.bmp"), true);
        //ByteBuffer scratch = ByteBuffer.wrap(((DataBufferByte)textureImage.getRaster().getDataBuffer()).getData());
        //ByteBuffer scratch = ByteBuffer.allocateDirect(((DataBufferByte)textureImage.getRaster().getDataBuffer()).getData().length + 3);
        /*
         *  The +3 in the last statement is important!  Without it, you get this:
         *      SEVERE: java.lang.IllegalArgumentException: Number of remaining buffer
         *      elements is 0, must be at least 3. Because at most 3 elements can be
         *      returned, a buffer with at least 3 elements is required, regardless of
         *      actual returned element count
         */
        //scratch.put(((DataBufferByte)textureImage.getRaster().getDataBuffer()).getData());  // RED
        //scratch.rewind();   // NOW IT'S RED.
        //for (int i = 0; i < scratch.limit(); ++i)
        //    System.out.println(scratch);
        texture[2].bind();
        //ByteBuffer scratch = ByteBuffer.allocateDirect(texture[2].getTextureData().length);
        //scratch.order(ByteOrder.nativeOrder());

        //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
        //GLU.gluBuild2DMipmaps(GL_TEXTURE_2D, 3, (int)texture[2].getWidth(), (int)texture[2].getHeight(), GL_RGB, GL_UNSIGNED_BYTE, (ByteBuffer)scratch.put(texture[2].getTextureData()).flip());

        org.lwjgl.opengl.GL30.glGenerateMipmap(GL_TEXTURE_2D); /* http://slick.javaunlimited.net/viewtopic.php?t=2755
                                                                *  Not sure if this worked properly, but I rather enjoy
                                                                *  not crying so I'll just smile and nod.
                                                                *  I went through a LOT of other options before I got this.
                                                                *  I also tried using the trick I found at
                                                                *  http://lwjgl.org/forum/index.php?action=printpage;topic=2233.0
                                                                *  (used above, in initGL) but that didn't work either.
                                                                */
    }
}

此代码已运行且最终有效。使用Slick-Util压缩它很多。你还会注意到我改变了速度的变化率; 0.01f太快了,所以我把它换成0.001f。希望这有帮助!

我的源代码链接:

"Mipmapping"

"Why is adding of the light in lwjgl so difficult?"