Need help about how to set up VBO-Rendering

Started by Cornix, May 25, 2013, 16:04:28

Previous topic - Next topic

Cornix

Hi, i am currently trying to learn how to use VBO's to render my 2D-Graphics.

This is how far i currently am:
I use 2 VBO's per sprite, the first VBO has the following interleaved data:
4 vertices (x, y, z)
4 texture coordinates (s, t)

the second VBO stores the indices for the order in which the vertices will be drawn, if i want to draw a quad i need 6 indices (3 for the first triangle and 3 for the second).

This is how i generate my VBO's:
public VBOPicure(float[] values) {
		data_vbo_id = GL15.glGenBuffers();
		element_count = values.length;
		
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, data_vbo_id);
		
		FloatBuffer buf = ByteBuffer.allocateDirect(Float.SIZE * element_count).order(ByteOrder.nativeOrder()).asFloatBuffer();
		buf.put(values);
		buf.flip();
		
		GL15.glBufferData(GL15.GL_ARRAY_BUFFER, buf, GL15.GL_DYNAMIC_DRAW);
		
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
		
		index_vbo_id = GL15.glGenBuffers();
		index_count = 6;
		byte[] indices = new byte[] {0, 1, 2, 2, 3, 0};
		
		GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, index_vbo_id);
		
		ByteBuffer buf2 = ByteBuffer.allocateDirect(Byte.SIZE * index_count).order(ByteOrder.nativeOrder());
		buf2.put(indices);
		buf2.flip();
		
		GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, buf2, GL15.GL_DYNAMIC_DRAW);
		
		GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
	}


I hope this is correct so far.


Now, when i want to draw it, i have to do this, right?
public void draw() {
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, data_vbo_id);
		GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, index_vbo_id);
		
		GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
		GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
		GL11.glEnableClientState(GL11.GL_INDEX_ARRAY);
		
		GL11.glVertexPointer(3, GL11.GL_FLOAT, 0, 0);
		// There are 4 vertices, each with 3 elements of type float.
		GL11.glTexCoordPointer(2, GL11.GL_FLOAT, 0, 4 * 3 * Float.SIZE);
		GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, element_count);
		
		GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
		GL11.glDisableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
		GL11.glDisableClientState(GL11.GL_INDEX_ARRAY);
	}


Or am i getting something wrong here?

Thanks for your help!

broumbroum


Cornix

Well, yes, thanks for your response.
I read that already but I am not quite satisfied.
First of all, the example code is unfortunately flawed. I dont exactly know at which point the error is, but the application uses the RGB-values of the vertex for the position while the XYZ-values dont do anything.
It already was quite a pain to get a grasp on that when you try to make it run but it doesnt work right.

In addition to that i have a question which was not answered by these tutorials:
First of all, do i really need a VAO? What I understood so far is, that the VAO stores the VBO's which are used. But you can also use
GL11.glVertexPointer(...);
GL11.glTexCoordPointer(...);

instead.


quew8

I wrote a lot of that page myself and I promise you that that is not the case. More likely you have made a mistake in reading or you're creating the data buffers wrongly.

As for VAOs, they are not required, many people don't use them and several people at least on this forum find them to be slower than pure vbos. The other thing is that they require OpenGL 3.0+ and lots of people still don't have that kind of hardware.

You posted some code, but seemed to be asking us to check through it without even seeing if it works or not. If it doesn't work you certainly didn't say what the problem was. Glancing at the code I don't see anything wrong with it but I would like to clarify that you are ordering your buffer data as:

x1, y1, z1, x2, y2, z2, ... s1, t1, s2, t2, s3, t3 ...

and not

x1, y1, z1, s1, t1, x2, y2, z2, s2, t2 etc...

The first is what your code describes. The second is what the wiki page recommends.

Cornix

I am absolutely sure I copied the code from the wiki page exactly without changing anything. It compiled, it started, and it showed a wrong picture. After meddling around for an hour i realized, that the RGB-values are actually used for the position and not the XYZ-values. I was baffled myself but it seems to me like a simple mistake was made somewhere.
The code i used was from: http://www.lwjgl.org/wiki/index.php?title=The_Quad_updating_a_VBO_with_BufferSubData

But i am glad to have my question answered, and i see your point. I will try to structure it in a different way.
However, i tested my code and it didnt work, i am sorry i didnt say so. It just didnt show anything at all on the screen.

I will try again, maybe i made a mistake somewhere.

On a sidenote, would it be possible to have a tutorial for the use of VBO's without the VAO's?

quew8

Ah, I didn't write that one. I was referring to the page @broumbroum linked which incidentally does not use vaos. I have had a look through that tutorial's code for every possible thing I could think of to cause the colour data to be used for position and I found nothing. (As if I ever find the bugs the first time). So you could be wrong, the tutorial could be wrong, you could both be wrong. All I know is that I have to be.

Without vaos btw, you essentially do all the vao setup (minus creating and binding the vao) every frame before you draw. Take a look at the tutorial but you should be able to skip most of it.

broumbroum

Quote from: Cornix

public void draw() {
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, data_vbo_id);
		GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, index_vbo_id); //<<
		
		GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);                      ^^
		GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);           ^^
		GL11.glEnableClientState(GL11.GL_INDEX_ARRAY);                          ^^
		
		GL11.glVertexPointer(3, GL11.GL_FLOAT, 0, 0);                              ^^
		// There are 4 vertices, each with 3 elements of type float.             ^^
		GL11.glTexCoordPointer(2, GL11.GL_FLOAT, 0, 4 * 3 * Float.SIZE);   ^^
		GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, element_count); // DRAWELEMENTS
		
		GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
		GL11.glDisableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
		GL11.glDisableClientState(GL11.GL_INDEX_ARRAY);
	}
If you copied the wiki tutorial, it's a bad one.  :D
glDrawArrrays is missing indices element_array, because it's the job of glDrawElements.
Quote
On a sidenote, would it be possible to have a tutorial for the use of VBO's without the VAO's?
It is indeed the code you posted above, after having made corrections to it. Vertices and color pointers use Arrays (without Object, unlike VAO and vertexAttrib.... is ), that you may store in Vertex Buffers -Objects-.