Course list http://www.c-jump.com/bcc/

Lab 9 -- Texture Mapping


  1. Introduction
  2. Getting ready
  3. Things to do
  4. How to submit

1. Introduction



2. Getting ready



3. Things to do


  1. Open Model.cpp and locate Model::upload_bitmap_texture() member function. It contains directions as follows:

    
        // 1) Generate a texture ID
        // 2) Bind that texture as the current ID
        // 3) Load the bitmap onto the GPU using glTexImage2D()
        // 4) Set the parameters for minification, magnificaiton and repeating UVs
        // 5) Get the ID of the variable "texture" from the fragment shader...
    
    

    To get this done, open Textures in OpenGL handout and jump to the topic Texture example (client side). A working sample project can also be found in our example folder:

    
        C:\bcc\GL262Labs\example\Lecture17_Texture
    
    

    Do it! If you are still unsure how all this code should look like, here a hint:

    
        glGenTextures( 1, &tex_buffer_ID );
    
        glBindTexture( GL_TEXTURE_2D, tex_buffer_ID );
    
        glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, bitmap_data );
    
        glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
        glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
        glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
        glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
        
        // Mipmap generation is quite easy:
        glGenerateMipmap( tex_buffer_ID );
    
        texture = glGetUniformLocation( shader->program_ID, "texture" );
    
    
  2. Examine the code in Model::render(). Notice what this function does when UV coordinates are present in our model:

    
        if (vTexCoord != -1) {
            glEnableVertexAttribArray( vTexCoord );
            // Turn on 2D texturing
            glEnable( GL_TEXTURE_2D );
            // Set it to be texture 0
            glActiveTexture( GL_TEXTURE0 );
            // Bind the texture we loaded as the current texture
            glBindTexture( GL_TEXTURE_2D, tex_buffer_ID );
            // and upload to the "texture" variable in the fragment shader
            glUniform1i( texture, 0 );
        }
    
    

    You don't need to make any changes here, but understand that this is an important part of rendering the texture.

  3. Next, open the vertex shader in Shaders\TextureShader_v.c file. Observe that there is the new in variable, vTexCoord, as well as new out variable, texCoord. This is data from our UV coordinates array, uploaded to OpenGL by Model::upload_2_server() member function. As you can see, the vertex shader doesn't do anything with UV coordinates, it simply passes the data through to the fragment shader. Nothing to change here.

  4. Open the fragment shader in Shaders\TextureShader_f.c file. The fragment shader receives the interpolated texCoord from the vertex shader. Also notice that it has the texture variable, already bound to texture unit zero by glActiveTexture() and glUniform1i() calls (as shown above):

    
    uniform sampler2D texture;
    
    

    The texture variable provides access to the actual image in GPU memory. To use the colors from the texture, we need to modify the old formula

    
        fColor = ambient + dif + spec;
    
    

    to a new, adding texel colors into the mix:

    
        fColor = ambient*0.5 + dif*0.5 + spec*0.5 + 0.5*texture2D(texture, newTexCoord);
    
    

    I am using factors of 0.5 for each component of the final color. You may tweak it to any proportion you like -- you should start feeling how flexible OpenGL is in this regard.

    A better way is to use texel color as a diffuse component:

    
        // Calculate the diffuse part
        float Kd = max (dot(N, L), 0.2);    // Intensity
        vec4 dif = Kd*texture2D(texture, texCoord*10);
        
        // Calculate the specular part. 
        float Ks = pow (max(dot(N, H), 0.0), shininess); // Intensity
        vec4 spec = Ks*specular;                         // ... and then color
        if (dot(N, L) < 0.0) {                // But only if the light is in front!
            spec = vec4(0.2, 0.2, 0.2, 1.0);
        }
    
        // Compute final color: 
        fColor = ambient*0.5 + dif + spec*0.5;
    
    
  5. Compile and run the program. Make sure everything works as expected. Try different models by uncommenting the corresponding MODEL_OBJ_FILENAME definitions. Remember to change the scale_amount variable if the object appears to be too small or too big on the screen.

  6. Open Shaders\TextureShader_f.c fragment shader. Observe what happens if you change the line

    
        newTexCoord = texCoord*10;
    
    

    to

    
        newTexCoord = texCoord;
    
    

    Multiplication by 10 makes UV coordinates repeating the texture ten times more often than the original. This permits texture resizing after appropriate parameters for minification, magnificaiton and repeating UVs are specified. (In our lab those preferences are handled by Model::upload_bitmap_texture() function.)

     


4. How to submit