Voxel - a start

Thanks Mike,

Display lists have been completely removed from OpenGL 3.1 (still compatibility with ARB supported) and in 3.2 it is up to the driver writers if they want to support them - in compatibility profile.

A good discussion here:

As the voxels are static is display list the best way, although, the player will be able to remove blocks so does this mean the display lists will need rebuilding?

Regards,
Steve

With my tests (using the different Riven VBO/VA techniques) I managed a more stable fps with VBO’s (constantly in the 80’s) while with display lists it fluctuated a bit more when looking around, but it was constantly higher (90-110).

Luckily LWJGL doesn’t force you to use the 3.1 profile then :slight_smile: I can just talk for myself and I’ve had less compatibility issues with State of Fortune which uses Displaylists than I have with State of Profit that uses VBO’s. Sure, you need to have a really crappy (intel…) gfx driver to not be able to use VBOs correctly, but they are out there.

When you remove blocks the display lists will need rebuilding, but if you try out State of Fortune you’ll notice that the time it takes to rebuild the displaylist isn’t even noticable as long as you spread out the rebuilding of several containers over several frames (which you should do with VBO’s as well).

I’m not saying to use displaylists instead of VBOs, I’m just saying that it isn’t as bad as people say they are. Especially seeing as at least my NVIDIA drivers optimize the (semi) static ones so heavily that they outperform what I can do with VBOs, even while following Riven’s latter examples (http://www.java-gaming.org/topics/introduction-to-vertex-arrays-and-vertex-buffer-objects-opengl/24272/view). For anything dynamic that needs to be rebuilt more or less every frame, use VBOs, especially as you can multithread the creation of them with ease.

Mike

Cheers Mike,

Very interesting.

I’m quite new to OpenGL, was stuck on the direct3d band wagon for a while.

Have you any advice on a simple technique to get heights for my voxels, just using a simple random value at the moment which looks crud, need it look smoother, I’ve got the SimplexNoise class, but not tried to use it as yet.

Thanks,
Steve

Simplex is the easiest way to go while still getting a nice result :slight_smile: To get an interesting landscape you can run it several times with a different frequency and weight. Something like this:

height=SimplexNoise.noise(x,y);
height+=SimplexNoise.noise(x/16,y/16)*10;

Mike

If you need terrain generation look at mine :slight_smile:
http://www.java-gaming.org/topics/terrain-generator/27502/view.html

Local Copy: https://dl.dropbox.com/u/39535549/Volt.jar (Demo + Source)

Thanks guys,

Will take a look at the code ;D

Mike - height=SimplexNoise.noise(x,y); the x and y, taking it I store the height inside an array
and then render?

I do this:


int voxelHeights[] = new int[xAmount * zAmount];  // used to store amount of voxels on y

and in render:


int index = 0;
		for(int x = 0; x < this.xAmount; x++)
		{
			for(int z = 0; z < this.zAmount; z++)
			{
				for(int y = 0; y < voxelHeights[index]; y++)
				{
					glTranslatef(x,y,z);
					glCallList(voxelList);
					glTranslatef(-x,-y,-z);
				}
				index++;
			}
		}

At the moment, I use random value for height:


private void generateWorld() {
		Random randomGenerator = new Random();
		for (int heights = 0; heights < xAmount * zAmount; heights++) {
			int height = randomGenerator.nextInt(16);
			if(height == 0) height = 1;
			voxelHeights[heights] = height;
		}
	}

So I’m guessing that I need to put the simplex noise in my generateWorld method?

Thanks again, really appreciate your advice.

Steve

I don’t know anything about simpleX, but I think that yes, you should probably put it in your generateWorld method. I’m confused, a little, about why you call

glTranslatef()

twice though, with positive and then negative values. Would that cancel the translate and just set the voxel position back at zero?

Hi Mike,

The glTranslate twice is to reset position back of the model matrix. I know I should just use one glTranslate, will resort to this later.

put this in my generateWorld to get heights from simplexnoise:


int index = 0;
		for(int x = 0; x < xAmount; x++)
		{
			for(int y = 0; y < zAmount; y++)
			{
				int height = (int)SimplexNoise.noise(x, y);
				voxelHeights[index] = height;
				index++;
			}
		}

I use height for how many voxels I draw on the Y, but SimplexNoise returns a double from the value of -1 to 1, don’t get how I can use this?

Thanks

Everyone is Mike? :slight_smile:

If your Simplex returns values from -1 to 1, just do (int)((result+1)/2*desired max height) or something like that.

Use pop and push matrix instead of translating back :slight_smile:

Mike

Hi,

This is what I got for the simplex noise:


int index = 0;
		for(int x = 0; x < xAmount; x++)
		{
			for(int z = 0; z < zAmount; z++)
			{
				
				int height = (int) (SimplexNoise.noise(x/16F, z/16F)*16F);
				voxelHeights[index] = height;
				index++;
			}
		}

height is sometimes zero, thus no height, what would you do with that, set it to 1? I’m taking it depending on the height you could set the block type to say water, grass, dirt, snow for instance?

Thanks again,
Steve

Simplex Noise returns values between -1 and 1.

Multiplying it by 16 and flooring results in an integer between -16 and 16.

If you want to have only positive values, you need to divide by 2 and add half the max value.

Eg:


(SimplexNoise.noise(x/16F, y/16F)/2F+0.5F)*16;

Will give a value between 0 and 16.

Thanks,

Got that working.

One question, how do you once you render a chunk, place another one next to it, above etc?

Regards,
Steve

What I do with voxel engines is put every single voxel in a chunk into one VBO. Then I render it.
Other chunk just mean I need to offset the data I put in the VBO.

What you do is translate to the position of the voxel, then draw it. Meaning you have to draw again and again and again etc.

The only solution to your problem at the moment, is to translate to the coordinates of the next chunk and repeat the process.

Hi,

So you put one chunk into VBO then render it, then get next chunk, put that into VBO, translate, then render it etc?..

I’m using display list atm, doesn’t seem too bad…but should it be in a VBO?

Thanks again

Display list is ok for learning purposes, but you’ll want to begin using VBOs for better performance.

Are VBO’s definitely faster than display lists for static geometry?

Just trying to find a good tutorial on drawing a cube with a VBO.

This looks good:

Just to recap, say if I have 20 chunks, I put one chunk into VBO then render, translate, then next chunk into VBO then render etc?..

Thanks

I just finished writing a post here with some code

Thanks for that :slight_smile:

It is looking like you shouldn’t use glTranslatef - so if not using a translate, do the blocks need to be in some form of local coordinate space? Sorry for not understanding fully, just trying get my head around how you would draw a block without glTranslatef and put another block at the side of it?
Do you have to translate all the blocks first then send to the GPU?

Here is my render code for a block:


for(int chunkAmount = 0; chunkAmount < 1; ChunkManager.getInstance().GetChunkCount(); chunkAmount++)
		{
			Chunk c = ChunkManager.getInstance().GetChunk(chunkAmount);
	
			for (int x = 0; x < c.CHUNK_SIZE; x++) {
				for (int y = 0; y < c.CHUNK_SIZE; y++) {
					for (int z = 0; z < c.CHUNK_SIZE; z++) {
						GL11.glPushMatrix();
						glTranslatef(x,y,z);   // !! Translating for each block in a chunk
						renderBlock(c.GetBlock(x,y,z));
						GL11.glPopMatrix();
					}
				}
			}
		}

// render given block - just check if it is active or not
private void renderBlock(Block b)
{
	if(b.IsActive())
	{
		glCallList(voxelList);   
	}
}

How could the glTranslatef be removed?

Thanks again, really, really appreciate all the help.
Steve

VBO’s are just like display lists, so you only have to store data inside it when the data changed.
Each chunk, block or object can have its own VBO.
With VBO’s its possible to update only a small part of the data, what would be much faster then updating all data like with display lists.

glTranslatef(x,y,z); can be removed by making the list (or the VBO in the future) draw the whole chunk instead one block.

Thanks,

So, we can just use an offset on the vertex data for a block to position it?

Also, how would I store all the blocks for a chunk into one display list?

I guess I should do this next:

  1. Put chunk into a VBO (all blocks for a chunk) - add an offset to each vertex in block to position it (modify vertex position directly) instead of using glTranslatef…
  2. Render chunk
  3. Get next chunk, repeat 1 until all chunks done

Does this seem ok? Then in (3) we add offset to chunk position (width of chunk)?

Thanks