Last update: 2 September 2015

Tutorial 2: Bump Mapping

This tutorial show how to peform simple and effective bump mapping technique on iOS. This technique is used widely in games to add details to the models without the need of complex or high polygon count model. We need a normal texture in addition to the diffuse. Light Position is send to the shader in the model space coordinate system and then transformed  to tangent space to perform light calculation. In the pixel shader we fetch a per pixel normal from the normal map, this leads to a non uniform light calculation on the model surface. Without the normal map we will get a uniform lighting on a plane surface. The screenshot bellow shows the result of this technique on a simple box.  (3D model from turbosquid.com.)

Code walkthrough

The shader needs a normal texture that defines the normal vector for each pixel. We then supply the light position in the model space, this can be done by multiplying the light position by the inverse of the transformation matrix of the model as follow:

    // this is to animate and move light on a circular trajectory
    static float y = 0.f;
    static float x = 0.f;
    x = -80.f * sinf(time);
    y = -80.f * cosf(time);
    //transform light to model space, so light calculation can be peformed in model space within shader
    //to do so we multiply the light position by the inverse of the model matrix of the model.
    vec4f lightPos = modelBumpMeshMat.inverse() * vec4f(x, y, 0, 1.f);

//send light pos to shader
    m_pShaderBump->SetUniform3fv("LightPosModel", 1, &lightPos.x);

Next in the vertex shader, we construct the TBN matrix, this matrix transform model coodinate system to tangent system, we then multiply the light direction by this matrix to transfrom the light vector to tangent space. In fact we need to have a common coordinate system to perform light calculation, normals and tangent are given in the tangent space we need to transfrom the light vector into the same coordinate system so our light calculation can make sense.

    //create tangent stace
    mat3 tangentSpaceXform = mat3(tangent, bitangent, normal);
   
    //transfrom light direction from model space to tangent space
    v_lightVec = lightDirection * tangentSpaceXform;

In the vertex shader, we fetch a per pixel normal from the normal texture, than we calculate the light intensity by doing the dot product between the normal vector and light direction.

    // per pixel normal
    vec3 normal = texture2D(textureBump, v_texCoord).rgb * 2.0 - 1.0;
    //light intensity is the dot product of the light direction with the per pixel normal
    float lightIntensity = dot(v_lightVec, normal);