Moving on from techniques for generating terrain for now, I started looking at how to generate a background for my rendered scene. So far I had been using a solid background color but I wanted something more interesting. Since the scene background in a typical game will obstructed in many places, most game engines do not render actual 3D geometry for far-away scenery but instead show a static image. There are a few options on how to implement this: traditionally, games have used what is called a skybox – a textured cube that surrounds the current scene. See for example Half Life using this to great effect to represent a far-away canyon. The skybox is moved relative to the player / camera, so that it appears to be infinitely far away at all times. More recent implementations of this technique have the skybox move a small amount relative to the camera so as to create the illusion that the player is progressing towards some location. A cube is easy to render having only 8 vertices, but one has to be careful texturing it to avoid seams at the edges.
A more advanced approach that overcomes these limitations is to render a textured sphere or dome around the scene. While this increases the geometrical complexity of the scene, it resolves the texturing issues by elimination problematic corners. Using polar coordinates (longitude & latitude), it is also possible to animate the surface of the sphere.
For my testing, I created a small test scene comprised of the following elements:
- A textured ground plane
- A cube to test out scene lighting
- A skydome
For the skydome, I defined the color of the horizon and the zenith. In the fragment shader, these colors are blended based on the elevation of the fragment to create a gradient which provides the base color of the sky:
In addition the the color gradient, it is also possible to blend in a texture. Here is an example of a star map to display a night sky over a black background color:
In the game, I would like to have a day-night cycle that dynamically changes the environment. To this end, I have divided a day in my game into phases like morning, day, evening, etc. Each phase defines its duration, the lighting parameters, as well as the skydome material. The environment system then transitions from one phase to the next using a transition function (linear, quadratic, etc.). Here is the same view of the skydome over the course of a day:
All of this provides a basic background to the rendered scene, but I felt that it was a bit too uniform. What was missing compared to the real world is a stellar body like our sun. Primarily, this adds a bright sphere at its location. Further, it also changes the color of the surrounding sky due to refraction at certain times of the day. There are many advanced articles on atmospheric scattering, but I just wanted something quick to make the sky look more interesting, so here is what I came up with: I was already storing a directional vector to light my scene geometry. This vector represents the direction of global illumination, or in other words, the direction from the sun to the scene geometry. With this information, I was able to determine the position of the sun as well as the level of refraction surrounding it for every fragment of the skydome. Using the same transition mechanism as before, the environment system is able to change the position and coloring of the light source over the course of the day:
I found that a skydome is an easy way to quickly add a dynamic background to a scene. My prototype could be extended by using the texture blending mechanism to show clouds during the day. Also, there still is a lot of room for improvement when it comes to rendering the sun and refraction.
The source code for this example is available on my Github repository.
Leave a Reply