You copied the Doc URL to your clipboard.

6.7.3. Example showing calculation of bump-mapped reflections

The application code in Example 6.29 uses an interpolated vertex color for the fragment. To use normal and diffuse texture samplers:

  1. The example in Example 6.31 uses normal and diffuse texture samplers from bitmaps to modify the reflections:

    Example 6.31. Context initialization in bump map application code

        // initialize the context and MDE classes
        // load the shader code
        // Loading scene from a Mali Binary Asset file eliminates the requirement to
        // construct an arrow of primitive shapes
        SceneAsset* scene = proxy.getSceneAsset("");
        // get the asset from the mba file and assign it to the cube_asset variable
        GeometryAsset* cube_asset = 
            static_cast<GeometryAsset*>(scene->getAsset(Asset::TYPE_GEOMETRY, 0));
        // this bitmap creates a texture used with the diffuse light calculation
        Texture2D *diffuseTexture = 
        // this bitmap creates a texture used with the specular light calculation
        Texture2D *normalMap =
        // Initialize the camera position, target, and up vector
        float cameraAngle = 0.0f;
        vec3 camPos = calculateCamPos(75.0f, cameraAngle);
        vec3 camTarget = vec3(0.0f, 0.0f, 0.0f);
        vec3 upVector = vec3(0.0f, 0.0f, 1.0f);
        // Set up the view, projection and world matrices and multiply them to get the
        // modelviewprojection and modelview matrices.
        mat4 view = mat4::lookAt(camPos, camTarget, upVector);
        mat4 proj = mat4::perspective(60.0f, 4.0f/3.0f, 1.0f, 500.0f);
        mat4 world = mat4::identity();
        // create the transformation matrix
        mat4 wvpMatrix = proj * view * world;
        // define a light position that will be used with specular reflections
        vec3 lightPosition(75.0f, 75.0f, 0.0f);
        // Initialize the uniforms
        context->setUniform("LIGHT_POSITION", lightPosition);
        context->setUniform("CAMERA_POSITION", camPos);
        context->setUniform("AMBIENT_LIGHT", AMBIENT_LIGHT);
        context->setUniform("DIFFUSE_LIGHT", DIFFUSE_LIGHT);
        context->setUniform("SPECULAR_LIGHT", SPECULAR_LIGHT);
        context->setUniformSampler("diffuseTexture", diffuseTexture);
        context->setUniformSampler("normalMap", normalMap);

  2. The vertex shader code in Example 6.32 is similar to the code in Example 6.27, except that the WORLD uniform is also passed to the shader:

    Example 6.32. Lighting initialization in bump map application code

        // Enable depth test and start drawing loop
            // use keyboard input to rotate the camera or the object
            wvpMatrix = proj * view * world;
            // set uniforms that have changed since the last draw
            context->setUniformMatrix("WORLD_VIEW_PROJECTION", wvpMatrix);
            context->setUniformMatrix("WORLD", world.toMat3());
            // Clear the screen and draw cube_asset with lighting
            // call the assets own draw method to render the primitives
        }while ( context->update() );

  3. The vertex shader code in Example 6.33 calculates the position of a fragment based on the interpolated POSITION value and a world view projection:

    Example 6.33. Lighting calculation in bump map vertex shader

    uniform mat4 WORLD_VIEW_PROJECTION;
    uniform mat3 WORLD;
    uniform vec3 LIGHT_POSITION;
    uniform vec3 CAMERA_POSITION;
    attribute vec4 POSITION;
    attribute vec3 NORMAL;
    attribute vec3 TANGENT;
    attribute vec3 BINORMAL;
    attribute vec3 TEXCOORD0;
    varying vec2 vTexCoord;
    varying vec3 vLightVector;
    varying vec3 vCameraVector;
    void main(void)
        vTexCoord =;
        vec3 pos = WORLD *;
        mat3 TBN = WORLD * mat3(normalize(TANGENT), normalize(BINORMAL),
        // No point in normalizing before the fragment shader as the normalization will
        // be offset by the interpolation anyway.
        vLightVector = (LIGHT_POSITION - pos) * TBN;
        vCameraVector = (CAMERA_POSITION - pos) * TBN;

  4. Example 6.34 shows the fragment shader combining the light sources:

    Example 6.34. Summing light values in bump map fragment shader

    uniform mat3 M_MATRIX;
    uniform sampler2D diffuseTexture;
    uniform sampler2D normalMap;
    uniform vec3 AMBIENT_LIGHT;
    uniform vec3 DIFFUSE_LIGHT;
    uniform vec3 SPECULAR_LIGHT;
    uniform float DIFFUSE_CONTRIBUTION;
    uniform float SPECULAR_CONTRIBUTION;
    uniform float AMBIENT;
    varying vec2 vTexCoord;
    varying vec3 vLightVector;
    varying vec3 vCameraVector;
    void main(void)
        // read the normal value for this point from the texture
        vec3 normal = normalize(texture2D(normalMap, vTexCoord).rgb * 2.0 - 1.0);
        // read the color for this point from the texture
        vec4 color = texture2D(diffuseTexture, vTexCoord);
        // calculate the intensity of the diffuse light reflected off the point
        vec3 lightVector = normalize(vLightVector);
        float nDotL = max(dot(normal, lightVector), 0.0);
        vec3 diffuse = DIFFUSE_LIGHT * nDotL;
        // calculate the multiplier for the specular reflection
        float specPow = 0.0; // was 0
        // if the nDotL value is less than 0, use 0.0 for the specular multiplier
        if (nDotL > 0.0)
            vec3 cameraVector = normalize(vCameraVector);
            // what is the reflection based on the normal and the camera view
            vec3 reflectVector = reflect(-cameraVector, normal); 
            specPow = pow(max(dot(reflectVector, lightVector), 0.0), 4.0);     
        // calculate the reflected light
        vec3 specular = SPECULAR_LIGHT * specPow;
        // add the light values for the point together and assign the result to the color
        gl_FragColor = vec4(AMBIENT_LIGHT, 1.0) * color + // was 1.0
                       vec4(diffuse, 1.0) * color + // was 1.0
                       vec4(specular, 1.0); //was 1.0