Posts In:

Real-Time Morphing of Dynamic Procedural Terrain

This is just plain cool.  Instead of approaching terrains by creating a set of vertices based on heightmap data and shoving them through a draw call, why not let the GPU do the work?

When I asked Victor Porof how he achieved such fantastic speeds in his procedural terrain video, he explained that, instead of actual translating heightmaps to vertex data on the CPU, he was using a vertex shader to displace the vertices dynamically based on the loaded heightmap texture.  The implications of this?  Any changes to the heightmap could be immediately visualized with no hiccups and no load on the CPU.

Now, at first I thought "WHAT!? You can't do texture lookups in vertex shaders!!"  Thankfully, I was wrong!  Vertex Shader Model 3.0 and above supports VTF (Vertex Texture Fetch), which allows texture lookups within the vertex shader.  I yelped with joy when I learned this.

At first, I implemented the method using just a static heightmap to observe the performance difference.  Indeed, the method is fast.  More importantly, however, it's possible to generate new terrains very, very quickly thanks to the immediate response from the GPU and the lack of CPU workload.  How quickly, you ask?  I decided to find out.

After modifying the Perlin multifractal shader code to add some continuity (i.e. make the noise function less sensitive to seed such that adding .0001f would only make a small change to the overall terrain), I threw in some code to increment the seed and update the heightmap every frame.  The results?  Unreal.  I had before me a dynamic, morphing terrain based off of a complex Perlin multifractal shader running at roughly 70 fps.  It looked really, really cool.

Let's take a moment to reflect on the implications of such speed.  The ability to generate new heightmaps at 70fps means that, really, we can generate 70 completely unique terrains in one second (by simply setting the noise function back to normal, where a tiny change in seed value gives you a completely new terrain).  Now, I'll be the first to admit, Perlin multifractal isn't enough for a beautiful terrain by itself.  But, theoretically, I could generate a terrain of 70x the complexity, as far as shader instructions are concerned, and still only require roughly one second per terrain.

If those numbers don't really sink in, I'll put it this way: beautiful, complex, procedural planets are looking really feasible.  In fact, at those speeds, I don't think it would even be necessary to save assets to the HD when exiting from the virtual world...you could just recreate all of the procedural assets (or at least the terrain) at runtime.  Incredible!

Unfortunately, I don't have any screenshots of this epic triumph, since they really wouldn't show the action.  If I can dig up Camtasia sometime this week, I'll try to upload a video so I will always be able to remember the day that I learned how to create 70 unique terrains per second!

Terraced Multifractals

Yes, it's official, I'm now severely addicted to HLSL. The raw power that it opens up for Project: A New Reality is simply mind-blowing. Experimentation with all sorts of random ideas has led to some pretty cool-looking terrains, though I'm going to spare the blog from any further screenshot explosions until I have something really draw-dropping.

Here's an interesting example of a neat heightmap shader. The algorithm is as follows:

  1. Generate a Perlin Multifractal [1]
  2. Generate a Perlin Multifractal [2]
  3. Reduce the bit depth of (1) by using the function y = a * floor(y/a), where a is the number of discrete levels to allow [3]
  4. Generate a final heightmap by blending [1] and [3] with [2] as the blending function

Basically, that's a complicated way of saying take a heightmap, force it into discrete levels, then blend it back on itself with another fractal function.  This way, natural-looking terraces appear but blend smoothly back into the terrain.

This example heightmap is a little too aggressive with the terraces, but that can, of course, be easily modified by fooling with the blending function.