The main perception of three dimensions comes from the shades. The human eye can only see colours and not the outlines. It's the transition from one colour to the other that signals the change into our brain. Similarly the change in the shadows informs our brain about the third dimension. The 'Moving into the third dimension' tutorial was based on the illusion of wireframe drawing for the 3D effect. The objects were actually transparent and the perspective drawing of the edges was enough to make you see 3D.
In real world though the objects are not drawn in wireframe mode and so we need something else to add realism into our scenes. Light is the answer to the problem. By adding light into the scene OpenGL applies different shadows to different faces, thus giving the required 3D effect.
Human perception of colour is not only the RGB value of the colour used to paint a surface. The actual colour that reaches our eyes contains information about the ambient light around the object, the diffuse and specular light that is reflected by the surface. According to Wikipedia 'Diffuse reflection' is the reflection of light from a surface such that an incident ray is reflected at many angles rather than at just one angle as in the case of specular reflection.' In other words diffusion spreads the light while specular reflection does what we all understand, reflects the light.
OpenGL lets us specify the behavior of our surfaces in respect to these types of light spreading. We specify the amount of ambient light in the scene that will illuminate parts of the scene where light is not falling directly. Then we can specify how the surface reflects the light, i.e. the intensity at any one of the red green and blue factors.
Here is how we do it. First we have to enable some features in OpenGL in order to draw with colour and light. The following fragment shows the command we have to issue to the renderer
glEnable (GL_DEPTH_TEST); // enable depth test to draw correctly in 3D glEnable(GL_COLOR_MATERIAL); // allow the use of colour for drawing the object glEnable (GL_LIGHTING); // enable lighting glEnable (GL_LIGHT0); // and turn on light 0 static GLfloat light_ambient[] = { 0.1f, 0.1f, 0.1f, 1.f }; // the colour and intensity of the ambient light static GLfloat light_diffuse[] = { 0.3f, 0.3f, 0.3f, 1.f }; // the diffuse property of the surface static GLfloat light_specular[] = { 0.95f, 0.95f, 0.95f, 1.f }; // the specular property // pass them to OpenGL glLightfv (GL_LIGHT0, GL_AMBIENT, light_ambient); glLightfv (GL_LIGHT0, GL_DIFFUSE, light_diffuse); glLightfv (GL_LIGHT0, GL_SPECULAR, light_specular);
Then when we draw in the 'render_frame' function and after we position the viewer, we can position the light as follows
static GLfloat light_position[] = { 80.f, 0.f, 0.f, 0.f }; // the position of the light glLightfv (GL_LIGHT0, GL_POSITION, light_position); // and pass it to OpenGL
Download the sample program and see how we do it.