Question

I'm trying to learn how to use LWJGL libraries. Took me forever to find lessons. I eventually stumbled upon the NEHE lessons that teach OpenGL across many programming languages. I downloaded the LWJGL version of Lesson07 and noticed it was using DevIL for the images. I asked a question on here earlier on what i should use instead of DevIL, and an informative user suggested that i go with Slick instead. I got past Lesson06 after tweaking it for a while, but now i am seriously stuck on Lesson07.

Specifically HERE:

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
}

I've tried to get it working, tried substituting Slick stuff in, yet all i have tried has either crashed or led to a black screen.

What is the best way to do this with Slick?

Was it helpful?

Solution

This one was rather annoying. I think it was easier to convert than Lesson 06, but that could be because I was at least a little more used to it than I was in 06. It still took me all night to get this to work and I didn't figure it out until morning, though.

Here's my entire code. Lines are commented on the most annoying parts, along with some CODE commented to show what DIDN'T work. Any such code that was put in a comment is probably very fragmented so I'm not sure if you'll understand what I was trying to do, but I left it in anyway. The two places that I got stuck at are the two places with helpful comments and links.

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.
                                                                */
    }
}

This code has been run and FINALLY works. Using Slick-Util compresses it a LOT. You'll also notice that I changed the rate of change for the speeds; 0.01f was way too fast, so I put it to 0.001f instead. Hope this helps!

Links from my source code:

"Mipmapping"

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

OTHER TIPS

You'll probably need to adapt the code to use the standard LWJGL image / texture loading features, at least up to the point of the glBindTexture() call. After that point I think you should be OK, it's all pretty standard OpenGL from that point.

There is some pretty decent example code here that demonstrates what you need to do:

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

I think the key lines of code you need are:

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());

In other words, I think it's actually a bit simpler than using DevIL.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top