PDA

View Full Version : Adding values to FloatBuffer



Mick Derevnin
04-07-2011, 06:51 AM
Hi guys, once more today I've stumbled across another bug in my code. A few of my friends and i have all had a look through it, and still cant figure it out.

Any help greatly appreciated, as always!

I apologies in advance since the code is in Java... since the problem is with my FloatBuffers, and c++ probably has a different implementation for adding attributes to the vertex shader.

The program:
I'm creating a flame in a simple particle system. It has the ability to do the bezier calculations on the cpu or through the shader (toggle-able). Adding particles while its rendering without using the shader works perfectly.

The problem:
When i turn on the shader, adding particles to the FloatBuffers behave unexpectedly.

Say i have my current floatbuffer, which can hold 3000 floats (before it buffer overflows), and i have exactly 3000 floats in it. While not using the shader, if i increase the number of floats to 4500, my code creates a new floatbuffer that can hold double the previous one (6k floats), copies the old 3000 floats into it, and adds the new 1500 floats ontop of it.

The result is i have a float buffer that can hold 6000 floats, and has 4500 in it currently.

When i do the same thing when the shader is turned in, instead of adding the 1500 extra floats ontop of the 3000, it seems like its wiping the buffer clean, and adding the 1500 new floats.

The result is i have a float buffer that can hold 3000 still (since it never tried to add the 3001st float, the function never creates a bigger buffer), but with only 1500 floats (the new floats i think) only.

I hope that makes some sense. The weird thing is, its the exact same createParticle() code that is being called when the cpu calculated flame or the shader calculated flame is running.

All attributes are bound and passed successfully into the vertex shader this time!

Here's hopefully all the relevant code...

The drawing code: drawParticles is called in display()


double lastRendered = System.currentTimeMillis();

protected void drawParticles(GL gl) {

gl.glColor4f(0.7f, 0.2f, 0.1f, 0.8f);
gl.glPointSize(20);

if(useShader) {

GPUrenderer(gl);
}
else {

CPUrenderer(gl);
}

if((System.currentTimeMillis() - lastRendered) >= 30) {

time += 0.03f;
lastRendered = System.currentTimeMillis();
}

if(time > 1) time = 0;
}

private void CPUrenderer(GL gl) {

gl.glUseProgram(0);

gl.glBegin(GL.GL_POINTS);

FlameParticle particle;
Vector3D particleLocation;

for(int i = 0; i < particleList.size(); i++) {

particle = (FlameParticle)particleList.get(i);

particleLocation = particle.currPosition(time);

gl.glVertex3f(particleLocation.x, particleLocation.y, particleLocation.z);
}

gl.glEnd();
}

private void GPUrenderer(GL gl) {

gl.glUseProgram(shader.getProgram());

gl.glUniform1f(gl.glGetUniformLocation(shader.getP rogram(), "time"), time);

// System.out.println(cp1.capacity());


cp0.rewind();
gl.glVertexPointer(3, GL.GL_FLOAT, 0, cp0); // bezier cp0
cp1.rewind();
gl.glVertexAttribPointer(BEZIER_CP1, 3, GL.GL_FLOAT, false, 0, cp1);
cp2.rewind();
gl.glVertexAttribPointer(BEZIER_CP2, 3, GL.GL_FLOAT, false, 0, cp2);
cp3.rewind();
gl.glVertexAttribPointer(BEZIER_CP3, 3, GL.GL_FLOAT, false, 0, cp3);
startTime.rewind();
gl.glVertexAttribPointer(START_TIME, 1, GL.GL_FLOAT, false, 0, startTime);

gl.glEnableClientState(GL.GL_VERTEX_ARRAY); // bezier cp0
// gl.glEnableVertexAttribArray(BEZIER_CP0);
gl.glEnableVertexAttribArray(BEZIER_CP1);
gl.glEnableVertexAttribArray(BEZIER_CP2);
gl.glEnableVertexAttribArray(BEZIER_CP3);
gl.glEnableVertexAttribArray(START_TIME);

gl.glDrawArrays(GL.GL_POINTS, 0, particleList.size());

gl.glDisableClientState(GL.GL_VERTEX_ARRAY); // bezier cp0
// gl.glDisableVertexAttribArray(BEZIER_CP0);
gl.glDisableVertexAttribArray(BEZIER_CP1);
gl.glDisableVertexAttribArray(BEZIER_CP2);
gl.glDisableVertexAttribArray(BEZIER_CP3);
gl.glDisableVertexAttribArray(START_TIME);
}


setting up the floatbuffers initially, called in init()


protected FloatBuffer cp0, cp1, cp2, cp3, startTime;

protected void setupBuffers() {

cp0 = BufferUtil.newFloatBuffer(3 * 1000);
cp1 = BufferUtil.newFloatBuffer(3 * 1000);
cp2 = BufferUtil.newFloatBuffer(3 * 1000);
cp3 = BufferUtil.newFloatBuffer(3 * 1000);
startTime = BufferUtil.newFloatBuffer(1000);
}


addParticles(amount to add) called when i press + on the keyboard


private void addParticles(int toAdd) {

int count = 0;

while(count < toAdd) {

createParticle();

count++;
}
}

protected void createParticle() {

FlameParticle particle = new FlameParticle();

particleList.add(particle);

FloatBuffer temp;

if(cp0.remaining() < 3) {
System.out.println("here");
// cp0.rewind();
temp = BufferUtil.newFloatBuffer(cp0.capacity());
temp.put(cp0);
temp.rewind();
cp0.rewind();
cp0 = BufferUtil.newFloatBuffer(cp0.capacity() * 2);
cp0.put(temp);
// cp0.position(temp.position());
}

if(cp1.remaining() < 3) {

// cp1.rewind();
temp = BufferUtil.newFloatBuffer(cp1.capacity());
temp.put(cp1);
temp.rewind();
cp1.rewind();
cp1 = BufferUtil.newFloatBuffer(cp1.capacity() * 2);
cp1.put(temp);
// cp1.position(temp.position());
}

if(cp2.remaining() < 3) {

// cp2.rewind();
temp = BufferUtil.newFloatBuffer(cp2.capacity());
temp.put(cp2);
temp.rewind();
cp2.rewind();
cp2 = BufferUtil.newFloatBuffer(cp2.capacity() * 2);
cp2.put(temp);
// cp2.position(temp.position());
}

if(cp3.remaining() < 3) {

// cp3.rewind();
temp = BufferUtil.newFloatBuffer(cp3.capacity());
temp.put(cp3);
temp.rewind();
cp3.rewind();
cp3 = BufferUtil.newFloatBuffer(cp3.capacity() * 2);
cp3.put(temp);
// cp3.position(temp.position());
}

if(startTime.remaining() < 1) {

// startTime.rewind();
temp = BufferUtil.newFloatBuffer(startTime.capacity());
temp.put(startTime);
temp.rewind();
startTime.rewind();
startTime = BufferUtil.newFloatBuffer(startTime.capacity() * 2);
startTime.put(temp);
// startTime.position(temp.position());
}

// System.out.println(cp0.position());

// cp0.position((particleList.size()-1)*3);
// cp1.position((particleList.size()-1)*3);
// cp2.position((particleList.size()-1)*3);
// cp3.position((particleList.size()-1)*3);
// startTime.position(particleList.size()-1);

cp0.put(particle.cp0.x);
cp0.put(particle.cp0.y);
cp0.put(particle.cp0.z);

cp1.put(particle.cp1.x);
cp1.put(particle.cp1.y);
cp1.put(particle.cp1.z);

cp2.put(particle.cp2.x);
cp2.put(particle.cp2.y);
cp2.put(particle.cp2.z);

cp3.put(particle.cp3.x);
cp3.put(particle.cp3.y);
cp3.put(particle.cp3.z);

startTime.put(particle.startTime);

System.out.println(cp0.position());
System.out.println("remaining " + cp0.remaining());
System.out.println("capacity " + cp0.capacity());

}


I hope that's everything relevant. To recap: when i toggle "useShader" to true, adding to FloatBuffers seems to "clear" the buffer before adding particles. When "useShader" is false, FloatBuffer's work as intended.

Once again, any help would be greatly appreciated!!

mobeen
04-07-2011, 07:04 AM
Shouldn't the enableVertexAttributeArray be called before the call to vertexattribPointer like this


gl.glEnableVertexAttribArray(BEZIER_CP1);
gl.glVertexAttribPointer(BEZIER_CP1, 3, GL.GL_FLOAT, false, 0, cp1);
cp2.rewind();
gl.glEnableVertexAttribArray(BEZIER_CP2);
gl.glVertexAttribPointer(BEZIER_CP2, 3, GL.GL_FLOAT, false, 0, cp2);
cp3.rewind();
gl.glEnableVertexAttribArray(BEZIER_CP3);
gl.glVertexAttribPointer(BEZIER_CP3, 3, GL.GL_FLOAT, false, 0, cp3);
startTime.rewind();
gl.glEnableVertexAttribArray(START_TIME);
gl.glVertexAttribPointer(START_TIME, 1, GL.GL_FLOAT, false, 0, startTime);

I am not sure if this will help but u can try.

Mick Derevnin
04-07-2011, 07:13 AM
Thanks Mobeen for having a look! At this point in time, anything is worth a try for me.

Unfortunately it didn't work.

On my home computer (i was doing this all day on my laptop), after i change it to the shader, and add particles to it, it actually crashed (though it still prints into standard output that it gets reset down to 1500 floats, instead of becoming 4500 floats).

It add 500 particles per everytime i press "+", and every particle adds 3 floats.

I'm assuming that's because its trying to draw more points than the floatbuffer has...

Any more input greatly appreciated!