Questions on VBO and adding geometry


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

This is highly suspicious code, as the value is written into a local variable, which is basically a no-op. The fact that there is also a field named ‘vboV’ doesn’t change this.

Fix:


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

I was so interested to see this aproach, to have each chunk make a buffer… But no matter what I do, this line will not run…
error… 115 is not a valid number in GL15 ?

So… can each chunk make a buffer? and then render itself? That seems the most sensible, but it just will not work for me… are you having any luck?

I figured it out, I just forgot to call

this.vboV

to actually reference the correct int.
As for your question Vermeer, I don’t entirely understand what you’re asking, but yes, you can create a chunk based on a buffer. I’ve seen your thread, and I would highly recommend switching over to VBOs, I generally get around 20 FPS more than you do with no optimizations (face culling, only rendering visible cubes).

Hi opi

Thanks for your positive comments. I hope you get time to work on yours soon!
Thanks to the suggestions you have posted in your thread I got VBO’s working.

Will keep poping back to see how your getting on. :slight_smile:

No problem! I think you’re doing great, I’m actually very envious of how much work you’re doing! I unfortunately will barely be able to code for the next couple of weeks at least, so don’t expect much from me for a while :confused:

Keep up the good work!

I tried to conquer textures this weekend, but it doesn’t seem like they want to load. I create a new VBO to hold the block texture coordinates, bind the texture two different ways actually(maybe that’s whats wrong), and then I create the VBO id for the the texture and call

glEnableClientState(GL_TEXTURE_COORD_ARRAY)

Here’s the full code:

package com.nishu.mime.world;

import java.nio.FloatBuffer;

import static org.lwjgl.opengl.GL11.*;

import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL15;

import com.nishu.mime.blocks.BaseBlock;
import com.nishu.mime.blocks.BlockType;

public class BaseChunk {

	public BaseBlock blocks[][][] = new BaseBlock[CHUNK_SIZE][CHUNK_SIZE][CHUNK_SIZE];

	BaseBlock block;

	private FloatBuffer vHandle;
	private FloatBuffer tHandle;

	int vboV;
	int vboT;

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

	int startX;
	int startZ;
	int startY;

	int count = 0;

	public static final int CHUNK_SIZE = 16;

	public static boolean isChunkActive = false;
	boolean shouldRenderBlock = false;
	boolean facesVisible[] = new boolean[6];

	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);
		tHandle = BufferUtils.createFloatBuffer(vertSize * vertAmount * faceAmount * blockAmount);
	}

	public void fillChunkWith(BlockType type) {
		isChunkActive = true;
		for (int x = startX; x < CHUNK_SIZE; x++) {
			for (int z = startZ; z < CHUNK_SIZE; z++) {
				for (int y = 0; y < CHUNK_SIZE; y++) {
					setBlock(type, x, z, y);
				}
			}
		}
		rebuildChunk(startX, startZ, startY);
	}

	public void rebuildChunk(int startX, int startZ, int startY) {
		boolean render;
		isChunkActive = true;
		int x = startX;
		int z = startZ;
		int y = startY;
		for (x = startX; x < CHUNK_SIZE; x++) {
			for (z = startZ; z < CHUNK_SIZE; z++) {
				for (y = startY; y < CHUNK_SIZE; y++) {
					render = checkFaces(x, z, y);
					if (render) {
						vHandle.put(BaseBlock.getQuadRenderCoords(x, z, y, BaseBlock.OFFSET));
						tHandle.put(BaseBlock.getQuadTextureCoords());
						blocks[x][z][y].bindTexture(vboT);
					}
				}
			}
		}
		vHandle.flip();
		tHandle.flip();
		vboV = genBuffer(vboV);
		vboT = genBuffer(vboT);
		bindBuffer(vboV, vHandle);
		bindBuffer(vboT, tHandle);
		render();
	}

	private boolean checkFaces(int x, int z, int y) {
		if (x <= 0 || z <= 0 || y <= 0 || x >= CHUNK_SIZE || z >= CHUNK_SIZE || y >= CHUNK_SIZE) {
			for(int i = 0; i < 6; i++){
				facesVisible[i] = true;
			}
		}
		if (x > 0 && x < CHUNK_SIZE - 1 && getBlock(x + 1, z, y) != null) {
			facesVisible[0] = false;
		} else {
			facesVisible[0] = true;
		}
		if (x > 0 && x < CHUNK_SIZE && getBlock(x - 1, z, y) != null) {
			facesVisible[1] = false;
		} else {
			facesVisible[1] = true;
		}
		if (z > 0 && z < CHUNK_SIZE && getBlock(x, z - 1, y) != null) {
			facesVisible[2] = false;
		} else {
			facesVisible[2] = true;
		}
		if (z > 0 && z < CHUNK_SIZE - 1 && getBlock(x, z + 1, y) != null) {
			facesVisible[3] = false;
		} else {
			facesVisible[3] = true;
		}
		if (y > 0 && y < CHUNK_SIZE && getBlock(x, z, y - 1) != null) {
			facesVisible[4] = false;
		} else {
			facesVisible[4] = true;
		}
		if (y > 0 && y < CHUNK_SIZE - 1 && getBlock(x, z, y + 1) != null) {
			facesVisible[5] = false;
		} else {
			facesVisible[5] = true;
		}
		shouldRenderBlock = facesVisible[0] && facesVisible[1] && facesVisible[2] && facesVisible[3] && facesVisible[4] && facesVisible[5];
		if (shouldRenderBlock) {
			System.out.println("Rendering");
			currentBlockCount++;
			return true;
		} else {
			System.out.println("Not Rendering");
			return false;
		}
	}

	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);
		
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboT);
		GL15.glBufferData(GL15.GL_ARRAY_BUFFER, tHandle, GL15.GL_STATIC_DRAW);
	}

	public int genBuffer(int id) {
		return id = GL15.glGenBuffers();
	}

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

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);

		glPushMatrix();
		glDrawArrays(GL_QUADS, 0, vertSize * vertAmount * faceAmount * currentBlockCount);
		glPopMatrix();
		
		glDisableClientState(GL_VERTEX_ARRAY);
		glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	}

	public BaseBlock getBlock(int x, int z, int y) {
		return blocks[x][z][y];
	}

	public void setBlock(BlockType type, int x, int z, int y) {
		blocks[x][z][y] = new BaseBlock(type, x, z, y, true);
	}
}

And here’s the texture coords:

public static float[] getQuadTextureCoords(){
		return new float[]{
				 0, 0, 0, 
				 1, 0, 0, 
				 1, 0, 1, 
				 0, 0, 1, 
				 
				 0, 0, 1, 
				 1, 0, 1, 
				 1, 1, 1, 
				 0, 1, 1, 
				 
				 1, 0, 0, 
				 1, 1, 0, 
				 1, 1, 1, 
				 1, 0, 1, 
				 
				 0, 1, 0, 
				 0, 0, 0, 
				 0, 0, 1, 
				 0, 1, 1, 
				 
				 0, 1, 1, 
				 1, 1, 1, 
				 1, 1, 0, 
				 0, 1, 0, 
				 
				 0, 1, 0, 
				 1, 1, 0, 
				 1, 0, 0,
				 0, 0, 0 
		};
	}

And my bind method:

public void bindTexture(int texID) {
		texture.bind();
		GL11.glBindTexture(GL11.GL_TEXTURE_2D, texID);
	}

What could I be doing wrong?

Hi. Will post code In my thread as asked.

But…texture coordinates only have 2 values, uv. Or(s,t)
You you putting 3 in?

The co-ordinaries are 2d for textures.

Oh wow I am… how stupid of me :stuck_out_tongue: Thanks for the code!

So I tried to tackle textures today. I have a simple texture that looks like this:

However, when I apply the texture to the cubes, it looks like this:

Obviously I did something very wrong. I basically load the texture up using Slick, create a buffer that holds 2 * 3 * 6 * 4096 (vertex size, amount of vertices per face, faces, number of blocks in a chunk) bytes or whatever you measure that in, bind the texture and put the data into the buffer. I then render it out. Here’s the relevant code:

public class BaseBlock {
		
	public static final int OFFSET = 1;

	private BlockType type;
	private Texture texture;
	private int x, z, y;
	private boolean isActive;

	public BaseBlock(BlockType type, int x, int z, int y, boolean isActive) {
		this.setType(type);
		this.x = x;
		this.z = z;
		this.y = y;
		this.setActive(isActive);
		try {
			this.texture = TextureLoader.getTexture("PNG", new FileInputStream(new File(type.tex_loc)));
		} catch (FileNotFoundException e) {
			System.err.println("Texture Location Not Found");
		} catch (IOException e) {
			System.err.println("Texture Not Loaded Correctly");
		}
	}

	public void bindTexture() {
		texture.bind();
	}

	public static float[] getQuadRenderCoords(int x, int z, int y, int offSet) {
		return new float[] { x, z, y, 
							 x + offSet, z, y, 
							 x + offSet, z, y + offSet, 
							 x, z, y + offSet, 
							 
							 x, z, y + offSet, 
							 x + offSet, z, y + offSet, 
							 x + offSet, z + offSet, y + offSet, 
							 x, z + offSet, y + offSet, 
							 
							 x + offSet, z, y, 
							 x + offSet, z + offSet, y, 
							 x + offSet, z + offSet, y + offSet, 
							 x + offSet, z, y + offSet, 
							 
							 x, z + offSet, y, 
							 x, z, y, 
							 x, z, y + offSet, 
							 x, z + offSet, y + offSet, 
							 
							 x, z + offSet, y + offSet, 
							 x + offSet, z + offSet, y + offSet, 
							 x + offSet, z + offSet, y, 
							 x, z + offSet, y, 
							 
							 x, z + offSet, y, 
							 x + offSet, z + offSet, y, 
							 x + offSet, z, y,
							 x, z, y };
	}
	
	public static float[] getQuadTextureCoords(){
		return new float[]{
				 0, 0,
				 1, 0,
				 1, 1,
				 0, 1,
				 
				 0, 0,
				 1, 0,
				 1, 1,
				 0, 1,
				 
				 0, 0,
				 1, 0,
				 1, 1,
				 0, 1,
				 
				 0, 0,
				 1, 0,
				 1, 1,
				 0, 1,
				 
				 0, 0,
				 1, 0,
				 1, 1,
				 0, 1,
				 
				 0, 0,
				 1, 0,
				 1, 1,
				 0, 1,
				 
		};
	}

Part of my chunk class:

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);
		tHandle = BufferUtils.createFloatBuffer(texSize * vertAmount * faceAmount * blockAmount);
	}

	public void fillChunkWith(BlockType type) {
		isChunkActive = true;
		System.out.println(startX);
		for (int x = startX; x < CHUNK_SIZE; x++) {
			for (int z = startZ; z < CHUNK_SIZE; z++) {
				for (int y = 0; y < CHUNK_SIZE; y++) {
					setBlock(type, x, z, y);
				}
			}
		}
		rebuildChunk(startX, startZ, startY);
	}

	public void rebuildChunk(int startX, int startZ, int startY) {
		boolean render;
		isChunkActive = true;
		int x = startX;
		int z = startZ;
		int y = startY;
		for (x = startX; x < CHUNK_SIZE; x++) {
			for (z = startZ; z < CHUNK_SIZE; z++) {
				for (y = startY; y < CHUNK_SIZE; y++) {
					render = checkFaces(x, z, y);
					if (render) {
						vHandle.put(BaseBlock.getQuadRenderCoords(x, z, y, BaseBlock.OFFSET));
						tHandle.put(BaseBlock.getQuadTextureCoords());
						blocks[x][z][y].bindTexture();
					}
				}
			}
		}
		vHandle.flip();
		tHandle.flip();
		vboV = genBuffer(vboV);
		vboT = genBuffer(vboT);
		bindBuffer(vboV, vHandle);
		bindBuffer(vboT, tHandle);
		render();
	}

Then how I 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);
		
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboT);
		GL15.glBufferData(GL15.GL_ARRAY_BUFFER, tHandle, GL15.GL_STATIC_DRAW);
	}

	public int genBuffer(int id) {
		return id = GL15.glGenBuffers();
	}

	public void render() {
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboV);
		glVertexPointer(vertSize, GL_FLOAT, 0, 0L);
		
		GL15.glBindBuffer(GL15.GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING, vboT);
		glTexCoordPointer(2, GL_FLOAT, 0, 0L);

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);

		glPushMatrix();
		glDrawArrays(GL_QUADS, 0, vertSize * vertAmount * faceAmount * currentBlockCount);
		glPopMatrix();
		
		glDisableClientState(GL_VERTEX_ARRAY);
		glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	}

Could it be because I didn’t wrap the texture? Is the texture not the right resolution? Its 16 * 16, but the block size is currently set at 1.

I figured one thing out, I changed this:

glTexCoordPointer(2, GL_FLOAT, 0, 0L);

to this:

glTexCoordPointer(3, GL_FLOAT, 0, 0L);

But now only one side of the blocks have textures. When I render out a skybox in immediate mode with the same texture coords, it works fine. So whats wrong with my VBO?

Im not entirly sure but i think it should be 2,
I interleaved mine like this.
glVertexPointer(3, GL_FLOAT, /* stride */21, / offset */(1) << 2);
GL11.glTexCoordPointer(2, GL_FLOAT, /
stride */21, / offset **/(4) << 2);

1 thing that may help is making a square texture, with a border, with different colour sides. It may help you see whats going on…

I think someone more experienced with this would give better advice. I dont want to advise you wrongly…

Hope you sort it soon… :slight_smile:

you have put no offsett on yours…

I used 2 and the textures were all screwed up:/ 3 partially works. For the offsets, why would I need them? I already offset my blocks when rendering, why would I need to offset them again?

Ok, I really would love some help, I’m incredibly frustrated right now. I have 2 problems:

  1. The textures for my cubes are actually stretching across the right, bottom, top and left sides of the blocks, but work normally on the front or back. I know my texture coords are right because I use them to draw a skybox in immediate mode! Should I be using some sort of wraping function?

  2. First off, I know OpenGL is a state based machine. However, I need help because when I texture my skybox, and the texture my blocks, the skybox texture is applied to the blocks. I bind the texture for the skybox, draw it, then bind the texture for the blocks and then draw them. Should I unbind the textures after I’m done with them so they arent applied to anything else? Or is there a better way? Someone suggested using

glPushAttrib()

to keep attributes of those vertices away from other vertices and thus my textures will not bleed over. I feel like this isnt the right way to do it though. Any thoughts?

Thanks for everyones help!

@vermeer: Those strides and offsets are nuts. Please read the specification of those methods.

These are the values Im using currently, which agree with the specifiaction.
glVertexPointer(3, GL_FLOAT, 32, 04);
GL11.glColorPointer(3,GL_FLOAT, 32, 3
4);
GL11.glTexCoordPointer(2, GL_FLOAT, 32, 6*4);

I copied thouse others from an outdated method by accident! I dont even remeber how I had 21 there!