Tuesday, August 13, 2013

Let's Talk About Planets


It's been a while since I've posted anything, but I certainly have not been idle.  In fact, the reason I haven't posted anything is because I have been so busy!  Usually I get an hour or two every night when I'm back from work/gym to work on this project, and writing blog posts is time consuming.  So usually I get coding instead of blogging, but I don't want to neglect this thing too much.

Sit back, this'll be a long one.

Up until recently, all of my terrestrial planets have been featureless, uniform spheres.  You could land on them, but you couldn't really go sightseeing.  Not so anymore.

I've always been a fan of building up concepts from the bottom, so if we're going to talk about planets the first thing we need to talk about is spherical quadtrees.  Each planet has six faces, which we'll call 'front', 'back', 'left', 'right', 'up', and 'down'.  Initially, each one of these faces is a flat grid of 32x32 vertices.  But planets are not square, so by normalizing the position vector of each vertex we end up with a unit sphere.  Moving these vertices along their normals by the equitorial radius gives us a sphere the size of the planet.

Each of these faces is the root node of a quad tree.  Each quad tree is capable of dynamically subdiving to provide higher levels of detail.  The reasons for this being necessary should be obvious, but I will state them anyway: it would require gigabytes of memory to store all of the vertices necessary to render a planet at a meaningful resolution (say, 5 meters between vertices).  Also, the majority of this fidelity cannot be appreciated when it is on a distant mountain, or from a ship looking down from orbit.  This method reduces the load on the GPU considerably, and consumes much less uncessary memory.

Every level down on the tree covers one quarter of the area of the parent, meaning we can represent more detail with the same group of 1024 vertices.  These subdivision continues until we reach a desired level of fidelity (based on a certain distance between vertices), at which point the node becomes a leaf.  Terrain leaves have collision meshes, and can be stood on.  In order to minimize physics complexity, only active pages (with objects directly above them) and their immediate neighbors have collision meshes.

The SphericalQuadTree class features a series of utilities for finding neighboring tiles given a direction of movement.  These utilities use a series of lookup tables to find the appropriate neighbor, and they even work across the "face" border.  Constructing these lookup tables took a while, and in order to get it right I actually had to make a paper cube that represented the 6 faces of the planet and label it.

With that stuff out of the way, we can talk about terrain generation.

Every planet has a terrain type and a seed value.  From there, we can generate the terrain for the entire planet.  This is done with an interface called the Landscaper, which has several different subclasses for different terrain types.  Every time a new vertex is created in a terrain page it calls a method on the Landscaper and then adds that to the equitorial radius, moving it up or pushing it down.

To do all of the generating I am using libnoise, an awesome open-source coherent noise generation library.

The first important thing to realize is that when I say "type" I don't mean things like plains and mountains.  The terrain type defines what type of planet it is.  Currently I am working on the simplest, called "Barren", to figure out what works and what doesn't.  After that is done, I will implement the others using the techniques from Barren.

Here's an example of what I've got so far (with vertices colored based on altitude):





And here are the currently-planned terrain types:

Barren

These planets are geologically dead (if they were ever very active at all).  Picture these planets looking a lot like the Moon.  They'll usually have rough mountainous areas and relatively flat maria produced by lava flows.  These types of planets will never have an atmosphere, and because of this will usually be heavily cratered.

Irregular

These aren't really planets so much as large captured asteroids.  Mimas is an example of what I'm going for here: a large, oddly shaped ball of rock.  Most of the geological features here will be cracks and craters in the surface.

Magmatic

"Lava" planets are generally young planets which haven't cooled down after their formation.  The Earth was probably like this for the first few million years of its existence.  The surface of these planets mostly appears to be "continents" of cooled magma seperated by gaping fissues of red.  Glowing rivers of lava can be easily seen from orbit.  These planets may or may not have an atmosphere, which would mostly be sulfur and other products of volcanic activity.

Ice

On the exact opposite end of the spectrum are ice planets.  Enceladus and Europa are great examples of these types of planets.  These planets will feature hilly white wastes, sprinkled with craters.  Enceladus also has interesting fractures on the surface caused by tidal stresses from the primary.  Some researchers suggest that Europa may have a sub-surface ocean.  I'm not sure if I'll be able to do something like this, but it could theoretically be modeled with some kind of terrain shell (I will have to think about this).  These planets may or may not have atmospheres.

Martian

I couldn't think of a great name for these, but basically they are relatively-habitable planets with terrain that was shaped by things like wind, dust storms, and glacier movement.  Rivers may appear on these planets, though the liquid is long gone.

Terran

Finally, the gems of the galaxy.  These are what the players are really hunting for if they want their best chance at survival.  These planets are much like Earth, with diverse geological regions and liquid water.  This will be the most difficult terrain generator to implement, and most likely the slowest because of the large number of noise modules needed to generate interesting terrain.

One of the things I want to add on to the basic terrain generation is the placement of monolothic features such as cataclysmic craters and giant mountains a la Olympus Mons.  I'm not sure how I can integrate this with the noise modules, but I will probably have to end up extending libnoise in order to do it.

Also, I mentioned atmospheres in several posts above.  I have a very rudimentary framework in place for atmospheres, but currently they are not actually implemented.  In terms of their actual generation, I'll save that for another post when I actually have something concrete done for it.

Once the actual generation of the physical terrain is complete, I'll be moving on to coloring them.  I have been thinking a lot about how to accomplish the texturing itself.  The planet terrain has a unique vertex class and its own set of pixel and vertex shaders, so I have a lot of freedom to try any methods I want without altering how anything else in the engine is rendered.

One of the first ideas to cross my mind was to do it all procedurally on the GPU, but I quickly decided that it would be too difficult to produce realistic results with only the data available to the GPU.

The idea I am leaning most heavily towards involves several steps.  I won't go into much detail until I actually have something implemented, but here is a rough overview.  First, we take the output of the noise modules determining things like terrian type and "biome" type.  Next, we also need to take into account the angle between the surface normal and the up-vector at that location on the planet (because this changes, the planet is round!) so that we don't get things like grass growing on the side of a cliff.  Once we have some information about the type of ground this vertex represents, we can blend together a palette of available ground textures to get the desired result.

Hopefully soon I'll have some more progress pictures for the different planet types (without textures).  Until then, onward and upward.

Tuesday, March 26, 2013

Starfield Builder (Iteration 2)

As part of the directx 11 port, I've finally revisited the starfield generator.  There isn't much new in this version, as it was mostly just porting dx9 to 11, but it finally draws textures on the quads for the stars, and colorizes them to match the actual star color.


The colors are very subtle, but still noticeable.  I'd rather have them that way, to be honest, instead of being obnoxiously in-your-face.

A simple re-write, but the results look much better!

Thursday, March 14, 2013

Ring Systems (Part 1)

I think it's pretty safe to say that Saturn's rings are one of the coolest things in the solar system (or at least one of the prettiest).  I've been wanting to give more love to rings for a while.  When I originally implemented them I was having quite a bit of stenciling problems (zbuffering doesn't work at these scales), and dropped them after I got them barely rendering.  Now that I've been slowly rebuilding every part of the engine to work with DirectX 11 I've come back around to gas giants.  Instead of doing the jovian shader immediately, I decided I really wanted to get rings right first (rationalizing to myself that they applied to all types of planets, and was thus a bigger step than just one specific type).

 The formation of ring systems isn't well understood, so I had to take a somewhat less-than-scientific approach to generating my own.  To over-simplify it, rings are basically a collection of particles inside of a planet's Roche Limit, meaning that the gravity of the primary is too strong inside that limit to allow them to coalesce into a planet.  I did a bit of reading on what we know about Saturn's rings and tried to nail down a way that they could be generated programmatically.  For a first iteration, I'm pleased with the results.

Structure


The Voyager probes were the first to discover that Saturn's rings were more complex than just the two main rings we could make out at our distance.  In reality, they are comprised of hundreds of thousands of tiny ringlets.  It's generally theorized that the structure of ring systems is closely tied to the moons orbiting the planet that hosts the rings.  The interaction of the gravity of the moons and planet with the ring particles creates "divisions" in the rings.  Moons that produce this effect are called "shepherd moons". 

To create the major structures I'm using a Weibull distribution modified by a portion of the number of moons the planet has.  There is a minimum value, so there is still some variety even if the planet has no moons.  "Major structures" includes rings and divisions.  By taking the modulus of the iterator in each loop I can alternate between divisions and rings.  An Inverse Gamma distribution is used to determine structure thickness, with the scale argument for divisions being smaller than rings.  Each structure is then written to the texture, with the alpha value varied using Perlin Noise to keep them from appearing as one solid color.

Here are some examples (each ring is given a random color to make them distinct during development):

Rainbow Rings!



There will be more on composition in a minute, but for now just know that each ring will have a general color.  To break up that homogeneity I added "minor structures", which are a randomly generated number of 1-texel wide rings roughly uniformly distributed throughout the major rings to add some flair.  Right now they're just green to make them stand out:



Composition & Color


Saturn's rings are comprised primarily of water-ice, with fragments of rock, dust, and minerals providing most of the color.  Right now all of the colors seen here are only for testing purposes.  Even though they look awesome, I don't want clown planets sprinkled around the galaxy.

This won't be implemented until much later, but the appearance of rings will eventually be determined by the composition of the planet they orbit.  The reason this feature is on hold for a while is because I have yet to figure out a good way to smear elements around the solar system with interesting distribution.  Before I can determine which elements will be present in the rings (and thus, which colors) I will need to determine the composition of the planet.

In general, lighter elements tend to be pushed into the outer solar system during stellar ignition (which is why all our outer planets are gas giants).  This is because when a star finally ignites the sudden burst of solar wind pushes the lighter elements away faster, leaving the silicates and heavy elements to form rocky planets.

Once I've finally managed to determine the composition of the planet I can take that and color the rings.  Right now I'm thinking that the more abundant materials of the planet will form the major rings, and the rarer and often brighter elements will provide the hint of variety in the minor rings.

Other Cool Stuff (in the future)


Eventually, I'll need to give the rings some real mass so that when you fly through them you don't realize it's really just a textured triangle ring.  Saturn's rings are made of particles ranging from a few centimeters to ten or more meters.  In terms of thickness, they range from a few meters to almost a kilometer.  In order to get this thickness, the shader will have to do a few things.  The first will be to fade away the texture nearest to the camera so there is a hole (in much the same way that you can't see the fog closest to you).  In order to fill that hole in the texture, I'll have to render dust specks in the field of view.  For more substantial particles, I haven't made up my mind on how to implement those.  Creating unique geometry on the fly for dozen or even hundreds of meter-sized asteroids seems like it would be a strain, even using geometry shaders.  Voxels may be the answer here, but I haven't yet implemented a sparse oct-tree renderer as it would be quite a task.

But I can dream.