Author: Romain Vergne (website)
Please cite my name and add a link to my web page if you use this course

Image synthesis and OpenGL: exercices 05

Setup

We will use Linux and the following libraries:

Installing sources. In a terminal, do:
  1. Download the sources at http://romain.vergne.free.fr/teaching/IS/data05/TP05.tgz
  2. If needed, edit the file main.pro to change paths
  3. To compile: qmake && make
  4. To run: ./tp05 models/file.off
  5. To edit: use either your preferred text editor or qtcreator

Textures and mipmapping

The goal of these exercises is to familiarize yourself with OpenGL textures and mipmapping. You should obtain something like this:





Exercice 1: prepare the shader

The source code contains the same files/classes as before
By default, the program loads a mesh and uses a Phong shader to display it, using vertex array objects
The attributes sent to the shader are
Look inside meshLoader.h. Texture coordinates are now available (array coords). One uv texture coordinate has been computed per vertex using a spherical mapping:
  1. We now need to be able to access texture coordinates in the vertex shader. By default, only positions and normals and sent.
  2. Modify the phong shader:
  3. Test if coordinates are available by displaying them in the shader using false colors:

Exercice 2: Creating a texture

As with other OpenGL objects, a texture is controlled via a uniquely defined integer value.
  1. Complete the function createTextures. The creation of a texture necessitates the following operations:
    1. glGenTextures(...); // generate a texture buffer in the GPU memory, controlled by an ID (this ID should be accessible - i.e. stored in the viewer.h file)
    2. glBindTexture(GL_TEXTURE_2D,...); // activate this texture - all the following functions will operate on this texture
    3. glTexImage2D(GL_TEXTURE_2D,...); // load the image into the GPU memory
    4. glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,...); // choose the filtering mode for minification
    5. glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,...); // choose the filtering mode for magnification
    6. glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,...); // choose the border mode in the U direction
    7. glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,...); // choose the border mode in the V direction
    8. Do not forget to delete the texture in the destructor of the viewer using glDeleteTextures(...);

Exercice 3: Using the texture in the shader 

The texture object is linked to the shader using the same way as for other uniform variables.
  1. Make the link between the texture and the shader
    1. As textures are already in the memory, we do not send them directly, but simply state which texture to use (via the texture location). In enableShader:
  2. Use the texture in the fragment shader
  3. Try to multiply texture coordinates by a scalar value (in the vertex or fragment shader)

Exercice 4: Automatic mipmapping

  1. Use glGenerateMipmap(GL_TEXTURE_2D); to generate mipmaps associated with the input texture. You will need to:
    1. call this function a first time in createTextures() in order to initialize GPU memory and generate the mipmaps
    2. call this function at runtime (in enableShader, after binding the texture) to specify that you use the mipmaps
    3. Try the different function seen in the course for the minification filtering
  2. Combine the texture color with the Phong color using a multiplication to obtain the final rendering.





BONUS

Exercice 5: Manual mipmapping

Copy your viewer.h / viewer.cpp to keep the previous results somewhere.
  1. Generate mipmaps manually using "textures/mipmap-test*.png"
    1. To manually generate mipmaps, simply use glTexImage2D(...) multiple times with the corresponding mipmap levels.
    2. Important: you will need to specify the minimal and maximal level (in this case 0 and 3) in the texture parameters
      1. glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_BASE_LEVEL,0);
      2. glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAX_LEVEL,3);
    3. Note: do not forget to remove (or comment) the calls to glGenerateMipmap() - we do not need it anymore since we make it by hand.
  2. What do you observe?

Exercice 6: Hatching (rendering inspired from the Tonal Art Maps)

We are going to use 6 mipmapped textures on top of the object. We will choose which texture to apply accoding to the light intensity at each point of the surface.

As these textures only contain grey values, we can use only 2 textures to store all the data for one level in RGB channels (see textures/tone_*.tga).
  1. Load "textures/tone_123*.png" in the current texture instead of the false colors.
  2. Create a new texture (new Id, new gen, new bind, new param, etc...) in order to load "textures/tone_456*.png" in the same way
    1. send it to the shader in the texture unit 1 (unit 0 is already used by the first texture)
  3. In the shader, you can now access 2 textures, each containing 3 gray values (stored in the RGB channels). The goal is to choose which on of this grey to use depending on light intensity.
    1. The 6 grey values correspond to the x-axis of the textures above. y-axis is automatically chosen thanks to OpenGL mipmaps
    1. The grey value may be interpolated between the 2 closest textures to obtain smooth effect:
      1. you can use the mix GLSL function that interpolates 2 values (look at ther GLSL spec and play with given functions to obtain a nice rendering.
      1. Ideally you can take the weighted mean value based on gaussian distance between the light intensity and the textures:
 \( \frac{\sum_i greyVal_i \ e^{-d_i/\sigma^2}}{\sum_i e^{-d_i/\sigma^2}} \), with \( d = \) distance between light intensity and the corresponding texture
 
PREVIOUS: 05 - TEXTURES
NEXT: 06 - APPEARANCE