How to add vertices to VBO?

How to add vertices to VBO? Currently i am trying to do something like this:

FLOATBUFFER:

public static FloatBuffer vertices = BufferUtils.createFloatBuffer(2*4*4);

ADDING TWO QUADS:

 vertices.put(new float[]
        {
            0,   0,
            0+200, 0,
            0+200, 0+200,
            0, 0+200,
           300,   300,
            300+200, 300,
           300+200, 300+200,
            300,  300+200
        });
        vertices.rewind();


 vboVertexID = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, vboVertexID);
        glBufferData(GL_ARRAY_BUFFER, vertices, GL_STATIC_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER, 0);

DRAWING:


            glEnableClientState(GL_VERTEX_ARRAY);
	         glEnableClientState(GL_TEXTURE_COORD_ARRAY);

		            glBindBuffer(GL_ARRAY_BUFFER, vboVertexID);
	                glVertexPointer(2, GL_FLOAT, 0, 0);
	                glDrawArrays(GL_QUADS, 0, 16);

            glDisableClientState(GL_VERTEX_ARRAY);
		      glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	     
	        

    1. What are you trying to draw?
    1. Why are you filling the buffer with 16 vertices but giving it a size of 32?
    1. Put an f after all your numbers.
  1. i am just trying to draw anything, i am learning VBO.
  2. i want to add more vertices, so i think i need free space.
  3. thanks for tip :slight_smile:

I found a way how i can add vertices, but i think its not right way:

public static float[] floats = new float[32]; 

public void verticesTick(){
vertices.put(floats);
		vertices.rewind();
		glBindBuffer(GL_ARRAY_BUFFER, vboVertexID);
        glBufferData(GL_ARRAY_BUFFER, vertices, GL_STATIC_DRAW);
}

With this i can modify my floats array and change my VBO, but i am doing this every tick, i think its problem.

You use VBOs to try and keep vertex data on the GPU (graphics processing unit) for as long as possible so that you don’t have to keep updating the data constantly. You’ll want to start off by creating an initialize method which creates the VBO. If you wanted to draw a triangle you’d have something like this:

To create and fill the buffer object with data-


public void initialize() {
	// when rendering, if this is enabled then glDrawArrays will look at the information stored by glVertexPointer or glVertexAttribPointer (which is introduced in newer OpenGL versions)
	glEnableClientState(GL_VERTEX_ARRAY);

	float[] data = {
			-0.5f, -0.5f, 0f // bottom left
			-0.5f, +0.5f, 0f // top left
			+0.5f, -0.5f, 0f // bottom right
	};

	vboVertexID = glGenBuffers(); // generates the handle (id) used to bind the buffer
	glBindBuffer(GL_ARRAY_BUFFER, vboVertexID); // binds the handle to the target GL_ARRAY_BUFFER
	// fills the most recently bound buffer (vboVertexID) with data. the usage (GL_STATIC_DRAW) indicates that the buffer data will be used for drawing and won't be changed directly
	glBufferData(GL_ARRAY_BUFFER, (FloatBuffer) BufferUtils.createFloatBuffer(data.length).put(data).flip() /* the buffer is flipped so that it draws from position 0 */, GL_STATIC_DRAW);
	glBindBuffer(GL_ARRAY_BUFFER, 0); // unbinds the most recently bound buffer (vboVertexID) from the target GL_ARRAY_BUFFER
}

The game loop- a simple game loop would look something like this:


public void loop() {
	initialize();

	while(!Display.isCloseRequested()) {
		Display.sync(60); //fps
		updateGameLogic();

		if(Display.isVisible || Display.isDirty) {
			render();
			Display.update();
		}
	}

	dispose(); // when closed, delete vbos with glDeleteBuffer(handle)
}

Rendering-


public void render() {
	glClearColor(0f, 0f, 0f, 1f); // colour to clear the screen; r, g, b, a
	glClear(GL_COLOR_BUFFER_BIT); // clears the colour buffer (the screen)

	glBindBuffer(GL_ARRAY_BUFFER, vboVertexID);
	
	 /*
	 * glVertexPointer(size, type, stride, offset) DEPRECATED in newer OpenGL versions
	 * 
	 * The arguments given to this function represent how the data in a
	 * buffer is stored. The given arguments are saved in memory. The size
	 * is the number of attributes per vertex (3D space means there are 3
	 * attributes). The type is the data type of each attribute. The stride is
	 * the number of bytes per vertex - float has 4 bytes so it should be
	 * 3(size)*4, however a value of 0 tells OpenGL that the data is tightly
	 * packed. The offset is the number of bytes between the start of the
	 * buffer and the first attribute.
	 */
	glVertexPointer(3, GL_FLOAT, 3 << 2, 0); // 3 is represented in bytes as 0011. shifting the bits 2 to the left changes it to 1100 which represents 12. 3 << 2 effectively means 3*4.

	/*
	 * glDrawArrays(mode, first, count)
	 * 
	 * Renders the shape. If the various states are enabled it will get the
	 * associated data from memory, e.g if GL_VERTEX_ARRAY is enabled it
	 * will get the data from memory assigned by glVertexPointer(...). The
	 * mode specifies what kind of geometric primitives (shapes) to render.
	 * The first is the starting position of the vertices to render in the bound
	 * buffer. The count specifies the number of vertices to render.
	 */
	glDrawArrays(GL_TRIANGLES, 0, 3);
	glBindBuffer(GL_ARRAY_BUFFER, 0);
}

If you don’t understand something just ask and I’ll explain it.

its great explanation, but you said this line:

 glVertexPointer(3, GL_FLOAT, 3 << 2, 0);

is deprecated, so how new version should like?

And if you can, i would like to see how i can draw quad in 2 dimensions. i tried to do that, but i am getting really strange results.

Don’t worry about using deprecated functions yet, but for reference, in V2.0 you would use shaders and instead use glVertexAttribPointer. To draw a quad, create a buffer and fill it with 12 attributes (3 per vertex). The for a square the vertices would be:


float[] data = {
    -0.5f, -0.5f, 0f // bottom left
    -0.5f, +0.5f, 0f // top left
    +0.5f, +0.5f, 0f // top right
    +0.5f, -0.5f, 0f // bottom right
};
glVertexPointer(3, GL_FLOAT, 3 << 2, 0)

These parameters would be the same since each vertex still has 3 attributes and the data is still formatted in the same way in the buffer.

However you have two options for glDrawArrays(). You could draw it with the mode GL_TRIANGLE_STRIP which is preferred for 3D models. You’d need to put a count of 4 since you have 4 vertices like so:

glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

Or you could draw it with the mode GL_QUADS which is preferred for a single quad, again using a count of 4.

glDrawArrays(GL_QUADS, 0, 4);

This image displays all the possible modes

However, do note that quads are not the best type to use. Triangles are better because the GPU breaks geometry down into triangles, so why give it extra work to do when using quads? Its a very small change, but worth it.

Thanks for answers! But now i am trying to put 2 quads in VBO and draw only second quad, but i am getting strange results:

VBO DATA:

	public static float[] data = new float[24];

public void initialize() {
		   glEnableClientState(GL_VERTEX_ARRAY);

		   
		   data[0] = 100;
		   data[1] = 100;
		   data[2] = 0;
		   data[3] = 400;
		   data[4] = 100;
		   data[5] = 0;
		   data[6] = 100;
		   data[7] = 400;
		   data[8] = 0;
		   data[9] = 400;
		   data[10] = 400;
		   data[11] = 0;
		   
		   data[12] = 100+ 300;
		   data[13] = 100+ 300;
		   data[14] = 0;
		   data[15] = 200+ 300;
		   data[16] = 100+ 300;
		   data[17] = 0;
		   data[18] = 100+ 300;
		   data[19] = 200+ 300;
		   data[20] = 0;
		   data[21] = 200+ 300;
		   data[22] = 200+ 300;
		   data[23] = 0;
		
		   //data[24] = 200 + 300;
		  // data[25] = 200 + 300;
		  // data[26] = 0;
		   vboVertexID = glGenBuffers(); 
		   glBindBuffer(GL_ARRAY_BUFFER, vboVertexID);
		   glBufferData(GL_ARRAY_BUFFER, (FloatBuffer) BufferUtils.createFloatBuffer(data.length).put(data).flip() , GL_STATIC_DRAW);
		   glBindBuffer(GL_ARRAY_BUFFER, 0); 
		}

I think this code is more or less good enough to render second quad.

RENDERING METHOD:

public void render() {
		   glClearColor(1f, 1f, 1f, 1f);
		   glClear(GL_COLOR_BUFFER_BIT); 

		   glBindBuffer(GL_ARRAY_BUFFER, vboVertexID);
		   
	
		   glVertexPointer(3, GL_FLOAT, 3 << 2, 0); 

		   GL11.glColor3f(0,0, 0);
		
		   
		   glDrawArrays(GL_TRIANGLE_STRIP,0,8);
		   
		   glBindBuffer(GL_ARRAY_BUFFER, 0);
		}

[spoiler]
http://i.tinyuploads.com/q6VDXX.png
[/spoiler]
And everything is ok, but when i change my rendering method to this:

public void render() {
		   glClearColor(1f, 1f, 1f, 1f);
		   glClear(GL_COLOR_BUFFER_BIT); 

		   glBindBuffer(GL_ARRAY_BUFFER, vboVertexID);
		   
	
		   glVertexPointer(3, GL_FLOAT, 3 << 2, 0); 

		   GL11.glColor3f(0,0, 0);
		
		   
		   glDrawArrays(GL_TRIANGLE_STRIP,4,8);
		   
		   glBindBuffer(GL_ARRAY_BUFFER, 0);
		}

I get this:
[spoiler]
http://i.tinyuploads.com/G6KjAb.png
[/spoiler]

How i can fix this problem?

EDIT:
i found one solution, i can change

glDrawArrays(GL_TRIANGLE_STRIP,4,8);

to this:

glDrawArrays(GL_TRIANGLE_STRIP,4,4);

And its works good, it is best solution?

Off topic sorry: I have seen no difference in performance when using quads vs 2 triangles. I think this is because the driver will turn a quad into triangles itself as I can only draw them. Not saying you should only do quads for sprites/what ever but I do not think there is a substantial performance gain. If you are using indices for static data, that is a different story.

For any 2d game quads are more than enough. Not sure about 3d games where there are massive polygon/triangle counts.

I converted one of my games from triangles to quads and didn’t get ANY performance gain whatsoever. Just stick with quads for 2d games. Less stuff to handle by yourself.

I agree, quads enough for 2d, but if i want to make particles system with VBO, i think triangles is much more better, so where is problem in here?

I dont care it anymore, i just changed it to quads.

New question:
How to add textures?

Oh, I know. I barely ever use triangles either, but I just wanted to let OP know so that he was informed about the “standards”.

As for texturing, you’ll need to create another FloatBuffer to store the texture coordinates. It’s actually almost the same process as what you just went through. But please, please just use Google and try it yourself. You’ll learn a lot.

Google is useless in my opinion, i cant find anything usefull.

I am trying to create platformer with tiles, and i want to store my tiles in chunks. And now i am thinking, it is possible to have chunk with 16*16 tiles and each tile with different texture?

Yes it’s possible. There are several options but perhaps the best approach is use one texture per chunk with the tile images packed into that: The tiles would be arranged as a 4x4 grid and your chunk would be a 4x4 grid of indices into that texture.

This means you have a single mesh and only one texture state change per chunk.

Depending on your game and how big the chunks/tiles are this could be extended to have a larger texture grid covering multiple chunks, e.g. you could store all the tiles in a single texture and just have one mesh for the entire scene.

  • stride

Have you ever played a platformer? Then yes, it’s possible.

Have you ever used textures in OpenGL before? It’s very easy to convert everything over to a buffer object. You’ll need to have a spritesheet though.

[quote]Have you ever played a platformer? Then yes, it’s possible.

Have you ever used textures in OpenGL before? It’s very easy to convert everything over to a buffer object. You’ll need to have a spritesheet though.
[/quote]
I mean i want to change textures using VBO

A “VBO” is just a buffer object. It doesn’t do much more than fill itself with data. You cannot “change textures using VBO”. If you mean you want a texture per buffer object, than you won’t have to mess with spritesheets. I think you need to clarify more so we can understand what you want.

I want to use something like this:

 glTexCoordPointer(2, GL_FLOAT, 0, 0);

To add textures, and i have chunks with 16*16 tiles.
I want each tile with different texture

Then you’ll need a spritesheet. Generate your texture coordinates within the range of 0 - 1 (obviously) and then put them in a FloatBuffer. Each tile type will have it’s own “unique” set of coordinates. Then find out how to render textures using buffer objects (VBOs).