Posted by
kyasbal on
Oct 02, 2018; 8:41am
URL: https://forum.jogamp.org/gl-bufferData-seems-not-working-correctly-when-floating-value-was-passed-as-ByteBuffer-tp4039246.html
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 ,];
....