I couldn't access the bugzilla because of internal server error. I think I found a bug.
I will copy all of this bug report to this post, but this is originally written with markdown so you can view this bug report in pretty with following URL also. https://www.notion.so/kyasbal/gl-bufferData-seems-not-working-correctly-when-floating-value-was-passed-as-ByteBuffer-0f68ce5b8ed843eaa9671b0d7acac484 # gl.bufferData seems not working correctly when floating value was passed as ByteBuffer ## Description of the bug When gl.bufferData receives ByteBuffer which was converted from FloatBuffer, the buffer seems to be filled with 0 in GPU side. But even it can be read correctly with `gl.glGetBufferSubData` I've created 2 buffers which was created in different way. 1 of that is created by `FloatBuffer.wrap` , and another one is created by `ByteBuffer.allocate` then fill that with `FloatBuffer#put` I thought even I had passed ByteBuffer into bufferData method, it should be correctly passed since that should perform just passing byte array into GPU side memory. And there is one more weird thing. If that buffer was read with `gl.glGetBufferSubData` , it seems read the buffer correctly even that was not passed into GPU actually. ## Screen shot The 2 blue dot on the right side is the buffer which was created with `FloatBuffer.wrap` The 1 red dot on the center is the buffer which was created with `ByteBuffer.allocate` . These points are placed in clip space coordinate. Therefore, red dot seems placed in origin of the clip space.(This is the reason I think the red buffer is filled with zero in GPU side memory) SCREEN SHOT IS ATTACHED EXTERNAL LINK THAT WAS PLACED HEAD OF THIS POST. (Because this forum seems not accepting posting images) ## Source code The main source code. package img.kakeru import com.jogamp.opengl.GL3 import com.jogamp.opengl.GLAutoDrawable import img.kakeru.graphics.DynamicSimpleShaderProgram import img.kakeru.graphics.glex.createBuffer import java.nio.ByteBuffer import java.nio.FloatBuffer import kotlin.coroutines.experimental.buildIterator class JOGLBug : GLRunnable() { override fun getSchedule(p0: GLAutoDrawable): Iterator<Int> { val gl = p0.gl.gL3 val window = this; // BEGINING OF INITIALIZE // Disable several flags gl.glDisable(GL3.GL_BLEND) gl.glDisable(GL3.GL_CULL_FACE) gl.glDisable(GL3.GL_SCISSOR_TEST) gl.glDisable(GL3.GL_DEPTH_TEST) gl.glDisable(GL3.GL_STENCIL_TEST) gl.glEnable(GL3.GL_VERTEX_PROGRAM_POINT_SIZE) // create buffers // BUFFER1: Correctly shown buffer (Created with FloatBuffer.wrap) val bufferSource1 = FloatBuffer.wrap(floatArrayOf(-0.5f,0.5f,0.5f,-0.5f,-0.5f,0.5f)) val buffer1 = gl.createBuffer() gl.glBindBuffer(GL3.GL_ARRAY_BUFFER,buffer1) gl.glBufferData(GL3.GL_ARRAY_BUFFER,bufferSource1.limit() * 4L, bufferSource1,GL3.GL_STATIC_DRAW) // BUFFER2: Incorrectly shown buffer (Created with Bytebuffer.allocate then it will be filled with put method of floatbuffer) val bufferSource2 = ByteBuffer.allocate(4 * 6); bufferSource2.asFloatBuffer().put(floatArrayOf(0.5f,0.5f,0.5f,0.5f,-0.5f,0.5f)) val buffer2 = gl.createBuffer() gl.glBindBuffer(GL3.GL_ARRAY_BUFFER,buffer2) gl.glBufferData(GL3.GL_ARRAY_BUFFER,bufferSource2.limit().toLong(),bufferSource2,GL3.GL_STATIC_DRAW) // create materials val materialRed = DynamicSimpleShaderProgram("./kakeru/position-only-es2.vp","./kakeru/single-color-es2.fp") val materialBlue = DynamicSimpleShaderProgram("./kakeru/position-only-es2.vp","./kakeru/single-color-es2-blue.fp") materialRed.setup(gl) materialBlue.setup(gl) // END OF INITIALIZE return buildIterator { while(true){ // BEGINNING OF A FRAME // RENDERING LOOP gl.glViewport(0,0,window.width,window.height) gl.glClearColor(1f,1f,1f,1f) gl.glClear(GL3.GL_COLOR_BUFFER_BIT or GL3.GL_DEPTH_BUFFER_BIT) // draw buffer1 materialBlue.use(mapOf()) gl.glBindBuffer(GL3.GL_ARRAY_BUFFER,buffer1) val posLoc1 = gl.glGetAttribLocation(materialBlue.program.id,"pos") gl.glEnableVertexAttribArray(posLoc1) gl.glVertexAttribPointer(posLoc1,3,GL3.GL_FLOAT,false,0,0L) gl.glDrawArrays(GL3.GL_POINTS,0,2) // draw buffer2 materialRed.use(mapOf()) gl.glBindBuffer(GL3.GL_ARRAY_BUFFER,buffer2) val posLoc2 = gl.glGetAttribLocation(materialBlue.program.id,"pos") gl.glEnableVertexAttribArray(posLoc2) gl.glVertexAttribPointer(posLoc2,3,GL3.GL_FLOAT,false,0,0L) gl.glDrawArrays(GL3.GL_POINTS,0,2) // Try to get Buffer2 contained elements val subBuffer = ByteBuffer.allocateDirect(6 * 4).asFloatBuffer() gl.glGetBufferSubData(GL3.GL_ARRAY_BUFFER,0,6 * 4,subBuffer) // Stringify bufferData var bufferStr = "[" for(i in 0 until 6){ bufferStr += (subBuffer[i]); bufferStr += " ,"; } bufferStr += "];" println(bufferStr) // Finalize the frame gl.glFinish() // END OF A FRAME yield(0) } } } } fun main(args:Array<String>){ val testInstance = TestExecutor(JOGLBug()) testInstance.start() } The following description is supplemental information for reading the code above. But, the basically there is no way to need omitted source codes. - `DynamicSimpleShaderProgram` is just a class to provide feature for compiling shader, using program and so on. Even I haven't attach source code of this class, this class is just perform that should do. There are no related code about buffers. - `GLRunnable` which is inherited by the main class of this source code. GLRunnable will call the `getSchedule` method on initialization timing when the window was created. Then it will call next() method of returned iterator for each frame. - `TestExecutor` is a class to run GLRunnable. This basically perform window creation task , and that is all this class do. - `gl.createBuffer` is extensional method to generate a single buffer. This method just perform `gl.glGenBuffers(1,array,0)` then it return the first element of the array position-only-es2.vp attribute vec3 pos; void main(){ gl_PointSize = 1000000000.; gl_Position = vec4(pos,1.0); } single-color-es2.fp precision mediump float; void main(){ gl_FragColor = vec4(1,0,0,1); } single-color-es2-blue.fp precision mediump float; void main(){ gl_FragColor = vec4(0,0,1,1); } Output of this program [0.5 ,0.5 ,0.5 ,0.5 ,-0.5 ,0.5 ,]; [0.5 ,0.5 ,0.5 ,0.5 ,-0.5 ,0.5 ,]; [0.5 ,0.5 ,0.5 ,0.5 ,-0.5 ,0.5 ,]; [0.5 ,0.5 ,0.5 ,0.5 ,-0.5 ,0.5 ,]; .... |
I conclude this was not bug of JOGL. I apologize I have doubted this library.
## Solution and why this problem was happen I found a solution for this problem. I conclude this problem was happen by difference of byte order between java and native environment. The floating buffer created as a byte buffer must be ordered with native order with following buffer creation code. val bufferSource2 = ByteBuffer.allocate(4 * 6) bufferSource2.order(ByteOrder.nativeOrder()) val floatingSource2 = bufferSource2.asFloatBuffer() floatingSource2.put(FloatBuffer.wrap(floatArrayOf(0.5f,0.5f,0.5f,0.5f,-0.5f,0.5f))) val buffer2 = gl.createBuffer() gl.glBindBuffer(GL3.GL_ARRAY_BUFFER,buffer2) gl.glBufferData(GL3.GL_ARRAY_BUFFER,bufferSource2.limit().toLong(),bufferSource2,GL3.GL_STATIC_DRAW) I think JOGL will consider the order of passed buffer if it was passed as typed buffers. If the floating values are represented as LITTLE_ENDIAN and it should be swapped for native environment, this seems to be converted as BIG_ENDIAN automatically during calling bufferData method. But, if I passed as a byte buffer, it is obviously the library will not be able to know which is floating value and should be swapped. This was a reason this problem was happen. **Therefore, this was not a problem of JOGL actually.** |
Administrator
|
Hello
Why not using Buffers.newDirectFloatBuffer(float[]) instead? It just does the right job.
Julien Gouesse | Personal blog | Website
|
Free forum by Nabble | Edit this page |