Archive

Posts Tagged ‘Procedural Landscapes’

In Deep Water

(Originally Written on Thursday, May 15, 2008)

As my current area of focus is the water effect, I thought a brief synopsis of how it works would be a good exercise; there are several inputs to the water effect, some read by just the pixel shader and some by both the vertex and pixel shader. There is no geometry shader involvement at the moment. The inputs are:

  • Water Depth Texture: This is a 2048×2048 8bit texture that stores how far below the water plane each point on the terrain is. Zero indicates sea level (or above) while 255 indicates a depth of 200m or so below sealevel. Anything deeper than this is clamped as the effect does not change for deeper water – one experiment is to try reducing this to a 1024×1024 to see if the effect remains of acceptable quality.
  • Surface Heightfield Texture: This is a 64×64 three channel floating point texture storing the height of the water waves along with X and Z peturbations to make them more ‘choppy’ – this texture is generated each frame on the CPU using a three pass fast fourier transform to move samples from a Phillips spectra from the frequency domain to the spacial one. The code is half based on the Tessendorf SIGGRAPH paper (which appears to be the defacto deep water rendering paper) but also pieced together from various demos I found on the net. I lack the maths skills to work entirely from the paper and besides, why re-invent the wheel. I would like a better understanding of the code though so I can optimise it further, possible even putting parts such as the FFT into a shader to get the GPU to help.
  • Reflection Texture: Rendered at half the screen resolution, the reflection texture is rendered separately before the rest of the world using alternative shaders that mirror the geometry across the water plane. The decision to use separate shaders rather than building the mirror into the transform was so that cheaper versions of the shaders could be used for speed. Once it’s rendered, it’s then blurred into a separate 1/4 x 1/8 screen size texture using a pixel shader to make the reflections less pixelated and generally look better.
  • Refraction Texture: Rather than render a separate refraction texture, a copy of the main back buffer is made after rendering the scene but before the water is rendered. Although this includes geometry above sea level which it shouldn’t really, in practice the effect works fine none the less. If this did become a problem it may be possible to employ the stencil buffer to mask off rendered pixels above the water line (I believe Crysis does this)
  • Foam Texture: A 512×512 8bit greyscale texture generated procedurally during program startup using fractal brownian motion, the foam texture is blended in by the pixel shader to provide wave crest highlights and shore foam where the water meets the land.
  • Z-Depth Texture: A screen-sized single channel floating point texture used as a secondary render target during rendering of the rest of the scene to store screen Z depth values. Although DX10 can use the Z buffer as an input, you cannot use it as both an input and an output at the same time limiting it’s usefulness in this mode. Instead I opted for a more conventional approach rendering a separate depth image that I felt could be of use for other effects later (depth of field? SSAO?).

The vertex shader reads from the surface heightfield texture to deform the vertices of a fairly simple radial mesh grid centred around the camera. The spacing of the grid vertices increases as the mesh extends away from the camera giving a more uniform triangle size when perspective is applied during rendering. The vertex shader also reads from the water depth texture to scale the wave amplitude so the closer to shore you are the smaller the waves. A potential experiment here is to also scale the frequency of the waves although this might introduce too many warping artifacts into the texture co-ordinates.

Most of the work is done in the fairly meaty pixel shader however, which also samples the 64×64 water surface texture but this time takes three samples of two octaves each so it can work out an approximate surface normal at that point. It also reads from the water depth texture to generate a basic water colour and to modulate alpha and uses the fresnel term to blend between the reflection and refraction textures. The sampling method is basically the same for both of these; for reflection the surface normal is projected onto a plane slightly above the sea and this displaced point projected back into screen space to get the point to read from the reflection texture while for refraction the plane is slightly below the sea and it’s the refraction ray (using a air->water refractive index of 1.33) that is projected.

The foam texture is blended in to the wave tops to help simulate the effect of breaking water and is also blended in where the water depth is shallow to produce shoals; the intensity read from the foam texture is animated to ping-pong back and forwards between zero and one to add more movement to the water.

The Z-depth texture is used for two purposes here, foam texture is blended in again but at a higher frequency where the water Z-depth is close to the previously rendered Z-depth to produce foam around the shoreline and it’s also used to vary the alpha of the water where it meets other geometry producing a far more satisfying soft edge to the water (similar to depth sprites) rather than the normal hard Z-buffer intersection. These are especially satisfying as they operate purely on the Z-depths so occur wherever anything penetrates the water not just at the shore so boats, floating debris, rocks or whatever all get foam and nice soft edges.

Finally diffuse lighting is applied and everything munged together to get the final result. One final ‘bodge’ is an artificial strengthening of the fresnel reflection in a cone pointing towards the sun; this is done to produce a reflection of the sun disc in the water replacing the need for normal specular – I found that using normal specular resulted in unsightly artifacts when the sun was low in the horizon that made it clear the specular was treating the sun as a point instead of an area. HDR would make it even better simulating glints on the water in the sun cone.

So now about the problems: The effect is best at the moment for deep water such as the ocean around the island, but it doesn’t work quite so well for shallow smaller areas such as ponds and smaller lakes as the waves just don’t look right for small water bodies. Either I need to play with the shaders and parameters to try to make them adjust their behaviour in these cases or I’m going to have to identify smaller bodies and render them separately using a different effect.

Other problems at the moment include a deterioration in effect quality when very close to the water plane and a complete breakdown when you go underwater – the latter at least is simply because I’ve not done any handling code for this; the plan is to bring the far clip plane in, increase fog, flip the reflection and refraction texture rendering to take account of being under the water and add some full screen ‘wibble’ effect. Another missing piece is the lack of caustics on the sea floor underwater – these could be done with an animated texture blended in based on water depth – beams of light underwater would also be cool.

Overall though I’m pretty happy with the effect so far, especially as it still adheres to my goal of producing entirely procedural effects – there are no textures loaded from disc, everything is generated.

Welcome to Isis Island

May 20, 2010 1 comment

(Originally Written on Wednesday, May 14, 2008)

I’ve started this journal to diarise some of the projects that I work on in my spare time to amuse myself and gain exposure to and experience of various game related technologies. Although I spend my days working as a software developer/architect, my day job rarely coincides with what I would regard as more ‘fun’ technologies so I have side projects I do in my own time where I can work on whatever I like without the pressure of actual deliverables.

So what is the first project? Well the first one I am floating here is ‘Isis’ who, according to the Book of the Dead is “She who gives birth to heaven and earth” – an apt title I feel for what I hope will grow into a fully functioning procedurally generated world…or in the spirit of walking before running at least a single Island.

The main technologies that I have experimented with in this project so far are:

  • DirectX 10 – I had never used before but now have at least a working understanding of. Microsoft redesigned the API significantly between DX9 and this version to make it a better fit for modern hardware (a move I agree with entirely) but it does mean a little re-learning is involved in making it work. Relying on DX10 does mean that Isis will only run on a capable graphics card and only on Vista, but as it’s purely a research project and my machines both at home and at work meet this requirement it’s not a problem.
  • Clip Maps – As an experiment I’ve decided to store both the height field and the primary diffuse texture for the landscape of my world using single very large textures and employ the ‘ClipMap’ algorithm to enable these large textures to be rendered. Clipmaps store a stack of textures arranged concentrically around a point where each level of the stack stores an area twice the size of the previous one but at half the detail. During rendering the pixel shader calculates which clip map level to read from for the pixel being rendered using a combination of distance and screen space texture derivatives. At the moment the height field is a 128K^2 texture and the diffuse a 512K^2 one.
  • Noise and Fractals – Although I’ve worked with noise functions before, this project places more demands on fractals than any I’ve undertaken previously. I’m using both absolute and differential 3D noise functions, turbulence functions and fractal brownian motion (fBm) all of which should be useful. fBm in particular has many uses for natural phenomenon simulation such as clouds.
  • Atmospheric Scattering – The underlying sky colour in Isis is based in part on the “Atmospheric Scattering” work presented by Sean O’Neil in the book “GPU Gems 2″. Part of the sky vertex and pixel shader code is adapted from his original source complemented by further processing of my own to add some simple clouds and horizon haze.
  • Deep Water – An implementation of the apparently defacto Tessendorf paper, I use fast fourier transforms to drive the wave simulation to simulate deep water waves and combine in reflection, refraction, fresnel, depth attenuation, crest and shore foam to produce the final effect. The water effect is currently my focal area as I am working on adapting it into an effect that can scale smoothly from large deep water areas to smaller localised lakes and pools.

Anyway enough rambling, here are some screenshots from the current version so you can see what I’m on about. It’s a long way from where I ultimately want to be but I’m reasonably happy with the progress so far.



There are of course many directions I would like to progress Isis further, but some of the ones most interesting to me at the moment are:

  • Rivers – Flowing water ranging from slow moving wide rivers to turbulent streams
  • World management – not a graphical effect but a data structure whos efficiency will be absolutely key to achieving any decent level of performance as things are added to the world. Some form of octree most likely.
  • Trees – Adding trees to the landscape will both increase the level of realism and add visual interest but also add a sense of scale to the hills and valleys as the inherent fractal nature of the height field makes it otherwise hard to tell actual size. Rather than use pre-built models I want to use procedural methods to create a number of tree types during startup which are then used to populate the world according to heuristics. The vertex shader will dynamically modify the vertices at render time to simulate wind.
  • Volumetric Clouds – Although there is a base layer of clouds in the sky currently implemented as a simple texture, the plan is to add volumetric clouds rendered most probably via a system of lit sprites or per-frame generated imposters. Being able to fly through the clouds will be a requirement of this system.
  • Fauna – animals, fish, birds, something to help bring the place to life.
  • Civilisation – To truly add interest to the environment the plan is to add a ‘civilisation’ system that generates a whole network of communities and social infrastructure within and around the natural features of the landscape.
  • Buildings – People of course need a place to live, so creating hamlets, villages, towns and even cities is desired. Initially these will be constructed from pre-loaded models but ultimately it would be interesting to see how far down this route I can get with just procedural methods. Sensible placement and sizing of the settlements is one of the challenges.
  • Tracks and Roads – To move about on, tracks, paths and roads that connect settlements are desired.
  • Bridges and Tunnels – Where tracks and roads cross valleys and rivers bridges and tunnels should be created. The burrowing of tunnels into the hillside is a significant challenge for the rendering and collision system.
  • Weather – rain, snow, storms, the usual things.
  • Vehicles – to move around the world in rather than just flying. A ‘walk’ mode would be a good start to help demonstrate how large the place is.
  • HDR and Lighting – bloom, tone mapping, motion blur and other post processing effects to give the visuals some of that professional polish
  • Better Texture Management – a more flexible ‘megatexture’ on-demand texture upload system rather than the limited clipmap algorithm

Okay enough for now, I’ll post more as I go.

Procedural News

May 20, 2010 1 comment

Just a short post to point out that Eric Bruneton has uploaded videos of some of his impressive work to YouTube:

http://www.youtube.com/user/ebruneton

It’s a testament to the quality of his work that “Rama” is still hypnotically impressive even after all these years.

Eric’s website can also be found here:

http://evasion.inrialpes.fr/~Eric.Bruneton/