These following posts span my later half of my 3rd Year at the University of Abertay Dundee when we were studying procedural generation and post processing effects.
I was initially tasked with creating a flat mesh to represent a terrain. It was advised to create an algorithm which created a diamond pattern. After sketching out a plan and trying to work it out in my head, I went on to code out what I thought would make the correct mesh. To my amazement; it was spot on. The only issue was that I was only using a vertex buffer, which not only meant there was up to 8 vertices at any one point, but also, randomly offset vertices would result in a broken surface.
So I went about editing my code to include an index buffer, which to my despair meant recalculating my algorithm, however with the basic principles in mind, this wasn’t too hard and I soon managed to recreated the same grid:
I was initially tasked with creating a flat mesh to represent a terrain. It was advised to create an algorithm which created a diamond pattern. After sketching out a plan and trying to work it out in my head, I went on to code out what I thought would make the correct mesh. To my amazement; it was spot on. The only issue was that I was only using a vertex buffer, which not only meant there was up to 8 vertices at any one point, but also, randomly offset vertices would result in a broken surface.
So I went about editing my code to include an index buffer, which to my despair meant recalculating my algorithm, however with the basic principles in mind, this wasn’t too hard and I soon managed to recreated the same grid:
Typical of feats for coders: I was so chuffed to have what to an onlooker would appear to be exactly the same as I had a few hours earlier.
I altered it slightly to make it more dynamic, it was initially only every square but I changed it to allow for rectangular lengths:
I altered it slightly to make it more dynamic, it was initially only every square but I changed it to allow for rectangular lengths:
Once I had a basic grid I needed to be able to fault the terrain. This was quickly done as I already had in my head how I wanted to do it: taking a gradient and a y intercept gives a variant line. I then set the vertex’s height based on which side of the line it was on. This was initially done when the vertex buffer was created, however I was tasked to try have the terrain dynamically regenerate and fault. This meant altering the vertex buffer to be dynamic.
The effect was relatively decent mountain range:
The effect was relatively decent mountain range:
As well as changing the vertex buffer (and with that the code so faulting took place with a function call), I added to the line generator by including a type of line, which would determine the comparison function used when changing a vertex’s height, as in it was either a straight line, a parabola or a cubic line as well as an x offset. This meant that the faults wouldn’t focus on a specific point as it initially had done, instead creating a more general terrain.
In addition, the curved lines would add more variation and make it more pseudo real.
As the above picture shows, the faulting algorithm favoured one side over another, knocking one side down while the other up. I changed this by making it even more random whether a side is knocked up or down.
These next pictures display the various effects, with the highlighted region being the vertexes that are knocked up while the others are knocked down:
In addition, the curved lines would add more variation and make it more pseudo real.
As the above picture shows, the faulting algorithm favoured one side over another, knocking one side down while the other up. I changed this by making it even more random whether a side is knocked up or down.
These next pictures display the various effects, with the highlighted region being the vertexes that are knocked up while the others are knocked down:
I changed the colouring vertices to make the terrain more believable. The lower vertices are coloured dark blue/black. This then expands into sand and grass (the colours based slightly on height giving a shaded effect). Until eventually, the terrain manages to produce mountains (with cheeky snow caps).
While I was happy with my creation an a first step in procedural programming, the randomness (or noise) that I was using was simply rand() (or white noise) which did a good job of creating pseudo random terrain, but it isn’t completely convincing as terrain.
For this, I began to look into Perlin noise.
Taking out the faulting, I began to try to implement Perlin noise into my application. My initial problem was one that I’m sure many veteran and indeed beginner procedural programmers will roll their eyes and shake their heads at: the input for the noise function I used were my vertex positions… which were set at 0.0f,1.0f,2.0f, etc.
Once I realised my mistake, I discovered how changing the value I scale my vertex input by would alter the ‘zoom’ for the noise and thus I made it possible to alter this real time. In addition I scaled the change in height so the noise could be made more or less prominent.
To start with, I used 2D Perlin noise as a height map:
For this, I began to look into Perlin noise.
Taking out the faulting, I began to try to implement Perlin noise into my application. My initial problem was one that I’m sure many veteran and indeed beginner procedural programmers will roll their eyes and shake their heads at: the input for the noise function I used were my vertex positions… which were set at 0.0f,1.0f,2.0f, etc.
Once I realised my mistake, I discovered how changing the value I scale my vertex input by would alter the ‘zoom’ for the noise and thus I made it possible to alter this real time. In addition I scaled the change in height so the noise could be made more or less prominent.
To start with, I used 2D Perlin noise as a height map:
I then went further and used 3D Perlin noise and had time as the value for the ‘slice’ from the 3D noise to choose and then use that slice as a height map. The effect was a smooth wave effect, which sadly can’t be displayed on here.
Inspired by Ken Perlin’s A Webwide World (makes my inner geek chuckle everytime): http://mrl.nyu.edu/~perlin/demox/Planet.html
I wanted to create a procedurally generated planet which re-evaluated itself when the camera moves towards/away from the planet giving the appearance of a genuine planet.
As well as the planet I wanted a bloom effect from the sun to give the impression of an eclipse as the camera pans into the shadow of the sun.
To start of with, I took a sphere generator which creates spheres from stacks and slices and added in world matrices so that I could translate and rotate them without affecting the local vertex coordinates.
I then had my application create two spheres, one acting as the sun/light source and the other as the planet that will have a procedurally generated texture.
I then created effect files, one that held the improved noise function (http://mrl.nyu.edu/~perlin/noise/), a ‘planet’ effect file which utilises the noise function and a ‘sun’ effect file which will be used for the HDR to make it appear bright.
This created a basic concept from which I can work from (excuse the horrible green, it was to double check anything that wasn’t rendering was definitely so and not just black):
Inspired by Ken Perlin’s A Webwide World (makes my inner geek chuckle everytime): http://mrl.nyu.edu/~perlin/demox/Planet.html
I wanted to create a procedurally generated planet which re-evaluated itself when the camera moves towards/away from the planet giving the appearance of a genuine planet.
As well as the planet I wanted a bloom effect from the sun to give the impression of an eclipse as the camera pans into the shadow of the sun.
To start of with, I took a sphere generator which creates spheres from stacks and slices and added in world matrices so that I could translate and rotate them without affecting the local vertex coordinates.
I then had my application create two spheres, one acting as the sun/light source and the other as the planet that will have a procedurally generated texture.
I then created effect files, one that held the improved noise function (http://mrl.nyu.edu/~perlin/noise/), a ‘planet’ effect file which utilises the noise function and a ‘sun’ effect file which will be used for the HDR to make it appear bright.
This created a basic concept from which I can work from (excuse the horrible green, it was to double check anything that wasn’t rendering was definitely so and not just black):
I’ve added a simple fBm function and clamped values to separate “land” from “ocean”. It currently uses branching so isn’t very efficient, but that will hopefully be rectified later once the project creates what is envisioned.
It’s currently a static noise too, so doesn’t alter based on camera position:
I’ve now implemented dynamic octaves based on distance from the planet (well technically the central point of orbit for the camera)
I changed the input value of the camera distance from a linear line to an inverse curve, this means that the octave variation will change at a slower rate the further you move from the planet and visa versa for when going towards it.
I also changed the colouring algorithm to eliminate the if statements, going from this:
if(H == 0){ //If water
outColor.y = 0.0f; //no green
outColor.z = 0.5f; //dark blue
}
else{ //land
outColor.y = H; //green (shaded based on turbulent value)
outColor.z = 0.0f;//no blue
}
outColor.x = 0.0f; //no red
to this:
outColor.x = 0.0f;
outColor.y = H;
outColor.z = 0.5f-0.5f*ceil(H);
Look, I can see an eagle with an impressive wingspan:
It’s currently a static noise too, so doesn’t alter based on camera position:
I’ve now implemented dynamic octaves based on distance from the planet (well technically the central point of orbit for the camera)
I changed the input value of the camera distance from a linear line to an inverse curve, this means that the octave variation will change at a slower rate the further you move from the planet and visa versa for when going towards it.
I also changed the colouring algorithm to eliminate the if statements, going from this:
if(H == 0){ //If water
outColor.y = 0.0f; //no green
outColor.z = 0.5f; //dark blue
}
else{ //land
outColor.y = H; //green (shaded based on turbulent value)
outColor.z = 0.0f;//no blue
}
outColor.x = 0.0f; //no red
to this:
outColor.x = 0.0f;
outColor.y = H;
outColor.z = 0.5f-0.5f*ceil(H);
Look, I can see an eagle with an impressive wingspan:
I’ve now added in different colours.
Again it was a quick throw up, using branching (and lots of it - one for each colour) and so I need to improve that. I also need to try and create a spline function which can interpolate between various points so that I can blend the colours a little better as they are currently very sharply separated.
I also altered the water to colour based on the fBm for the planet and then clamped it such that deeper regions are smoothed off.
This gives this effect:
Again it was a quick throw up, using branching (and lots of it - one for each colour) and so I need to improve that. I also need to try and create a spline function which can interpolate between various points so that I can blend the colours a little better as they are currently very sharply separated.
I also altered the water to colour based on the fBm for the planet and then clamped it such that deeper regions are smoothed off.
This gives this effect:
I took a step back to take a different route forward.
removing the blending (because I would be changing it later down the line anyway, to instead colour based on altitude) I have now implemented a simple directional light which will be the basis for the HDR I intend to implement.
I clamped the intensity (as, for my implementation, it ran [-1,1]) between [0,1]
This allowed me to then add in an ambient light (not realistic, but for viewing purposes it allows all the land to be viewed.
In the midst of procrastination, I have added in night lights, as in the ambient lighting given off from cityscapes currently on the dark side of the planet
To do this I created another fBm with a lower fractal increment which results in a noise result closer to white noise, I then clamp the value at a high amount to limit the amount of lights and then add these lights onto the colour based on 1 - the global light intensity, so that the lights only appear on the darker parts of the planet.
Creating another fBm was highly costly and, ironically, for optimisation, I created an if statement to limit when the shader creates a new fBm, which results in it running smoother when looking at the parts of the planet that are in sun.
I also added in a basic specular highlight to the model to accentuate the reflective nature of the sea against the land.
To make the traversal of the planet easier (and to show the aesthetic advantages) I included an optimise toggle which switches between different pixel shaders, one which contains all the additional visual improvements, and one which contains just the basic land, sea separation with the basic lighting.
Here is a picture of the night lights:
removing the blending (because I would be changing it later down the line anyway, to instead colour based on altitude) I have now implemented a simple directional light which will be the basis for the HDR I intend to implement.
I clamped the intensity (as, for my implementation, it ran [-1,1]) between [0,1]
This allowed me to then add in an ambient light (not realistic, but for viewing purposes it allows all the land to be viewed.
In the midst of procrastination, I have added in night lights, as in the ambient lighting given off from cityscapes currently on the dark side of the planet
To do this I created another fBm with a lower fractal increment which results in a noise result closer to white noise, I then clamp the value at a high amount to limit the amount of lights and then add these lights onto the colour based on 1 - the global light intensity, so that the lights only appear on the darker parts of the planet.
Creating another fBm was highly costly and, ironically, for optimisation, I created an if statement to limit when the shader creates a new fBm, which results in it running smoother when looking at the parts of the planet that are in sun.
I also added in a basic specular highlight to the model to accentuate the reflective nature of the sea against the land.
To make the traversal of the planet easier (and to show the aesthetic advantages) I included an optimise toggle which switches between different pixel shaders, one which contains all the additional visual improvements, and one which contains just the basic land, sea separation with the basic lighting.
Here is a picture of the night lights:
Still in procrastination mode: Added clouds.
Messing around with various methods, the cheapest and most passable are ones which reuse the fBm that created the planet.
This means that the clouds very crudely follow the land and oceans, however for the current objective, it does a good enough job. If I was to concentrate more on it, I’d create a separate cloud mesh which generated a more believable cloud texture, taking into account vortexes etc.
The main issue with the clouds (due to them following the land and oceans) is that it cancels out the shallow water effect - it’s not as noticeable. So I made the decision to just cut that effect from the application as the clouds create a more realistic planet than the shallow waters do:
Messing around with various methods, the cheapest and most passable are ones which reuse the fBm that created the planet.
This means that the clouds very crudely follow the land and oceans, however for the current objective, it does a good enough job. If I was to concentrate more on it, I’d create a separate cloud mesh which generated a more believable cloud texture, taking into account vortexes etc.
The main issue with the clouds (due to them following the land and oceans) is that it cancels out the shallow water effect - it’s not as noticeable. So I made the decision to just cut that effect from the application as the clouds create a more realistic planet than the shallow waters do:
Ok, so I couldn’t help but continue making my world pretty, but this is the last touch up before I finally delve into the post-processing that I’ve been avoiding so avidly.
I managed to get the Phone specular highlight to work for my planet, meaning there’s a dynamic reflection of the sun’s light on the world as you orbit it. Which leads to a lovely ecliptic effect ready for the HDR effect.
I managed to get the Phone specular highlight to work for my planet, meaning there’s a dynamic reflection of the sun’s light on the world as you orbit it. Which leads to a lovely ecliptic effect ready for the HDR effect.
Twas quite a rocky road to getting my application to the point where it can render to a buffer of my choice, and then pass that render through another shader.
Therefore I’m at the point where there is technically some post-processing; a simple grey scale filter.
It actually looks pretty good, in my opinion, in grey scale.
It’s not ground breaking, but it is certainly a big step towards getting the desired bloom effect.
Therefore I’m at the point where there is technically some post-processing; a simple grey scale filter.
It actually looks pretty good, in my opinion, in grey scale.
It’s not ground breaking, but it is certainly a big step towards getting the desired bloom effect.
Done.
Or at the very least, I have the application I set out to create for my coursework. There’s still a vast amount of room for improvement.
but here’s a screen shot of the planet will bloom. Note the cheeky bloom glinting off the sea:
Or at the very least, I have the application I set out to create for my coursework. There’s still a vast amount of room for improvement.
but here’s a screen shot of the planet will bloom. Note the cheeky bloom glinting off the sea:
Possible improvements that I could pursue at my leisure are:
- Improving the framerate.
My application performs all the features I want, but there’s plenty of room for optimisation.
- Adding distortion to the clouds so they appear more realistic.
I could have vortex forces that distort the clouds in a natural appearing manner.
- Changing the bloom to include HDR
The current bloom, just uses the brightest pixels with a small acceptance margin for the
bright pass. This means that the bloom is limited to small values, as larger values will blur the light so much that it fades to nothing, hence why there’s only a small corona around the sun. Using a HDR, this would be alot more exaggerated as the sun’s value would be much higher, creating a more believable effect, including a better eclipse.
- Making a more believable landscape
I could colour the land based on altitude, as I had previously planned.
I could also add in bump mapping, altering the normal of the texel based on the noise value it gets from the fBm.
The night lights are a nice addition, but I could further the believability by adding in other random features, such as thunder storms: Having lights similar to the cities flashing randomly around the most prominent clouds.
- Improving the framerate.
My application performs all the features I want, but there’s plenty of room for optimisation.
- Adding distortion to the clouds so they appear more realistic.
I could have vortex forces that distort the clouds in a natural appearing manner.
- Changing the bloom to include HDR
The current bloom, just uses the brightest pixels with a small acceptance margin for the
bright pass. This means that the bloom is limited to small values, as larger values will blur the light so much that it fades to nothing, hence why there’s only a small corona around the sun. Using a HDR, this would be alot more exaggerated as the sun’s value would be much higher, creating a more believable effect, including a better eclipse.
- Making a more believable landscape
I could colour the land based on altitude, as I had previously planned.
I could also add in bump mapping, altering the normal of the texel based on the noise value it gets from the fBm.
The night lights are a nice addition, but I could further the believability by adding in other random features, such as thunder storms: Having lights similar to the cities flashing randomly around the most prominent clouds.