Voxel Engine Best way to render?

Alright i am attempting to make a voxel engine which is similar to Minecraft (Just for fun) I have rendered 4 chunks and I have gone down from 120 FPS to 60 FPS so the way i am doing it isn’t very efficient.

I am using LWJGL 3 using the Open GL 3+
All of my rendering is done using VAOs (Vertex Array Objects)

Each chunk has to go though this method
Rendering code (CHUNK CODE)

private static final int LENGTH = 16;
	private Vector3f pos;
	private Block[][][] blockData;

	public Chunk(float xPos, float yPos, float zPos) {
		setPos(new Vector3f(xPos*(Block.BLOCK_WIDTH * LENGTH), yPos*(Block.BLOCK_HEIGHT * LENGTH), zPos*(Block.BLOCK_LENGTH * LENGTH)));
		blockData = new Block[LENGTH][LENGTH][LENGTH];
		for (int x = 0; x < LENGTH; x++) {
			for (int y = 0; y < LENGTH; y++) {
				for (int z = 0; z < LENGTH; z++) {
					blockData[x][y][z] = new Block(1,(x*Block.BLOCK_WIDTH)+pos.x, (y*Block.BLOCK_HEIGHT) + pos.y,(z*Block.BLOCK_LENGTH) + pos.z);
				}
			}
		}

	}

	public void render(Model staticObject,StaticShader shader) {
		shader.start();
		{
		GL30.glBindVertexArray(staticObject.getMesh().getVaoID());
		{
		GL20.glEnableVertexAttribArray(0);
		GL20.glEnableVertexAttribArray(1);
		GL20.glEnableVertexAttribArray(2);
		for (int x = 0; x < LENGTH; x++) {
			for (int y = 0; y < LENGTH; y++) {
				for (int z = 0; z < LENGTH; z++) {
					Vector3f blockPos = blockData[x][y][z].getPosition();
					shader.loadTransformationMatrix(Utils.createTransformationMatrix3D(blockPos, new Vector3f(), new Vector3f(1,1,1)));
					GL11.glDrawElements(GL11.GL_TRIANGLES, staticObject.getMesh().getCount(), GL11.GL_UNSIGNED_INT, 0);
					
				}
			}
		}
		GL20.glDisableVertexAttribArray(2);
		GL20.glDisableVertexAttribArray(1);
		GL20.glDisableVertexAttribArray(0);
		}
		GL30.glBindVertexArray(0);
		}
		shader.stop();
		
		
		
	}

	public Vector3f getPos() {
		return pos;
	}

	public void setPos(Vector3f pos) {
		this.pos = pos;
	}

I have also used culling for the back faces

		GL11.glEnable(GL11.GL_CULL_FACE);
		GL11.glCullFace(GL11.GL_BACK);
		GL11.glFrontFace(GL11.GL_CW);

Just to make sure I’m reading your code right, are you making a separate draw call (and setting up an individual transform) for each voxel?

Yes I am, however I am only using 4 VAOs (Each chunk)
and I am binding and rendering every cube then unbinding it

There’s a good amount of work that will go in to making a voxel renderer have good performance, and there’s no perfect, or single way to do it, and the ‘best’ way will likely be different across different computers. I’ve not made a voxel engine, and can’t confirm any of the implications of the below, but I believe these are some major points worth considering, in no particular order:

  • Only render voxels that you need to, through frustum culling, and occlusion culling. Do not test each voxel as that will incur a heavy cost, instead you would want to test visibility on chunks, if you’re using a chunk based system, and just allow a for the data of a few offscreen voxels to be sent down the graphics pipeline.
  • Construct a mesh representing the surface of an area of voxels and render the mesh, rather than rendering everything in that area.
  • Reduce the amount of draw calls you make, one draw call per voxel is likely to be far too many.
  • Be as cache coherent as possible. This basically means use a 1D array, and avoid using ‘Block’ classes as class instances require additional memory, and will just have less performance than using a plain int to represent the block type.

and I’m sure there’s plenty of other optimizations to be made for alternative approaches and specific parts, and many probably just to do with not doing silly things.

I’d suggest just taking one small step at a time until it works, before moving on to another optimization, taking an iterative approach to improvement.

On a tangent, I’ve got my own idea for voxel occlusion culling, but I’ll need a voxel engine to test it in, so I may have to try make one myself some time.

Just been searching around the internet and frustum culling looks really really confusing and complicated :frowning:

It is a little complicated if you’re not familiar with the math, but it’s not that bad. But, as noted in the above post there are a lot of other things you could try as well.

There’s a lot of info on voxel rendering available online, so nothing I say here will be new, and I haven’t actually done any voxel rendering myself. But as Husk said, one obvious possibility for improvement would be to batch your geometry and make fewer draw calls. For example, you could render one mesh per chunk rather than one per voxel. And, by building the meshes in world space you’d eliminate the need for the world transform (I imagine building a transform matrix per voxel, as you’re doing now, is probably pretty costly). Another consideration is that you’ll want your voxels to connect to one another seamlessly, and that won’t necessarily be guaranteed if you’re rendering each voxel with a separate transform (the same applies with chunks as well).

So that’s probably where I’d start, with building a separate mesh for each chunk. Note that sides of a voxel that are next to another occupied voxel cell can be skipped, which will likely cut down on your geometry significantly.

Yeah i have thought about doing it that way but what i cannot get around my head is how would I set a individual voxel to (Visible/Invisible)

Okay I have made all of the voxels into one mesh now how would i remove selected ones like deleteBlock(x,y,z) ???

Ok so it doesnt look like they are actually meshed , I can still see all the lines inbetween them. Also if you want to improve performance you will need to implement face culling , currently from your render code I can see that you render all voxels with every face. If you are using opengl I think its something like glEnable(GlFaceCulling). Been a few months since ive done any opengl work so if someone could clarify this for me that would be great. Also , how many vbos do you have , if you have one for each voxel you are going to lag like crazy even with only a couple.

Okay i have already done face culling and all of those voxels are in one mesh i am not sure why there are dots there

http://pastebin.com/QMM0J61p // Just so you can see

and I am using 1 VAO which contains 4 VBOS(Vertices, Indices, TextureCoords,normals) for 1 Mesh
The next step which i cannot understand is how to get each individual voxel and edit it?
would i have to bindBuffer each frame with new data?

I mean like i can edit the data before it loads but when it loads i cant edit it does this mean every time i change something i will need to reload the whole chunk?

Ok well , to edit each individual part you will need to regenerate the mesh . This can be expensive so I wouldnt suggest just meshing the entire object , meshing an object down by a power of 10 would improve performance but also prevent terrible lag. If you know it wont be modified ( through certain conditions) then mesh at will.

You could look into glMapBufferRange for updating chunks.

So are you saying not to mesh it now and keep it at individual voxels? Okay ill look at glMapBufferRange ;D

As noted above, the dots that are visible where the voxels meet indicate a problem in your approach. I looked at your code, and to be honest I’m not sure offhand why you’re getting them, because it looks like all your vertex positions are at integer coordinates, and in that range I wouldn’t expect any numerical error, but maybe I’m missing something. It’s more or less irrelevant though, because conceptually you don’t want to compute the vertex positions for each voxel separately, as this can lead to rendering artifacts (as appears to be happening here).

As for how many voxels to include in one mesh, I think the idea is not to use one mesh for all voxels, or one mesh for each voxel, but rather to split the environment up into chunks of NxNxN voxels, where N is some reasonable number like 16. The idea is to find a reasonable compromise between one huge mesh (hard to cull and hard to edit, and maybe excessive in terms of the amount of data in a single draw call) and one mesh per voxel (too many draw calls and too much per-voxel overhead).

If you’re going for a modifiable environment, then you may have to rebuild chunks dynamically as needed, but that’s not unreasonable.

As for how the mesh for each chunk should be built, to prevent rendering artifacts, you want to make sure that the coordinates for any particular (most likely shared) vertex position are always computed using exactly the same arithmetic (computing the same vertex coordinates multiple times with different arithmetic can lead to the kinds of visual artifacts you’re seeing).

There’s a lot more to consider here, but switching to a chunk-based system and not computing the coordinates of shared vertex positions multiple times using different arithmetic (which is what can lead to rendering artifacts) would probably be a good start (or at least it seems so - maybe someone else will suggest a better approach).

I already have a chunk base system not working fully but it works but what i wouldl ike to know is how would i edit the chunk (Mesh) when destroying blocks/editing?

I’ll offer a couple more ideas, but I’m basically just speculating here (again, I haven’t done any voxel rendering myself, and there’s a lot of detailed information already out there that might of more use to you).

For any given chunk, you only need to include voxel faces that are actually visible (for any two adjacent voxels, the coincident faces can be omitted). Technically this also applies between chunks (that is, the voxels in one chunk can obscure faces of the voxels of a neighboring chunk), but if you wanted to keep things simple you could consider faces on the boundary of a chunk to always be visible. That way, you won’t have to rebuild neighboring chunks when a chunk changes.

For simplicity, I’d start with just rebuilding the mesh for a chunk from scratch any time the chunk changes. (If that proves to perform poorly, then you could investigate more sophisticated approaches.) I would do it something like this (off the top of my head, so may be incorrect). Iterate over all the voxels in the chunk. If the voxel is occupied, add all the faces for the voxel for which the adjacent voxel (if there is one) is unoccupied. To prevent rendering artifacts, vertex positions with the same coordinates should always be computed using exactly the same arithmetic. (I’m assuming here that you’re asking about how to modify the mesh geometry, and not about OpenGL-related details like how to dynamically update a VBO.)

Okay so i have done the culling inside the mesh(chunk) so when i go inside it i cannot see anything outside. So how would i be able to edit these voxels with my mouse cursor?

Use google , there are a lot of ways to do this. The easiest is ray casting and suprisingly its the fastest. Go research it, seriously not difficult stuff.