FloatBuffers and glGetTexParameter

After much gnashing of teeth, I finally figured out how OpenGL handles images and it, of course, makes perfect sense. I’m having a problem with getting texture information, though. Basically, I just want to use glGetTexParameter(…) to pull the width and height off a texture, but I need to use Buffers (In my case, FloatBuffers) to do it. These are things that I have never used and after spending several hours searching forums and the net, can’t find a simple tutorial on them. I currently have the error “FloatBuffer is not direct”. Here’s my 2D drawing method:


  public static void drawSprite(int sprite, int xLocation, int yLocation)
  {
    org.lwjgl.opengl.GL11.glPushMatrix();
    org.lwjgl.opengl.GL11.glBindTexture(org.lwjgl.opengl.GL11.GL_TEXTURE_2D, sprite);
    org.lwjgl.opengl.GL11.glTranslatef(xLocation, yLocation, 0);
    org.lwjgl.opengl.GL11.glColor3f(1, 1, 1);
    org.lwjgl.opengl.GL11.glBegin(org.lwjgl.opengl.GL11.GL_QUADS);
    float[] floats1 = new float[6];
    floats1[0] = 0;
    floats1[1] = 0;
    java.nio.FloatBuffer floats;
    floats = java.nio.FloatBuffer.wrap(floats1);
    floats.position(0);
    org.lwjgl.opengl.GL11.glGetTexParameter(org.lwjgl.opengl.GL11.GL_TEXTURE_2D,
            org.lwjgl.opengl.GL11.GL_TEXTURE_WIDTH, floats);
    floats.position(1);
    org.lwjgl.opengl.GL11.glGetTexParameter(org.lwjgl.opengl.GL11.GL_TEXTURE_2D,
            org.lwjgl.opengl.GL11.GL_TEXTURE_HEIGHT, floats);
    floats.position(0);
    float width = floats.get();
    floats.position(1);
    float height = floats.get();
    org.lwjgl.opengl.GL11.glTexCoord2f(0, 0);
    org.lwjgl.opengl.GL11.glVertex2f(0, 0);
    org.lwjgl.opengl.GL11.glTexCoord2f(0, height);
    org.lwjgl.opengl.GL11.glVertex2f(0, height);
    org.lwjgl.opengl.GL11.glTexCoord2f(width, height);
    org.lwjgl.opengl.GL11.glVertex2f(width, height);
    org.lwjgl.opengl.GL11.glTexCoord2f(width, 0);
    org.lwjgl.opengl.GL11.glVertex2f(width, 0);
    org.lwjgl.opengl.GL11.glEnd();
    org.lwjgl.opengl.GL11.glPopMatrix();
  }

It gives me the same error if I try creating the buffer using the .allocate() method as well.

Those FloatBuffers are awkward. Recently started on LWJGL myself and had major problems. Eventually I twigged that the reason for using the NIO type buffer is that the native code can directly access it… but only if it is a ‘direct’ buffer. You can create one of these as a byte buffer and then tell java to pretend it’s one of the others. However there’s a useful static method in the LWJGL Utils package that does all the hard work for you. Big sigh of relief here. But then it still didn’t work! Turns out you need to rewind it after putting data in.

Your problem is slightly different, since you want to read data back, rather than stuff it in. I expect it’s going to be similar though.

Here’s a snippit of working code:

            GL11.glEnable(GL11.GL_LIGHTING);
            float[] al = { 0.3f, 0.3f, 0.3f, 0.0f }; // RGBA for ambient light
            ambientLight = BufferUtils.createFloatBuffer(al.length);
            ambientLight.put(al);
            ambientLight.rewind();
            GL11.glLight(GL11.GL_LIGHT0, GL11.GL_AMBIENT, ambientLight);

Okay, thanks, that helped with the floatbuffer. I’m still having some problems though, which is ticking me off. I originally made a little 2D engine using the spaceinvaders example textureloader. Unfortunately, I did that on my desktop and my monitor died in a spritzing of sparks, so I can’t look at my code to see how I did it. Now I want to use devIL to load images. How I understood it to work was that when devIL loaded the texture, it would return a number. I use that number to bind the texture, assuming that openGL remembers that number in relation to the texture. Basically, here’s what I’m doing:

main class (snippet):


            DisplayMode mode = MyGraphics.getDisplayMode(1024, 768, 32, 60);
            Display.setDisplayMode(mode);
            Display.create();
            Display.setFullscreen(true);
            MyGraphics.setGL2D();

            IL.ilInit();
            int craftImage = ILUT.ilutGLLoadImage("craft.pcx");
            
            
            MyGraphics.setBuffer();
            MyGraphics.drawSprite(craftImage, 100, 100);
            Display.update();
            Thread.sleep(2000);

The MyGraphics class is all static methods - basically shortcuts I’m creating to simplify the display operations.


  public static void drawSprite(int sprite, int xLocation, int yLocation)
  {
    org.lwjgl.opengl.GL11.glPushMatrix();
    org.lwjgl.opengl.GL11.glBindTexture(org.lwjgl.opengl.GL11.GL_TEXTURE_2D, sprite);
    org.lwjgl.opengl.GL11.glTranslatef(xLocation, yLocation, 0);
    org.lwjgl.opengl.GL11.glColor3f(1, 1, 1);
    org.lwjgl.opengl.GL11.glBegin(org.lwjgl.opengl.GL11.GL_QUADS);
    java.nio.FloatBuffer floats = org.lwjgl.BufferUtils.createFloatBuffer(6);
    //floats.position(0);
    org.lwjgl.opengl.GL11.glGetTexParameter(org.lwjgl.opengl.GL11.GL_TEXTURE_2D,
            org.lwjgl.opengl.GL11.GL_TEXTURE_WIDTH, floats);
    floats.position(1);
    org.lwjgl.opengl.GL11.glGetTexParameter(org.lwjgl.opengl.GL11.GL_TEXTURE_2D,
            org.lwjgl.opengl.GL11.GL_TEXTURE_HEIGHT, floats);
    floats.rewind();
    //floats.position(0);
    //float width = floats.get();
    //floats.position(1);
    //float height = floats.get();
    float width = 64;
    float height = 64;
    System.out.println(width + ", " + height);
    org.lwjgl.opengl.GL11.glTexCoord2f(0, 0);
    org.lwjgl.opengl.GL11.glVertex2f(0, 0);
    org.lwjgl.opengl.GL11.glTexCoord2f(0, height);
    org.lwjgl.opengl.GL11.glVertex2f(0, height);
    org.lwjgl.opengl.GL11.glTexCoord2f(width, height);
    org.lwjgl.opengl.GL11.glVertex2f(width, height);
    org.lwjgl.opengl.GL11.glTexCoord2f(width, 0);
    org.lwjgl.opengl.GL11.glVertex2f(width, 0);
    org.lwjgl.opengl.GL11.glEnd();
    org.lwjgl.opengl.GL11.glPopMatrix();
  }

I entered “64” manually for my width and height because I wasn’t sure if the floatbuffer was working or not. My problem now seems to be that the Display.update(); method call is an “Invalid operation”. I must be forgetting something important.

Just so you know, here’s the .setBuffer() method:


  public static void setBuffer()
  {
    org.lwjgl.opengl.GL11.glClear(org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT | org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT);
    org.lwjgl.opengl.GL11.glMatrixMode(org.lwjgl.opengl.GL11.GL_MODELVIEW);
    org.lwjgl.opengl.GL11.glLoadIdentity();    
  }

There is no need for an array here. You can simply do that :



// create a buffer
FloatBuffer ambientLight = BufferUtils.createFloatBuffer(4);

// fill it with RGB for ambient light
ambientLight.put( 0.3f ).put( 0.3f ).put( 0.3f ).put( 0.0f );
ambientLight.rewind();

// That's it !
glLight( GL_LIGHT0, GL_AMBIENT, ambientLight );


To answer NovaC, a direct buffer is simply a buffer created using the static method ByteBuffer.allocateDirect(). See ByteBuffer’s javadoc for in deep explanations. I think BufferUtils does nothing more than calling that.

Assuming IL loads the image into a texture, the returned number is a handle to an OpenGL ‘texture object’. But other than that you’re ok.

Display.update() checks against glGetError, which is how OpenGL reports errors at runtime. Usually you’d now look at all the code that you just changed and narrow it down to a single OpenGL call (with copious use of the LWJGL checkErrors method (may be named something different)). Then you can look up that function in the OpenGL docs (MSDN has a complete set for up to 1.1) and it’ll tell you what you’re doing wrong.

However in this case its probably your calls to glGetTexParameter. You can only call a few OpenGL functions between a glBegin/End (vertex, colour, texcoord) and anything else will error like this. Just move your calls outside the begin/end pair.

But actually, once loaded into GL, all texture coords are between 0 and 1 for the full image, regardless of the actual texture resolution. So you don’t even need the get width/height calls, just switch them both with 1 and you’ll be fine.

Okay, so I resolved the Display.update() problem - I needed to add another call before I started writing to the buffer. I also resolved my image loading problems. Relative directory structure and all that jazz. The problem I have now is related to the actual display.

It might still be a problem with the image loading process, but I’m still not getting any output. Also, regardless of using 0 - 1 for my texture coords, what about vertex coords for created the quad?

I think openIL is NOT giving me the full story. Probably the same with glGetTexParameter as it doesn’t actually affect the floatbuffer. From what I understood, glGetTexParameter would put the proper attribute value into the FloatBuffer, except when I analyze the buffer, nothing is being entered into it. Ever. Even when I move it to before the glBegin statement.

Originally, I was getting a “0” back from the ilutGLLoadImage() function. I changed the filename to absolute and now I get “1”. I assume that means its actually loading, but nothing else was affected. glGetTexParameter still doesn’t do anything with the FloatBuffer and I still get no output to the display.

I don’t know what I could be missing or not understanding. The tutorials for OpenIL made it clear that this loader was supposed to simplify the process when working with openGL textures.

[quote]It might still be a problem with the image loading process, but I’m still not getting any output. Also, regardless of using 0 - 1 for my texture coords, what about vertex coords for created the quad?
[/quote]
Use whatever you like :stuck_out_tongue: The texture will just get scaled. Are you at least getting a white quad on screen? Invalid texture state results in pure white instead of texture colour. Or do you not see any quad at all? (In which case your vertex positions and/or projection setup is wrong).

0 for a texture id is invalid, and probably indicates something went wrong. Anything >0 should be valid. Did you remember to glEnable(GL_TEXTURE_2D) ?