A skybox is a little trick to produce the distant background to a scene - maybe a distant landscape to the horizon, and a sky.
The obvious way to do this would be to draw very large and distant quads with suitable textures on them. But an easier way is this:
The rest of the scene would usually be 'outside' the skybox. But there will be no effect from it on the depth buffer, so everything else will be visible. An advantage of this approach i sthat you do not hav eto worry about drawing things outside the skybox.
Suppose we want to draw a scene in space. We could Google for pictures of star fields, but in fact they are easy to create programmatically. We need 6, with some attributes:
// size of the sky box buffers
int skyBoxImageWidth = 512;
int skyBoxImageHeight = 512;
// the buffers
private ByteBuffer[] skyBoxImage = new ByteBuffer[6];
// their 'names'
int[] skyBoxTextures = new int[6];
We make the buffer contents like this:
/**
* Create the skyBoxImage buffers and put star images in them.
* For each of the 6 buffers, make each texel black, and then
* put 500 coloured dots in them which look like distant fixed stars
*
*/
void makeSkyboxImages() {
for (int image = 0; image < 6; image++) {
for (int i = 0; i < skyBoxImageHeight; i++) {
for (int j = 0; j < skyBoxImageWidth; j++) {
skyBoxImage[image].put((byte) (0));
skyBoxImage[image].put((byte) (0));
skyBoxImage[image].put((byte) 0);
skyBoxImage[image].put((byte) 255);
}
}
skyBoxImage[image].rewind();
// the texel at (col, row) is at offset
// row*skyBoxImageWidth*4 + col*4 an dthe next 3 bytes
// make 500 stars
for (int i = 0; i < 500; i++) {
int row = (int) (Math.random() * skyBoxImageHeight);
int col = (int) (Math.random() * skyBoxImageWidth);
int offset = row * skyBoxImageWidth * 4 + col * 4;
skyBoxImage[image].put(offset, (byte) (155 + Math.random() * 100));
skyBoxImage[image].put(offset + 1, (byte) (155 + Math.random() * 100));
skyBoxImage[image].put(offset + 2, (byte) (155 + Math.random() * 100));
}
}
}
We set this up in init()
// make skybox images
for (int i = 0; i < 6; i++) {
skyBoxImage[i] = BufferUtil.newByteBuffer(skyBoxImageWidth * skyBoxImageHeight * 4);
}
makeSkyboxImages();
gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1);
final int[] tmp = new int[6];
gl.glGenTextures(6, tmp, 0);
for (int image=0; image<6; image++)
{
skyBoxTextures[image] = tmp[image];
// make the named texture to be the type we want
gl.glBindTexture(GL.GL_TEXTURE_2D, skyBoxTextures[image]);
// say how it repeats if needed
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_REPEAT);
// and how texels and pixels map
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER,
GL.GL_LINEAR);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER,
GL.GL_LINEAR);
// connect to data
gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, skyBoxImageWidth,
skyBoxImageHeight, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE,
skyBoxImage[image]);
}
This draws the sky box:
private void drawSkyBox(GL gl)
{
float x=camera.getX();
float y=camera.getY();
float z=camera.getZ();
gl.glDisable(GL.GL_DEPTH_TEST);
gl.glEnable(GL.GL_TEXTURE_2D);
gl.glTexEnvf(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_DECAL);
gl.glBindTexture(GL.GL_TEXTURE_2D, skyBoxTextures[0]);
gl.glBegin(GL.GL_QUADS);
// one face..
gl.glTexCoord2f(0.0f, 0.0f);
gl.glVertex3f(x-1.0f, y-1.0f, z-1.0f);
gl.glTexCoord2f(0.0f, 1.0f);
gl.glVertex3f(x-1.0f, y+1.0f, z-1.0f);
gl.glTexCoord2f(1.0f, 1.0f);
gl.glVertex3f(x+1.0f, y+1.0f, z-1.0f);
gl.glTexCoord2f(1.0f, 0.0f);
gl.glVertex3f(x+1.0f, y-1.0f, z-1.0f);
// another face..
gl.glBindTexture(GL.GL_TEXTURE_2D, skyBoxTextures[1]);
gl.glTexCoord2f(0.0f, 0.0f);
gl.glVertex3f(x+1.0f, y-1.0f, z-1.0f);
gl.glTexCoord2f(0.0f, 1.0f);
gl.glVertex3f(x+1.0f, y+1.0f, z-1.0f);
gl.glTexCoord2f(1.0f, 1.0f);
gl.glVertex3f(x+1.0f, y+1.0f, z+1.0f);
gl.glTexCoord2f(1.0f, 0.0f);
gl.glVertex3f(x+1.0f, y-1.0f, z+1.0f);
//.. plus another 4 faces
gl.glEnd();
gl.glDisable(GL.GL_TEXTURE_2D);
}
The code in display is
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();// Reset The View
glu.gluLookAt(camera.getX(), camera.getY(), camera.getZ(), lookAt.getX(), lookAt.getY(), lookAt.getZ(), up.getX(), up.getY(), up.getZ());
drawSkyBox(gl);
gl.glEnable(GL.GL_DEPTH_TEST);
glut.glutSolidSphere(1.0, 20, 20);
..
The result is 