0

working with LWJGL's implementation of OpenGL, and trying to work with the lighting functions. This requires the creation of FloatBuffers to pass to OpenGL. Relevant code follows:

GL11.glClearColor(0,0,0,0);

float[] ambientLight={(float).3,(float).5,(float).8,1};
FloatBuffer ambientLightB = FloatBuffer.allocate(4);
ambientLightB.put(ambientLight);

float[] diffuseLight={(float).25,(float).25,(float).25,1};
FloatBuffer diffuseLightB = FloatBuffer.allocate(4);
diffuseLightB.put(diffuseLight);

float[] lightPosition={0,0,1,1};
FloatBuffer lightPositionB = FloatBuffer.allocate(4);
lightPositionB.put(lightPosition);

float[] matAmbient={1,1,1,1};
FloatBuffer matAmbientB = FloatBuffer.allocate(4);
matAmbientB.put(matAmbient);

float[] matDiff={1,1,1,1};
FloatBuffer matDiffB = FloatBuffer.allocate(4);
matDiffB.put(matDiff);

GL11.glShadeModel(GL11.GL_SMOOTH);
GL11.glEnable(GL11.GL_DEPTH_TEST);
GL11.glEnable(GL11.GL_CULL_FACE);
GL11.glFrontFace(GL11.GL_CCW);
GL11.glEnable(GL11.GL_LIGHTING);

GL11.glMaterial(GL11.GL_FRONT,GL11.GL_AMBIENT,matAmbientB);
GL11.glMaterial(GL11.GL_FRONT, GL11.GL_DIFFUSE,matDiffB);
GL11.glLight(GL11.GL_LIGHT0,GL11.GL_AMBIENT,ambientLightB);
GL11.glLight(GL11.GL_LIGHT0,GL11.GL_DIFFUSE,diffuseLightB);
GL11.glLight(GL11.GL_LIGHT0,GL11.GL_POSITION,lightPositionB);
GL11.glEnable(GL11.GL_LIGHT0);

The first call I make to glMaterial gives the following error:

Exception in thread "main" java.lang.IllegalArgumentException: Number of remaining buffer elements is 0, 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

Not quite sure what I'm doing wrong here, seems to be a problem in the creation of the FloatBuffer.

genpfault
  • 51,148
  • 11
  • 85
  • 139
sol_var
  • 847
  • 1
  • 9
  • 9

3 Answers3

1

Flip() the buffer after the put(), or use FloatBuffer.wrap(), which would also save you some lines of code. Or maybe it needs another 4 slots, so allocate 8 elements.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • I don't see any flip() method in the java documentation of the class... Wrap doesn't work, that gives me an error saying I need a direct Buffer... Shouldn't need 8 buffers, the equivalent function call in C takes a size 4 array – sol_var Mar 03 '12 at 01:35
  • Flip was in the super class, gave the same direct buffer error – sol_var Mar 03 '12 at 05:30
  • @sol_var (1) Buffer.flip() does exist, look again. It is inherited. (2) If you really need a direct buffer, `allocate()` shouldn't work either, you would have to use `allocateDirect()`. Something wrong here. (3) There is no `C` equivalent of `FloatBuffer`. I think you're going to have to look again at the documentation for the package you're using. – user207421 Mar 03 '12 at 09:02
  • EJP, thank you for your information, it was very helpful. Just to clarify, by C equivalent, I meant the equivalent of the function call, not the equivalent of the FloatBuffer. In C the function glMaterialfv would be called instead for the exact same effect, and its third parameter is a pointer to a float array of size four instead of a FloatBuffer of size 4. – sol_var Mar 03 '12 at 14:57
1

The solution ended up requiring another function call specific to LWJGL (BufferUtils.createFloatBuffer), as well as the flip() method. The following correctly initialized the buffer

float[] matAmbient={1,1,1,1};
FloatBuffer matAmbientB = BufferUtils.createFloatBuffer(4);
matAmbientB.put(matAmbient);
matAmbientB.flip();
sol_var
  • 847
  • 1
  • 9
  • 9
0

The idea of using FloatBuffers with LWJGL is so native code can use there buffers directly, in order for this to work correctly they should be used like so,

//Create a directly allocated buffer in bytes (16 = 4 Floats * size of float in bytes)
ByteBuffer bytes = ByteBuffer.allocateDirect(16).order(ByteOrder.nativeOrder());
FloatBuffer fb = bytes.asFloatBuffer();
fb.put(...);
fb.rewind(); //Moves the internal buffer pointer back to the start for the next thing to read from it

The ByteOrder.nativeOrder() will ensure that whether your system uses big or little endian it will be transferred correctly from java to native code. (See http://en.wikipedia.org/wiki/Endianness)

The LWJGL buffer util likely does this for you

Istinra
  • 343
  • 4
  • 8