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("cube.mba");
        // 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 = 
            proxy.getTexture2DAsset("rock_t.png")->getTexture2D();    
    
        // this bitmap creates a texture used with the specular light calculation
        Texture2D *normalMap =
            proxy.getTexture2DAsset("rock_n.png")->getTexture2D();    
    
        // 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
        glEnable(GL_DEPTH_TEST);
        do
        {
            // 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
            glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
    
            // call the assets own draw method to render the primitives
            cube_asset->draw();
        }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)
    {
        gl_Position = WORLD_VIEW_PROJECTION * POSITION;
        vTexCoord = TEXCOORD0.st;
        
        vec3 pos = WORLD * POSITION.xyz;
        mat3 TBN = WORLD * mat3(normalize(TANGENT), normalize(BINORMAL),
                           normalize(NORMAL));
        
        // 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
    }