Archive for the ‘Improvements’ Category.

Fault Formation improved

Introduction

I’ve improved the Fault Formation algorithm further.

Now I can obtain a more detailed heightmap with half iterations, this is a huge improvement for performances and quality!

The problem

The original algorithm says that, for each generated random line, one side of the map has to be raised adding some value and the other side has to remain unchanged.

This algorithm gives not so good results with big maps, look at the following image to understand what I mean:

the heightmap in the left panel shows a terrain generated by 1000 iterations of the original algorithm, as it’s possible to notice there are too much mountains and too few plains. The blur (right panel) doesn’t fix this problem.

In order to improve the variedness of the terrain I changed the algorithm subtracting the same value that is added to one side of the map to the other side. This didn’t sort the problem out, so I tried to clamp the height values inside the shader to the range [0.0 - 1.0]. Clamping the values improved the generation a bit, but it gave more coarse maps, like showed in the following image:

The left panel shows a terrain generated by 1000 iterations of the modified algorithm with clamping. It’s easily possible to see the lines that determine the terrain, also in the blurred version (right panel).

In order to give more detailed heightmaps the modified algorithm requires about 50% more of iterations (so 1500).

Another problem inherited by the original algorithm is the almost totally lack of control on the generated terrain.

The new algorithm

The new algorithm I’ve developed fixes all the described problems and it’s really simple, the only difference with the original one is that now I subtract a different value to the other side of the map, this value is just the value added to the other side multiplied by a constant in the range [0.0 - 1.0].

So the code that modifies the map now is something like this:

if(fragment is on the left side)
	h += inc;
else
	h -= (inc * dec_mult);

The new algorithm gives more detailed maps using less iterations and allows to control the results varying the dec_mult value as showed in the following image:

The top-left panel shows a map generated by 1000 iterations of the new algorithm setting dec_mult = 0.1, the top-right panel shows the blurred version. The bottom-left panel shows the same map setting dec_mult = 0.01, the blurred version is on the right.

Of course setting dec_mult = 0.0 gives the same results as the original algorithm.

The new algorithm sometimes generate some weird results using some values of dec_mult, an example is showed in the left panel of the following image:

but this problem can be easily solved using a fixed value to add/subtract to the heights (in the original algorithm the added value is decreased with each iteration), obtaining so a standard map as showed in the right panel of the previous image.

Now the algorithm requires a normalization phase after the generation, but the normalization takes a short time and so the new algorithm can be considered faster than the previous version because it generates more detailed maps using half the iterations. A normalization phase takes about 70 ms. for a 1024×1024 heightmap, instead 500 iterations take about 500 ms. so it’s definitely faster!

UPDATE 19/04/2008

I’ve found the original paper about the Fault Formation algorithm, the author says to change the values on both sides of the map after a line is drawn. So my implementation follows the original algorithm!

I’m wondering why Jason Shankel (author of a chapter about the FF in Game Programming Gems 1) describes the “different” algorithm with just the raising operation. Maybe for a performance issue.

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

Shaders optimization

Introduction

Thanks to a night at Encelo’s flat that meant some discussions (several beers… :-) ) and a bit of testing I’ve improved a lot the performance of almost all the shaders!

I’ve continued to work on optimization for another day, and now I’m really satisfied of the results I’ve obtained, in most of cases the improvements are amazing, as you will see in the benchmarks I’m going to publish in the next posts.

In this discussion I’m going to talk about a couple of optimizations for shaders coding.

Optimizing the two phases shaders

As I’ve described in my previous posts, the first three thermal erosion shaders are based on two different phases.

In my first implementation I put the code of both phases in a single shader and the program decided what phase to execute according to a uniform variable “phase” and an if branch.

I’ve discovered this is a bad way of coding, the best way is split the two phases in two different shaders, attach them to two different shader programs and call the appropriate program inside the GL application keeping the logic branch there.

Optimizing the shaders execution

Thanks to the previous optimization I’ve started to attach every single shader to a different shader program, and (re)call the program when needed, i.e. the associated key is pressed.

Before of that I used a single shader program and I attached to it a different shader every time it was needed, this way required a linking at every execution and I suppose it requires several other operations hidden inside the GL/graphic pipeline, taking so much more time to execute the shader.

Some minor optimizations

Some minor suggestions to keep in mind are:

  • use GLSL functions also for simple code as the cross product
  • avoid type casting and use floats all the times that are required computations (usually GLSL functions requires float and so they built-in variables are)
  • use the latest video drivers, updating my NVIDIA video drivers from 100 to 169 version improved thermal erosion shaders by about 10%.
[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

Can I take a picture…?

Introduction

I’ve spent the last 2 days coding a lot, the result of this “burst” of development is a brand new feature and several fixes/improvements in the code.

New features

The main feature developed is the possibility to export the generated maps in PNG, this feature uses libpng and it’s based on the Encelo’s code. The main difference between my code and the Encelo’s one consists in the fact that I don’t use a SDL surface to write the PNG file, but my code uses just the GL texture.

I’ve developed this feature to be able to generate and save maps bigger than the screen resolution (I took screenshots using GIMP before of that), now it’s possible to set a dimension for the main window and a different dimension for the texture (the map).

Thanks to this new feature I’m going to use 1024×1024 as new default dimension for my maps.

Another useful feature is the computation of the percentage of height ranges, now, pressing a button it’s possible to know how much heights are in the ranges [0.0, 0.25], [0.25, 0.5], [0.5, 0.75] and [0.75, 1.0].

Improvements

I’ve also fixed a couple of bugs in the old code, in particular in the normalization code, furthermore I’ve coded a Screen class that manages the SDL window and all the GL code to init the environment and display the scene in the right way, this has cleaned the code a bit.

In the end I’ve also improved the visualization of the initial settings of all the programs.

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

Code refactory

Introduction

I’ve spent the last few days (yes, Christmas too…) working on a big refactory of the code of my programs, most of the code is Object Oriented now and I’m planning to make everything OO soon.

The changes

I’ve introduced 3 news classes:

  • Shader : a vertex or a fragment shader, the code loads, compiles and manages a shader
  • ShaderProgram : a shader program, it’s connected to two Shader
  • PingPongTexture : a couple of textures needed by the Ping-Pong technique

Furthermore I’ve rearranged the shaders, now all the sources are in a separate directory and they can be easily used in both the programs.

Example of code

This code manages the erosion using the old code:

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);

vs = InitShader(GL_VERTEX_SHADER, “src/shad.vert”);
fs = InitShader(GL_FRAGMENT_SHADER, “src/shad3.frag”);
p = InitProgram(vs, fs);

tex0_loc = glGetUniformLocation(p, “Tex0″);
alpha_loc = glGetUniformLocation(p, “alpha”);

glUniform1i(tex0_loc, 0);
glUniform1f(alpha_loc, alpha);

for(int i = 0; i < eros_it; i++)
{
	glDrawBuffer(att_point[write_tex]);

	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, tex[read_tex]);

	ShaderDraw();

	if(read_tex)
	{
		read_tex = 0;
		write_tex = 1;
	}
	else
	{
		read_tex = 1;
		write_tex = 0;
	}
}

This code manages the same stuff using the new code:

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);

p->AttachShader(eros1_shader);
p->LinkProgram();
p->UseProgram();

eros1_shader->SetUniformInt(“Tex0″, 0);
eros1_shader->SetUniformFloat(“alpha”, alpha);

for(int i = 0; i < eros_it; i++)
{
	pp_tex->SetDrawBuffer();

	glActiveTexture(GL_TEXTURE0);
	pp_tex->BindTexture(READ_TEX);

	p->Run(W, H);

	pp_tex->Swap();
}

The difference is really evident!

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

Circles algorthm and floating point textures

Introduction

This post discuss the use of floating point (16 bits) textures with the Circles algorithm.

Results summary

Using floating point textures  gives a good improvement because it fixes a problem that affects several maps generated with this algorithm. In fact, when the number of iterations is bigger than 500 or when some parameters like the radius of the circle are bigger than the default values, the map shows several white regions.

Thanks to floating point textures and to the normalization phase those regions are normalized and all the maps are usable.

Some examples

This is a terrain of type 2 generated by 500 iterations using a 16-bits texture before (left) and after (right) the normalization phase:

          

It’s possible to notice the white regions in the first image.

This is a terrain of type 1 generated by 1000 iterations using a 16-bits texture before (left) and after (right) the normalization phase:

         

Also here it’s possible to notice the white region in the first image.

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]