Deep Sky Objects

By
Dave
Project
Published
19 Feb 2010 23:10
Last Modified
13 Jan 2013 17:55

I've started looking into adding some deep sky objects such as star clusters and galaxies, and have been thinking about the following:

  1. Loading the data.
  2. Sprite markers for the position, size and type of deep sky object.
  3. Rendering a text label at the appropriate position and scale.

Loading Data

Once again there is plenty of data available in the public domain. I found some basic lists of objects to get me started, converted the data to XML and used the automatic content serialization in XNA Game Studio 3.1 to compress the XML to an XNB file, as per my Background Stars.

Sprite Markers

Adding sprites in the appropriate positions was relatively straightforward. In order to specify the size of the object, I created a custom VertexElement structure, VertexPositionColorSize, which let me set a VertexBuffer with all the data the shader needed to position, color and scale the sprite.

Rendering Text

The labels were more interesting in that there were several options. I had the following requirements:

  1. I wanted the labels to render efficiently, as there may be many instances visible at once.
  2. I was considering scaling the labels as a size/proximity dimension.
  3. I didn't need to use the depth buffer since these labels would always be at the "back".

With these requirements in mind, the following approaches were apparent:

  1. Use SpriteBatch.DrawString() with SpriteFonts.
  2. Using line primitives to render vector-based fonts.

The SpriteBatch approach is shown below in Figure 1. While not ideal for scaling labels to large sizes (the fonts are drawn as scaled bitmaps), the approach proved surprisingly performant.

Deep Sky Objects

Figure 1. Deep Sky Objects from Messier Catalog with SpriteBatch text

It is possible to extract vector definitions from the "Modern", "Roman", and "Script" Windows Fonts. I took the approach of pre-generating the line primitives for a given label at load time and passing them to the shader with a given scale and offset per frame. This proved slightly more performant than the SpriteBatch approach, and provided a good option for scaling the text to large sizes without occluding any objects in the background. Examples are shown in Figures 2 - 4.

Deep Sky Objects

Figure 2. Globular and Open Clusters with scaled PointSprites and Vector Fonts

Deep Sky Objects

Figure 3. Globular Clusters with Right Ascension, Declination Grid

Deep Sky Objects

Figure 4. Globular and Open Clusters with Background Stars and Earth

Note that the Deep Sky Objects are shown at an exaggerated scale for clarity, and without anti-aliasing.

HDR Effects

By
Dave
Project
Published
9 Feb 2010 22:02
Last Modified
13 Jan 2013 17:54

One of the things I needed to start thinking about sooner or later was supporting High Dynamic Range (HDR) render targets, initially for the following reasons:

  1. I wanted to use a realistic bloom effect for the sun, without affecting other rendered planetary bodies.
  2. Atmospheric scattering algorithms lead to a wide range of luminance values.
  3. Background stars span a wide range of luminance values.

The use of HDR in combination with Tone Mapping to normalise luminance values into a standard render target would allow me to deal with each of these issues. This post will focus on the just the first issue of rendering the sun.

Non-HDR Approach

There are a number of approaches to rendering bright objects. One example is the lens flare sample on the XNA Creators Club site, which uses occlusion queries on the GPU to render glow and flare sprites when the sun is visible. Figure 1 shows the use of this technique.

Occlusion Queries Sprites

Figure 1. Non-HDR Sun effect using Occlusion Queries with Glow and Flare Sprites

HDR Approach

Another approach to rendering bright objects is based on image post-processing. The bloom sample on the XNA Creators Club is a good model for implementing bloom post-processing effects, along with additional control over color saturation. I combined this approach with an HDR render target (I used SurfaceFormat.HalfVector4), and added some HDR-textured spheres to represent bright lights. I rendered my scene as per normal and, using a post-processing bright-pass filter, extracted pixels for which the color range fell outside of the normal (0-1) range. I then used several passes of a Gaussian blur filter to create "star" and "bloom" effects and combined this with the original image, as shown in Figure 2.

HDR Test

Figure 2. HDR Post-Processing Test. Note that the "lights" are not being used in any lighting calculation for the central "planet" (a simple ambient value is applied to its texture), since this test was simply to demonstrate post-processing effects.

I then applied this post-processing approach as an alternative method to rendering the sun, as shown in Figure 3 below.

HDR Post-Processing

Figure 3. Sun effect HDR Post-Processing effects

Combinations of both approaches can also be used, as per Figure 4 below.

HDR Post-Processing and Occlusion Queries Sprites

Figure 4. Sun effect using both HDR Post-Processing and Occlusion Query Sprites

Using HDR render targets is an expensive process, even for many current GPUs. However, it has a number of advantages over the Occlusion Query approach, such as:

  1. Rendering one or many HDR-textured items in a post-processing pixel shader has the same GPU cost, unlike running multiple occlusion queries.
  2. Since post-processing effects are pixel-based, this approach leads to more realistic results when HDR-textured items are partially occluded.

Planetary Body Shader Part 2

By
Dave
Project
Published
9 Feb 2010 19:30
Last Modified
13 Jan 2013 17:56

In Part 1 I showed some screenshots of a planet rendered using multiple effects. I'll discuss each of these in turn, and begin with a composite image to show how each effect contributes to the overall image.

Earth Shader Composite

Figure 1. Composite image showing per-pixel, single-direction lighting (top left), addition of bump-mapping and specular (Phong) reflection (top right), addition of atmospheric scattering (bottom left), and addition of clouds and cloud shadows (bottom right).

The first thing I needed to do was create a model. I could have used a predefined sphere, but chose instead to generate the mesh algorithmically so that I could easily control the number of vertices.

Texture

Once I had a model, the first thing I needed to do was to apply a texture. NASA has an extensive image library, and the Visible Earth site has a collection of land maps for Earth. These maps are Equidistant Cylindrical projections, so my texture coordinates were simply:

x = λ
y = θ

where

λ = longitude,
θ = latitude

Lighting

The Shader Series on the XNA Creators Club site is a great introduction to lighting. My initial lighting model was a simple per-pixel shader, with a single directional light source from the sun. I subsequently added specular reflection using a Phong shading algorithm.

Relief

In order to show surface features without significantly increasing the number of vertices in the planet model, bump (normal) mapping can be used. There are numerous sources of normal maps on the Internet, available in various formats (I'm using DDS), and a good sample of how to implement normal mapping in a shader can be found on the XNA Creators Club site.

Atmospheres

There are many discussions on the subject of atmospheric scattering, many of which reference the work by Nishita et al. The article "Accurate Atmospheric Scattering", GPU Gems 2, Chapter 16 by Sean O'Neil served as a good starting point and is available here.

Clouds

The Visible Earth site also has a collection of cloud maps. This texture is then rendered on another sphere model above the surface of the planet.

Shadows

It was an important effect to cast shadows from the clouds onto the surface, particularly toward the terminator where the shadows are longer and not directly below the clouds themselves. My first approach was to implement a sphere-ray intersection algorithm in a pixel shader to dertermine the surface position of a shadow cast from my cloud sphere, and subtract the result from the existing surface texture.

Planetary Body Shader

By
Dave
Project
Published
9 Feb 2010 00:58
Last Modified
13 Jan 2013 17:57

In order to render my planetary bodies, I had to consider the following effects:

  1. Texture
  2. Lighting
  3. Relief
  4. Atmospheres
  5. Clouds
  6. Shadows

I'll discuss each of these in later posts, but for now here are some screenshots of the first attempt at rendering a planetary body using these effects.

Earth Shader

Earth Shader

Earth Shader

Earth Shader

Earth Shader

Figures 1-5. Earth Shader

Background Stars

By
Dave
Project
Published
7 Feb 2010 21:18
Last Modified
13 Jan 2013 17:57

In order to render a realistic star background, I could either use an image texture (either mapped onto a sphere or a cube), or a set of dynamic points. I opted for the latter so that I could more easily support changing my field-of-view (i.e. "zooming-in") without losing detail on my background.

Numerous star catalogues are available in the public domain. I opted for the Hipparcos Catalog, which lists the positions of approximately 100,000 stars. I converted the catalog to XML and then used the Content Pipeline in XNA Game Studio 3.1 to compress the XML to an XNB file. The data can then be loaded at runtime simply by using:

BackgroundStar[] stars = Content.Load<BackgroundStar[]>("hipparcos");

BackgroundStar is a simple class containing information such as position, brightness, spectral type etc. for each star in the catalogue.

I was really surprised at the level of performance I got when rendering these items, initially as point primitives, and subsequently as point sprites. For the latter, I created myself a simple blurred sprite which I sized according to the brightness, and tinted according to the spectral type of the star. As an example, here's a screenshot of Orion taken with both a wide and narrow field-of-view.

Orion Wide-Angle

Figure 1. Orion Wide Angle

Orion Tele-Photo

Figure 2. Orion Tele-Photo

One of the issues here is that the apparent magnitude of a star is a logarithmic scale. This means that the faintest stars visible to the naked eye (around magnitude 7-8) are approximately five thousand times fainter than the brightest star in the sky (Sirius, magnitude -1.46). The Hipparcos Catalog lists stars down to around magnitude 14, so in order to render this range of magnitudes with only 255 levels of luminance I had to flatten the brightness curve.

Celestial Grid

By
Dave
Project
Published
7 Feb 2010 00:01
Last Modified
13 Jan 2013 17:58

To make things much easier, I wanted to render a grid to help with orientation. In planetary terms this would be a latitude/longitude grid, however the celestial equivalent is declination/right ascension respectively.

This was simply a matter of drawing line primitives on the surface of a sphere centered around the camera viewpoint. I chose not to converge all my lines of right ascension at the "poles", as shown below. The only drawback to this was that I had to draw multiple lines, since it's only possible to use just one if the lines converge.

Celestial Grid Equator

Figure 1. Celestial Grid Equator

Celestial Grid Poles

Figure 2. Celestial Grid Poles

One advantage of using multiple lines, however was that I have the option of varying the color for particular lines. For example, I might choose to make the "equator", or elliptical plane, more opaque.

Starting Positions

By
Dave
Project
Published
6 Feb 2010 22:46
Last Modified
13 Jan 2013 17:59

Errm, where do I start in building a Virtual Solar System?

How about the orbits of the planets? At the start of the 17th Century, Kepler coined his laws of planetary motion. His first law defined the orbit of a planet as an ellipse with the sun at a focus, and the position on an ellipse can be defined by six unique pieces of data:

  1. Semi-Major Axis (a)
  2. Eccentricity (e)
  3. Inclination (i)
  4. Argument of Perifocus (ω)
  5. Longitude of Ascending Node (Ω)
  6. True Anomaly (θ)

These "Orbital Elements" for each body are available on the NASA JPL Horizons system.

The XNA Creators Club is a fantastic resource, with heaps of examples to get me started on a simple app to render orbital positions. Plugging in the data gave me the following results:

Inner Planet Orbits

Figure 1. Inner Planet Orbits

Outer Planet Orbits

Figure 2. Outer Planet Orbits

Once I had this basic framework for rendering orbits and positions I could add additional bodies, such as comets and moons as shown below

Outer Planet & Comet Orbits

Figure 3. Outer Planet & Comet Orbits

Outer Jupiter Moon Orbits

Figure 4. Outer Jupiter Moon Orbits

Virtual Universe

By
Dave
Project
Published
6 Feb 2010 22:45
Last Modified
13 Jan 2013 18:01

I finally decided that I should try to get my head around the XNA Framework. Why, do you ask? Well, I found myself tinkering on another WPF project, requiring a reasonable amount of 3D, spending a considerable amount of time performance tuning the application. I started to wonder "if I spent the time I would otherwise spend performance tuning this app on learning how to implement the same application using XNA, could I end up getting to the same level of performance using XNA in the same overall time?"

So I thought I'd blow the cobwebs off this blog and use it as a journal as I try to find my path into the scary world of Games Programming.

I've had in my mind for some time the desire to learn more about the dynamics of the solar system. Maybe I spent too much time playing Elite. I really struggle with names, so for the time-being until I think of a better one, I'll refer to this project as "Virtual Universe".

Page