LWJGL Forum

Programming => Lightweight Java Gaming Library => Topic started by: xjia on October 09, 2013, 16:22:35

Title: OpenGL light example not working using equivalent code in LWJGL
Post by: xjia on October 09, 2013, 16:22:35
Hi!

I am learning the "light.c" example described at http://www.glprogramming.com/red/chapter05.html

After successfully run the example written in C, I modified it to draw a box instead of a sphere. After that, I also translated the C code into Java using LWJGL. However, the Java version doesn't work at all.

Both the C and Java versions are pasted at https://gist.github.com/stfairy/d2aa2f48a9a5801ae72e

The screenshot below is the expected result (which is generated by the C version, but the Java version only gives a black window)

(http://i.stack.imgur.com/5rv8F.png)

Thanks!

P.S. I also posted this question to StackOverflow but got no response... http://stackoverflow.com/questions/19264860/opengl-light-example-not-working-using-equivalent-code-in-lwjgl

EDIT: Thanks to the reply of Fool Running, I figured out it is because I didn't understand how nio.Buffer works.  After writing the values into the buffer, we also need to reset the cursor position by calling rewind().  Final code listed below.


// ...
private FloatBuffer floatBuffer(float... values) {
FloatBuffer buffer = BufferUtils.createFloatBuffer(values.length + 4);
buffer.put(values);
return (FloatBuffer) buffer.rewind();
}
// ...
Title: Re: OpenGL light example not working using equivalent code in LWJGL
Post by: Fool Running on October 09, 2013, 16:33:04
you are not flipping your float buffers so it is using zeros for the material stuff and the light position. Try using the following code instead:
private FloatBuffer matSpecular = floatBuffer(1, 1, 1, 1);
private FloatBuffer matShininess = floatBuffer(50, 0, 0, 0);
private FloatBuffer lightPosition = floatBuffer(1, 1, 1, 0);

private FloatBuffer floatBuffer(float... values) {
FloatBuffer buffer = BufferUtils.createFloatBuffer(values.length);
buffer.put(values);
return (FloatBuffer)buffer.flip();
}
Title: Re: OpenGL light example not working using equivalent code in LWJGL
Post by: xjia on October 10, 2013, 01:31:12
Quote from: Fool Running on October 09, 2013, 16:33:04
you are not flipping your float buffers so it is using zeros for the material stuff and the light position. Try using the following code instead:
private FloatBuffer matSpecular = floatBuffer(1, 1, 1, 1);
private FloatBuffer matShininess = floatBuffer(50, 0, 0, 0);
private FloatBuffer lightPosition = floatBuffer(1, 1, 1, 0);

private FloatBuffer floatBuffer(float... values) {
FloatBuffer buffer = BufferUtils.createFloatBuffer(values.length);
buffer.put(values);
return (FloatBuffer)buffer.flip();
}


Thanks for your prompt reply!

However it gives an exception now:

Exception in thread "main" java.lang.IllegalArgumentException: Number of remaining buffer elements is 1, must be at least 4. Because at most 4 elements can be returned, a buffer with at least 4 elements is required, regardless of actual returned element count
at org.lwjgl.BufferChecks.throwBufferSizeException(BufferChecks.java:162)
at org.lwjgl.BufferChecks.checkBufferSize(BufferChecks.java:189)
at org.lwjgl.BufferChecks.checkBuffer(BufferChecks.java:258)
at org.lwjgl.opengl.GL11.glMaterial(GL11.java:1847)
at LightExample.initGL(LightExample.java:29)
at LightExample.start(LightExample.java:100)
at LightExample.main(LightExample.java:112)

Even if I use values.length + 4, it gives exactly the same exception.

After I read the javadoc of nio.Buffer, I found this in the doc of flip():
QuoteThe limit is set to the current position and then the position is set to zero.
And I think the limit shouldn't be changed.
So I changed my code to use rewind() instead, and it works now!  ;D ;D ;D

Final code:

private FloatBuffer floatBuffer(float... values) {
FloatBuffer buffer = BufferUtils.createFloatBuffer(Math.max(4, values.length));
buffer.put(values);
return (FloatBuffer) buffer.rewind();
}
Title: Re: OpenGL light example not working using equivalent code in LWJGL
Post by: Fool Running on October 10, 2013, 12:24:19
Quote from: xjia on October 10, 2013, 01:31:12
However it gives an exception now:

Exception in thread "main" java.lang.IllegalArgumentException: Number of remaining buffer elements is 1, must be at least 4. Because at most 4 elements can be returned, a buffer with at least 4 elements is required, regardless of actual returned element count
at org.lwjgl.BufferChecks.throwBufferSizeException(BufferChecks.java:162)
at org.lwjgl.BufferChecks.checkBufferSize(BufferChecks.java:189)
at org.lwjgl.BufferChecks.checkBuffer(BufferChecks.java:258)
at org.lwjgl.opengl.GL11.glMaterial(GL11.java:1847)
at LightExample.initGL(LightExample.java:29)
at LightExample.start(LightExample.java:100)
at LightExample.main(LightExample.java:112)

Even if I use values.length + 4, it gives exactly the same exception.

Yes, that is why I changed the shininess to:
private FloatBuffer matShininess = floatBuffer(50, 0, 0, 0);
As a general rule, flip is better since it verifies that you put the number of values into the buffer as you thought you did. This is especially important when you start re-using buffers and don't always fill them up. But rewind works as well if you don't care about verification.  ;D
Title: Re: OpenGL light example not working using equivalent code in LWJGL
Post by: xjia on October 10, 2013, 15:05:57
Quote from: Fool Running on October 10, 2013, 12:24:19
Quote from: xjia on October 10, 2013, 01:31:12
However it gives an exception now:

Exception in thread "main" java.lang.IllegalArgumentException: Number of remaining buffer elements is 1, must be at least 4. Because at most 4 elements can be returned, a buffer with at least 4 elements is required, regardless of actual returned element count
at org.lwjgl.BufferChecks.throwBufferSizeException(BufferChecks.java:162)
at org.lwjgl.BufferChecks.checkBufferSize(BufferChecks.java:189)
at org.lwjgl.BufferChecks.checkBuffer(BufferChecks.java:258)
at org.lwjgl.opengl.GL11.glMaterial(GL11.java:1847)
at LightExample.initGL(LightExample.java:29)
at LightExample.start(LightExample.java:100)
at LightExample.main(LightExample.java:112)

Even if I use values.length + 4, it gives exactly the same exception.

Yes, that is why I changed the shininess to:
private FloatBuffer matShininess = floatBuffer(50, 0, 0, 0);
As a general rule, flip is better since it verifies that you put the number of values into the buffer as you thought you did. This is especially important when you start re-using buffers and don't always fill them up. But rewind works as well if you don't care about verification.  ;D

Thanks for this explanation.  Now I fully understand why there is an exception now :-)