Tutorial 13 : Light [Part II]

Tutorial Download Section

In this second light tutorial, we will see in more details the light source properties to creates differents kind of light.
 

Here, we will see how to creates this 3 kind of lights :
    positional light
    directional light
    spot
 

In the previous tutorial, we have ceated a positional light source. This kind of light emits light from a particular location (define by the property : GL_POSITION) and emits ray in all direction.

A directional light emits light from an infinite distance. The ray emitted are all parallel and have the same direction (defined by the property GL_POSITION).

This two kind of lights are represented in the following picture :


Positional and Directional light

The property GL_POSITION is an array that contains the 4 values : (x, y, z, w)
The 3 first defines the position of the light or the direction of the ray depending of the value of w. (x, y, z) values are represented in the previous picture in the two cases.

If w is equal to 0, the light is a directional one. If w is different to 0, the light is a positional one (in general, we take w = 1).
 

The light received by an object from a directional light is independant of his position. Effectively, all ray have the same direction so the object is always lit by the 'same' rays.
In contrary, light received by an object from a positional light depends on his position.

You can remark that the shape of the positional light move with the object contrary to the shape of the directional light remains fixe for all the object position.
 

Initialization of these two lights

    /**
     * GL_LIGHT0
     * - directional light source
     * - no ambient
     * - white diffuse
     */

    private void initDirLight()
    {
        float noAmbient[] = {0.0f, 0.0f, 0.0f, 1.0f};
        float whiteDiffuse[] = {1.0f, 1.0f, 1.0f, 1.0f};
        /*
         * Directional light source (w = 0)
         * The light source is at an infinite distance,
         * all the ray are parallel and have the direction (x, y, z).
         */

        float position[] = {1.0f, 1.0f, 0.0f, 0.0f};
       
        gl.glLightfv(GL_LIGHT0, GL_AMBIENT, noAmbient);
        gl.glLightfv(GL_LIGHT0, GL_DIFFUSE, whiteDiffuse);
        gl.glLightfv(GL_LIGHT0, GL_POSITION, position);
    }
   
    /**
     * GL_LIGHT1
     * - positional light source
     * - yellow ambient
     * - yellow diffuse
     *
     * Rem:
     * To have a "real" effect, set the ambient and diffuse to the same color.
     */

    private void initPosLight()
    {
        float yellowAmbientDiffuse[] = {1.0f, 1.0f, 0.0f, 1.0f};
        /*
         * Positional light source (w = 1)
         * The light source is positioned at (x, y, z).
         * The ray come from this particular location (x, y, z) and goes towards all directions.
         */

        float position[] = {-2.0f, 2.0f, -5.0f, 1.0f};
       
        gl.glLightfv(GL_LIGHT1, GL_AMBIENT, yellowAmbientDiffuse);
        gl.glLightfv(GL_LIGHT1, GL_DIFFUSE, yellowAmbientDiffuse);
        gl.glLightfv(GL_LIGHT1, GL_POSITION, position);
    }

 

A spot is a particular positional light source. Like positional light sourcen a spot is positionned at a defined point and emit light from this point. The difference is, for a spot, the ray emission is restricted to a cone area. Outside the cone, a spot emits no light.

A spot have the same properties of the positional light viewed previously. In addition, a spot have a direction (GL_SPOT_DIRECTION) which correspond to the emission cone center and an angle (GL_SPOT_CUTOFF) which define the cone boundaries.
Those two new properties are represented in the picture bellow :


Spot light

The axis of the cone is define by the direction GL_SPOT_DIRECTION. The angle of the cone is tha value GL_SPOT_CUTOFF.
In this tutorial, the spot is direction is update at each frame to simulate a circular movement. The spot cutoff can also be modified.
 

If you have read Lesson 6, you probably heared about light attenuation.
The attenuation of the light is defined with the 3 constants : GL_CONSTANT_ATTENUATION, GL_LINEAR_ATTENUATION and GL_QUADRATIC_ATTENUATION. Here I use default values that correspond to no attenuation with the distance. It is more details in Lesson 6, we also use this in Tutorial 15.

For spot light, there are a second attenuation. The first attenuation takes in consideration the distance between the source and the vertex (for infinite light source, attenuation is not taken in account).
The spot attenuation take in account the distance between the vertex and the center of the cone. This attenuation defines how the light is concentrated in the center of the cone.
The OpenGl constant for this attenuation is GL_SPOT_EXPONENT. The value associated is in the interval [0, 128]. The highest value define a high concentrated spot. The lowest value defines a spot that emits light equaly in the cone.
 

Initialization of the Spot

    /******************
     * NEW *   Spot   *
     *********************************************************************************
     * This light is a sport. A spot emits lights on a particular direction.         *
     * To create a spot, we have to specify the spot direction (GL_SPOT_DIRECTION)   *
     * and the spot cut-off (GL_SPOT_CUTOFF).                                        *
     * The spot cut-off is the angle of the cone in which the spot emits light. The  *
     * axis of the cone is the spo direction.                                        *
     *********************************************************************************/

    private void initSpot()
    {
                /*Particular properties of all the lights*/
       
        float noAmbient[] = {0.0f, 0.0f, 0.2f, 1.0f};       //low ambient light
        float diffuse[]   = {0.0f, 0.0f, 1.0f, 1.0f};
        float position[]  = {0.0f, 0.0f, 0.0f, 1.0f};
       
        //properties of the light
        gl.glLightfv(GL_LIGHT2, GL_AMBIENT, noAmbient);
        gl.glLightfv(GL_LIGHT2, GL_DIFFUSE, diffuse);
        gl.glLightfv(GL_LIGHT2, GL_POSITION, position);
       
                /*Spot properties*/
       
        /*
         * define the spot direction and cut-off
         */

        updateSpot();
       
        //exponent propertie defines the concentration of the light
        gl.glLightf(GL_LIGHT2, GL_SPOT_EXPONENT, 15.0f);
       
        //light attenuation (default values used here : no attenuation with the distance)
        gl.glLightf(GL_LIGHT2, GL_CONSTANT_ATTENUATION, 1.0f);
        gl.glLightf(GL_LIGHT2, GL_LINEAR_ATTENUATION, 0.0f);
        gl.glLightf(GL_LIGHT2, GL_QUADRATIC_ATTENUATION, 0.0f);
    }
   
    /*
     * Update position, direction and cut-off of the light
     */

    private void updateSpot()
    {
        float direction[] = {xSpotDir, ySpotDir, zOffset};
       
        //spot direction
        gl.glLightfv(GL_LIGHT2, GL_SPOT_DIRECTION, direction);
        //angle of the cone light emitted by the spot : value between 0 to 180
        gl.glLightf(GL_LIGHT2, GL_SPOT_CUTOFF, spotCutOff);
    }

 

D: enable/disable directional light
P: enable/disable positional light
S: enable/disable spot

+ - : increase/decrease cutoff
R : reset spot position
M : pause/unpause sphere movement
 

Remember to download the GraphicEngine-1.1.2 to run this tutorial !


If you've got any remarks on this tutorial, please let me know to improve it.
Thanks for your feedback.
 

Previous Tutorial

Back

Next turorial

Copyright © 2004-2012 Jérôme Jouvie - All rights reserved. http://jerome.jouvie.free.fr/