Skybox tutorial

Preface
This article is assumes you have some basic understanding of OpenGl.

In many 3D-games today we see an image in the background. The image is nicely rotated when we look around. There are some different methods to produce this effect but the skybox is the easiest and probably the best. A skybox is a box which seems to contain the entire scene and is rendered from the inside. The skybox is always rendered before the other geometry in the scene with depthtesting off.

Geometry
The geometry of the skybox is simple, just a box. However, keep in mind that we are inside the box and the sides must face us. We will be using GL_QUADS to make the box. The box will be 1x1x1 units in size. We never want to go to the edge of the box so we will use a little trick, we position the camera in the middle of the box each time it is rendered. Also, make sure that depthtesting is disabled, lighting should also be disabled but some neat day/night effect maybe could be produced by using lighting, your call.

Texture
The next thing is the texture. A skybox could contain either 5 or 6 textures depending on whenever the bottom is visible or not. The texture itself should be divided to 5 or 6 parts, one for each quad.

The image below is an unwrapped box, this is an example of how you could wrap your textures. It doesn't really matter as long as you know which one that belongs the each quad. To generate my textures I use Terragen (See below). One issue we might run into is edges in corners, to prevent this we tell OpenGL to use GL_CLAMP as texturewrapper. This should pretty much conclude everything about a basic skybox, so onto the code.

Simple skybox
As I alread said I assume some knowledge in OpenGL so you should know how to make the box itself, just remember that we are inside the box. In my examples I have 6 quads. First I will show you how to load your textures:  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

As explained above this makes sure the textures displayed correctly and no edges will appear on the quads. '''In some cases we need to turn off interpolation too. Just set GL_TEXTURE_MAG_FILTER and GL_TEXTURE_MIN_FILTER to GL_NEAREST.''' Below is a sample routine to render the skybox. All lines will be explained later.



// Store the current matrix glPushMatrix;

// Reset and transform the matrix. glLoadIdentity; gluLookAt(       0,0,0,        camera->x,camera->y,camera->z,        0,1,0);

// Enable/Disable features glPushAttrib(GL_ENABLE_BIT); glEnable(GL_TEXTURE_2D); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glDisable(GL_BLEND);

// Just in case we set all vertices to white. glColor4f(1,1,1,1);

// Render the front quad glBindTexture(GL_TEXTURE_2D, _skybox[0]); glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex3f( 0.5f, -0.5f, -0.5f ); glTexCoord2f(1, 0); glVertex3f( -0.5f, -0.5f, -0.5f ); glTexCoord2f(1, 1); glVertex3f( -0.5f, 0.5f, -0.5f ); glTexCoord2f(0, 1); glVertex3f( 0.5f,  0.5f, -0.5f ); glEnd;

// Render the left quad glBindTexture(GL_TEXTURE_2D, _skybox[1]); glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex3f( 0.5f, -0.5f,  0.5f ); glTexCoord2f(1, 0); glVertex3f( 0.5f, -0.5f, -0.5f ); glTexCoord2f(1, 1); glVertex3f( 0.5f,  0.5f, -0.5f ); glTexCoord2f(0, 1); glVertex3f( 0.5f,  0.5f,  0.5f ); glEnd;

// Render the back quad glBindTexture(GL_TEXTURE_2D, _skybox[2]); glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex3f( -0.5f, -0.5f, 0.5f ); glTexCoord2f(1, 0); glVertex3f( 0.5f, -0.5f,  0.5f ); glTexCoord2f(1, 1); glVertex3f( 0.5f,  0.5f,  0.5f ); glTexCoord2f(0, 1); glVertex3f( -0.5f, 0.5f,  0.5f );

glEnd;

// Render the right quad glBindTexture(GL_TEXTURE_2D, _skybox[3]); glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex3f( -0.5f, -0.5f, -0.5f ); glTexCoord2f(1, 0); glVertex3f( -0.5f, -0.5f, 0.5f ); glTexCoord2f(1, 1); glVertex3f( -0.5f, 0.5f,  0.5f ); glTexCoord2f(0, 1); glVertex3f( -0.5f, 0.5f, -0.5f ); glEnd;

// Render the top quad glBindTexture(GL_TEXTURE_2D, _skybox[4]); glBegin(GL_QUADS); glTexCoord2f(0, 1); glVertex3f( -0.5f, 0.5f, -0.5f ); glTexCoord2f(0, 0); glVertex3f( -0.5f, 0.5f,  0.5f ); glTexCoord2f(1, 0); glVertex3f( 0.5f,  0.5f,  0.5f ); glTexCoord2f(1, 1); glVertex3f( 0.5f,  0.5f, -0.5f ); glEnd;

// Render the bottom quad glBindTexture(GL_TEXTURE_2D, _skybox[5]); glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex3f( -0.5f, -0.5f, -0.5f ); glTexCoord2f(0, 1); glVertex3f( -0.5f, -0.5f, 0.5f ); glTexCoord2f(1, 1); glVertex3f( 0.5f, -0.5f,  0.5f ); glTexCoord2f(1, 0); glVertex3f( 0.5f, -0.5f, -0.5f ); glEnd;

// Restore enable bits and matrix glPopAttrib; glPopMatrix;

The camera transformation is a little bit special when rendering a skybox. We never translates by the camera position, only rotation is applied. This is because the skybox never moves. It is always positioned at origo (0,0,0). Below is a sample of the skybox in use. The rendering above could easily be optimized in numerous ways but for clarity it is kept simple.

Tips&Tricks
There are many things that can improve the quality of the skybox. Here are a few:

Moving clouds
Create a plane inside the skybox, let it have transparent edges and a texture with transparent clounds. Animate the texture coordinates in a given direction.

Sun
Add a lightsource in the spot that the sun would be and add a large lensflare. Alphablending a white fullscreen quad when you look toward it really makes you think you look into the sun.

Day & night
Either animate the texture or very slowly fade between two skyboxes. Also remember to adjust the ambient lighting to make it darker at night.

Terragen
Terragen is a tool to generate terrains but it works perfectly for generating skybox-textures too. I won't go into details but this is the basics. Position the camera in the center. Make sure the zoom is 1.0 or the image won't fit together. Adjust roll, yaw and pitch for each image you take. The Valve Developer Community has a nice tutorial and automated script for generating textures with terragen.

Links

 * Terragen
 * Valve Developer Community (Skybox (2D) with Terragen)
 * Hazel Whorley - Some excellent skybox textures, free for noncommersial usage.