OpenGL light example not working using equivalent code in LWJGL

Started by xjia, October 09, 2013, 16:22:35

Previous topic - Next topic

xjia

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)



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();
	}
// ...

Fool Running

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();
	}
Programmers will, one day, rule the world... and the world won't notice until its too late.Just testing the marquee option ;D

xjia

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

Fool Running

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
Programmers will, one day, rule the world... and the world won't notice until its too late.Just testing the marquee option ;D

xjia

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 :-)