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

标签 java opengl lwjgl devil

我正在尝试学习如何使用 LWJGL 库。我花了很长时间才找到教训。我最终偶然发现了 NEHE 类(class),该类(class)教授跨多种编程语言的 OpenGL。我下载了 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 实现此目的的最佳方法是什么?

最佳答案

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

这是我的整个代码。对最烦人的部分进行了注释,并注释了一些代码以显示哪些不起作用。放在注释中的任何此类代码可能都非常零散,因此我不确定您是否会理解我想要做什么,但无论如何我还是将其保留了下来。我陷入困境的两个地方是两个有有用评论和链接的地方。

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。希望这有帮助!

来 self 的源代码的链接:

"Mipmapping"

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

关于java - 如何将 NEHE Lesson07 中的 DevIL 转换为 Slick 库?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8352319/

相关文章:

Java-ThreadLocal 与 ConcurrentHashMap

java - 返回声明不起作用

c++ - 如何从 3D 点获取屏幕坐标? OpenGL

java - 渲染纹理深度

java - Slick2D如何开始动画,将其暂停直到发生某些事情,然后继续播放?

java - LWJGL Display.set宽度/高度?

java - 创建双泛型数组 - Java

java - 如何在 Java/Android 中解析 JSON 日期时间

带和不带照明的 OpenGL 顶点颜色

Java - 在屏幕上写文本