Questions on VBO and adding geometry

So I have some basic code that renders out a few cubes using a VBO. Now, I want to go a little more advanced and I want to remove and add cubes. I currently render my VBO like this:

private void newChunk(){
		glBindBuffer(GL_ARRAY_BUFFER, vbo.vboVHandle);
		glVertexPointer(3, GL_FLOAT, 0, 0L);
		
		glBindBuffer(GL_ARRAY_BUFFER, vbo.vboCHandle);
		glColorPointer(3, GL_FLOAT, 0, 0);
		
		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_COLOR_ARRAY);
		for(int x = 0; x < var1; x++){
			for(int z = 0; z < var2; z++){
				for(int y = 0; y < var3; y++){
					glPushMatrix();
					glTranslatef(x, y, z);
					glDrawArrays(GL_QUADS, 0, 24);
					glPopMatrix();
				}
			}
		}
		glDisableClientState(GL_VERTEX_ARRAY);
		glDisableClientState(GL_COLOR_ARRAY);
	}

And heres my VBO initialization class:

public class VBO {
	
	public int vboVHandle;

	public int vboCHandle;
	
	public float size = 0.5f;
	public float color = 0.5f;
	
    public FloatBuffer vertices;
    
    public VBO(){
    
    FloatBuffer colorData = BufferUtils.createFloatBuffer(3 * 4 * 6);
	colorData.put(new float[]{
			-color, color, color,
    		color, color, color,
    		-color, color, color,
    		color, color, color,
    		
    		-color, color, color,
    		color, color, color,
    		-color, color, color,
    		color, color, color,
    		
    		-color, color, color,
    		color, color, color,
    		-color, color, color,
    		color, color, color,
    		
    		-color, color, color,
    		color, color, color,
    		-color, color, color,
    		color, color, color,
    		
    		-color, color, color,
    		color, color, color,
    		-color, color, color,
    		color, color, color,
    		
    		-color, color, color,
    		color, color, color,
    		-color, color, color,
    		-color, color, color
	});
	colorData.flip();
	
	vertices = BufferUtils.createFloatBuffer(3 * 4 * 6);
    vertices.put(new float[] {
    		-size, -size, size,
    		size, -size, size,
    		size, size, size,
    		-size, size, size,
    		
    		-size, -size, -size,
    		-size, size, -size,
    		size, size, -size,
    		size, -size, -size,
    		
    		-size, size, -size,
    		-size, size, size,
    		size, size, size,
    		size, size, -size,
    		
    		-size, -size, -size,
    		size, -size, -size,
    		size, -size, size,
    		-size, -size, size,
    		
    		size, -size, -size,
    		size, size, -size,
    		size, size, size,
    		size, -size, size,
    		
    		-size, -size, -size,
    		-size, -size, size,
    		-size, size, size,
    		-size, size, -size});
    vertices.flip();
    
    vboVHandle = glGenBuffers();
    glBindBuffer(GL_ARRAY_BUFFER, vboVHandle);
    glBufferData(GL_ARRAY_BUFFER, vertices, GL_DYNAMIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);


    vboCHandle = glGenBuffers();
    glBindBuffer(GL_ARRAY_BUFFER, vboCHandle);
    glBufferData(GL_ARRAY_BUFFER, colorData, GL_DYNAMIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    
    }

}

Pretty basic. How would I go about actually removing or adding cubes? I know I have to use glMapBuffer and glUnMapBuffer, but how do I actually make an array of cubes and upload them to the VBO to be rendered? Also, I am currently rendering the cubes like this:

glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_COLOR_ARRAY);
		for(int x = 0; x < var1; x++){
			for(int z = 0; z < var2; z++){
				for(int y = 0; y < var3; y++){
					glPushMatrix();
					glTranslatef(x, y, z);
					glDrawArrays(GL_QUADS, 0, 24);
					glPopMatrix();
				}
			}
		}
		glDisableClientState(GL_VERTEX_ARRAY);
		glDisableClientState(GL_COLOR_ARRAY);

Which obviously renders one cube, just with different coords. How would I render multiple cubes instead of just one?
Thanks for any help!

What’s wrong with what you’re currently doing?

I dont think anything is currently wrong, if you’re talking about how I’m rendering the cubes. I’ve just heard people saying that you should render a new cube everytime instead of the same one at different coordinates.

That depends on what you’re doing. For static geometry then yes, go ahead and generate your cubes and store them in an array. For dynamic geometry, I wouldn’t recommend it, at least not for cubes or anything more advanced than that. What are you expecting to gain?

EDIT: Also, negative color values?

My geometry will be dynamic. And I dont know what I expect to gain, I was just wondering if my way of doing it was wrong as I’m very new to VBOs. So how would you recommend me storing my cubes if you don’t think an array would be good?

I’d recommend that you merge the data into one VBO by interleaving the vertex attributes. Other than that, I don’t see what’s wrong with rendering them one by one like you’re currently doing. Although you say your geometry will be dynamic, exactly what will you be rendering using cubes?

My terrain? Its a cube world, and I assume by static you mean never changing. If I’m wrong, please correct me!

See this thread: http://www.java-gaming.org/index.php?topic=27868.0 It has some good points.

I would call a cube world static, since it only changes very rarely. 99.9% of all frames won’t have anything changed, so there’s no need to regenerate the data. Split up the world into subsections so you don’t have to regenerate the world every time something changes. You’ll also have to manually cull faces that aren’t visible and do frustum culling, but it’s all in the thread I linked.

Wow thank you, that will definetely help me out!

Don’t convert to display lists though. If you read the whole thread you’ll see that display lists are deprecated now and all, so stick with VBOs. They’re what you’re supposed to use.

I read through that whole post, and I’m still a little confused on how to store all my vertex data in one VBO. Basically, what I want is to have a VBO with 16x16x16 cubes. Then I’ll generate new chunks and translate the chunks to the correct position. When that’s done, I want to draw the VBO in that chunk position, so I can avoid calling glTranslate a lot. I’m stuck on how I should store 4096 blocks in one VBO though. Should I make an array and then throw the array into the VBO?

The definitive theoretical maximum of vertices is 161616 cubes * 6 faces * 4 vertices = 98 304 vertices per chunk. Each vertex needs a 3D float position and an RGBA color, so you get a total of 12 + 4 = 16 bytes per vertex. In total, you need a ByteBuffer with a length of 1 572 864. (1.5MBs of data, it’s actually almost nothing). Whenever the geometry of a chunk needs to be regenerated, use this buffer to prepare vertex data for the chunk. Just loop through the 16x16x16 chunk of cubes. For each cube, check if any of the cube’s neighbors is air to see if it’s visible. If it is, just generate vertex positions for that face (vertexPosition = chunkWorldPosition + localPositionInsideChunk + cubeVertex) and store their data in the buffer. When you’re done (note: you’ll end up with a LOT less data than the maximum capacity of the buffer in 99.999% of all cases.) just flip the buffer. Tadaah! You now have a perfectly fine buffer ready to be sent of to the GPU with glBufferData()!

Since the data is already translated, you can draw chunks with just a few lines of code later.


glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);

for(int i = 0; i < numVisibleChunks; i++){
    Chunk c = getChunk(i);
    glBindBuffer(GL_ARRAY_BUFFER, c.getVBO());
    glVertexPointer(3, GL_FLOAT, 16, 0);
    glColorPointer(4, GL_UNSIGNED_BYTE, 16, 12);
    glDrawArrays(GL_TRIANGLES, 0, c.getNumVertices());
}

glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);

Sorry for bumping the thread, but I have a few more questions!

  1. Do you know of any good tutorials on how to texture 3d objects? I’m trying to texture my cubes now and I don’t think using
glBindTexture ()

would be a good idea. I have heard about texture atlases, but I’m confused on how to bind the textures to the cube and draw them. Can I use a VBO?

2.I want to be able to pick the cubes in the 3D world and delete or add more. Can I use ray tracing to figure out where the current mouse position is in the world? Or do I have to ‘flatten’ the image down so its 2D and then just use the mouse position to pick cubes that way? I would a then ‘unflatten’ the image so it looks 3D again of course. I feel like that would be horribly inefficient though!

I am not so good at modern stuff but the way you bind a texture is by calling that function. TextureAtlas has multiple textures on it so you can bind it once and then render without having to bind a different texture. You do this by specifying different texture coordinates. If you are using modern opengl you do not need texture atlases.

You could probably pack all your different cube textures into a single 512512 or 10241024 texture if they are lower resolutions. That is you would have dirt, grass, water, etc all on one texture so there is only one bind call when you render your cubes. You can get away with quite a few texture binds and still stay at 60fps. I would say that as long as you do not bind a texture on every single cube you should be ok. Another thing you could do is have the current texture id saved and before binding a new one see if it matches the texture that is already bound that way you could reduce a bind call which may happen often.

I think the best way is to ray trace and pick the first cube it intersects with.

Thank you! However, my problem is that I cannot find any tutorials on how to actually render the texture. Is there a way to use VBOs to draw textures?

Rendering textures is pretty much the same as plain colours.
Firstly make sure GL_TEXTURE_2D is enabled.
Then replace your per vertex colour values with texture coordinates.
Bind the texture.
Draw the primitive as per normal.

Bind the texture as in calling

glBindTexture()

? Sorry, I’ve never done this obviously :stuck_out_tongue:

I want to add that I´m really new to this myself, but I sat with this all weekend, so I though I might share what I learned… Take a look at Davedes tutorial on how to load textures if you haven´t done that already:

Then you basically create a new buffer the same way you did with colors, but instead of colors you add texturecoordinates:

texCoordsData = BufferUtils.createFloatBuffer( **Enter buffersize here**);
texCoords.flip();

vboTextureHandle = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vboTextureHandleHandle);
glBufferData(GL_ARRAY_BUFFER, texCoordsData, GL_DYNAMIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);

And then you enable GL_TEXTURE_COORD_ARRAY the same way as you did with color and vertex:

glEnableClientState(GL_TEXTURE_COORD_ARRAY);

So it´s basically the same as vertex and color. Just make sure you bind the texture with before the drawmethod.

glBindTexture(GL_TEXTURE_2D, textureID);

I notice you don´t use glVertexPointer() or glColorPointer() method? I thought you had to use that to draw a VBO? Can someone share some insight…? Edit: Did not read all the code in the first post. So never mind me… :slight_smile:

So I’m stuck again! This time, I redesigned my chunk class for probably the fifth time, and now I come up with this error:

Cannot use offsets when Array Buffer Object is disabled

Which means I’m not calling

fglBindBuffer(target, buffer)

However, I believe I am. If someone could take a look at my code, I would be very grateful:

public class BaseChunk {

	BaseBlock block;

	private FloatBuffer vHandle;

	int vboV;
	int vboT;

	int vertSize = 3;
	int vertAmount = 4;
	int faceAmount = 6;
	int blockAmount = 4096;

	int startX;
	int startZ;
	int startY;

	public static final int CHUNK_SIZE = 16;

	public static boolean isChunkActive = false;

	public BaseChunk(int startX, int startZ, int startY, boolean isChunkActive) {
		this.startX = startX;
		this.startZ = startZ;
		this.startY = startY;
		BaseChunk.isChunkActive = isChunkActive;

		vHandle = BufferUtils.createFloatBuffer(vertSize * vertAmount * faceAmount * blockAmount);
	}

	public void fillChunkWith(BlockType type) {
		for (int x = startX; x < CHUNK_SIZE; x++) {
			for (int z = startZ; z < CHUNK_SIZE; z++) {
				for (int y = 0; y < CHUNK_SIZE; y++) {
					vHandle.put(BaseBlock.getQuadRenderCoords(x, z, y, BaseBlock.OFFSET));
					block = new BaseBlock(type, x, z, y);
				}
			}
		}
		vHandle.flip();
		genBuffer(vboV);
		bindBuffer(vboV, vHandle);
		render();
	}

	public void bindBuffer(int vboV, FloatBuffer vHandle) {
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboV);
		GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vHandle, GL15.GL_STATIC_DRAW);
	}

	public void genBuffer(int vboV) {
		vboV = GL15.glGenBuffers();
	}

	public void render() {
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboV);
		glVertexPointer(3, GL_FLOAT, 0, 0L);

		glEnableClientState(GL_VERTEX_ARRAY);

		for (int x = 0; x < CHUNK_SIZE; x++) {
			for (int z = 0; z < CHUNK_SIZE; z++) {
				for (int y = 0; y < CHUNK_SIZE; z++) {
					glPushMatrix();
					glDrawArrays(GL_QUADS, 0, vertSize * vertAmount * faceAmount * blockAmount);
					glPopMatrix();
				}
			}
		}
		glDisableClientState(GL_VERTEX_ARRAY);
	}
}

Any suggestions?

Hi opi

Sorry I can’t help you with you code, but I hope you get it sorted, and will keep popping back to see your progress. Look interesting and you are tackling similar problems to me.