Adding and removing Vertices from VBO

Started by david37370, February 05, 2015, 21:15:43

Previous topic - Next topic

david37370

Hello, yesterday i've run into a problem and wasted a few hours without success. Im making a minimal engine that would handle VAO and VBO's for me, cause i dont like them.  ;)
Everything works till the point when i tried to add new vertices. i have texture, color and location for each vertex, and i can move the vertices with no problem using glBufferSubData.
from what i understood, its impossible to change VBO size so i have to specify a fixed size and then add vertices with glBufferSubData. for that to work i also need to add vertex index data in the VBOi (index data VBO). I dont know why my code doesn't work - instead of adding a new triangle, no new vertices are visible on screen and instead a triangle is drawn from some random vertices. unexpected.

Declaring VBOs code- vertices:
glBufferData(GL_ARRAY_BUFFER, 1000l, GL_STATIC_DRAW); // create buffer for indexes of size 1000 bytes
glBufferSubData(GL_ARRAY_BUFFER, 0, verticesFloatBuffer);

glVertexAttribPointer(0, Vertex.positionElementCount, GL_FLOAT, false, Vertex.STRIDE, Vertex.positionByteOffset);
glVertexAttribPointer(1, Vertex.colorElementCount,    GL_FLOAT, false, Vertex.STRIDE, Vertex.colorByteOffset);
glVertexAttribPointer(2, Vertex.textureElementCount,  GL_FLOAT, false, Vertex.STRIDE, Vertex.textureByteOffset);

indices:
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 1000l, GL_STATIC_DRAW);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, indicesBuffer);


i know for a fact that this code works. now the vertex adding part - i'll have to elaborate about my program. I have an arraylist of Drawables, abstract drawable has private variables stride and shapeBuffer, and functions like getElements[], render(int offset), setupIndices(ArrayList<Byte> indices, byte offset).
classes like Vertex, Line, Triangle extend Drawable. Line contains 2 Vertices, Triangle 3 obviously.

The function which is supposed to add a new triangle, t:

public void create(){
		
                //Creating triangle t. this works
                Triangle t = createTriangleAroundMouse();
                
		//finding at which offset to add the vertices
		int VBOoffset=0;
		for (Drawable shape:shapes){VBOoffset+=shape.shapeBuffer.capacity();}

                //create buffer that contains the triangle
		FloatBuffer verticesFloatBuffer = BufferUtils.createFloatBuffer(t.getStride());  //verticesByteBuffer.asFloatBuffer();
		verticesFloatBuffer.put(t.getElements());
		verticesFloatBuffer.flip();
		
		//triangle adds its indices to the arraylist. guaranteed to work, tested
		ArrayList<Byte> indices = new ArrayList<Byte>();
		indexOffset = t.setupIndices(indices, indexOffset);
		
		//add indices to buffer - also guaranteed to work
		int indicesCount = indices.size();
		ByteBuffer indicesBuffer = BufferUtils.createByteBuffer(indicesCount);
		byte[] indicesArray = new byte[indices.size()];
		for (int i=0; i < indicesArray.length; i++){
			indicesArray[i]=indices.get(i);
		}
		indicesBuffer.put(indicesArray).flip();
		
		//problematic part. is it correct?
		glBindVertexArray(vaoID);
		glBindBuffer(GL_ARRAY_BUFFER, vboID);
		glBufferSubData(GL_ARRAY_BUFFER, VBOoffset, verticesFloatBuffer);
		glBindBuffer(GL_ARRAY_BUFFER, 0);
		glBindVertexArray(0);
		
		//am i handling the indices correctly?
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboiID);
		glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, indexOffset, indicesBuffer);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
		
		stride+=t.getStride();
		shapes.add(t);
	}

       
        the shapeBuffer variable in class Drawable is necessary(i think) in the update section, where i use glBuffereSubData:
int VBOoffset=0;
for (Drawable shape:shapes){
	shape.shapeBuffer.rewind();
	shape.shapeBuffer.put(shape.getElements());
	shape.shapeBuffer.flip();
	
	glBufferSubData(GL_ARRAY_BUFFER, VBOoffset, shape.shapeBuffer);
	VBOoffset+=shape.shapeBuffer.capacity();
}


this code works.
i would greatly appreciate help here! I didnt even try removing vertices yet.
thanks :)

abcdef

You don't need a subbuffer, you just need to tell opengl that your data isn't static. I have no issues running the below when creating dynamic sized data sets.

        glBindBuffer(GL_ARRAY_BUFFER, vertexBufferId);
        glBufferData(GL_ARRAY_BUFFER, vertexData, GL_STREAM_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER, 0);


you can do the same with indexes

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferId);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexes, GL_STREAM_DRAW);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

david37370

Your code just creates the buffers. how do you add data after you've created them? just modifying vertexData and indexes float buffers didn't work.

abcdef

you modify the vertexData and indexes and then rebind then to the vertexBufferId and indexbufferId via the same way you used them in the first place.

david37370

But doesn't that kill the concept of VBO? if i send all the data every time i make a change, there's no point in storing the data in the GPU. what i want to do is store the data in the GPU and only the data that i modify will be sent. for example, i have 10 dynamic lines, each consists of 2 vertices. if i only move the 6th line, i should use glBufferSubData, right? and that didn't work for me. maybe i'm wrong. another thing that relates closely to this: should i make 2 VBO's, one for movable content, one for dynamic? or stick with 1?

quew8

All this really depends on the situation. If you won't be updating the data very much then it really doesn't matter if you replace all the data or only the bits that have changed. And it's a fair bit simpler to update the whole VBO. However if a VBO contains a large proportion of static data or if you are changing it many times and you need the performance then better to only update dynamic sections.

Likewise with the two VBOs. Interleaving VBOs will be generally faster but you get the additional complexity. Depends on how fast you need it to be and what the data is.

My advice: do what feels like the simplest thing and if it is not quick enough then move up to something more complex but faster.