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: exercises 08

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/data08/TP08.tgz
  2. If needed, edit the file main.pro to change paths
  3. To compile: qmake && make
  4. To run: ./tp08 file.off
  5. To edit: use either your preferred text editor or qtcreator

Shadow Mapping

The goal of these exercises is to familiarize yourself with basic shadow mapping techniques. You should obtain something like:




Default

The program renders a few objects on a plane without shadows.
Examine the file viewer.h / viewer.cpp

Exercise 1: examine the framebuffer object

To create the shadow map, we need to render the scene (depth) into a texture.
We thus first need to create a FBO that will be used to create the depth buffer.
  1. Look at the function createFBO:
    1. What is the role of the texture called _texDepth?
    2. What is the size of this texture (see _depthResol)?
    3. Why no colored textures are attached to the FBO (as we did before)?

Exercise 2: render the scene into the depth texture from the light point of view

Once the FBO created, we can draw the scene inside the associated depth texture, as before.
The only difference is that we only want to render the depth according to the light point of view.
We do not need any rendering here - just the depth that will be further used for testing shadows!
  1. Fill the function paintGL
    1. Bind the FBO (glBindFramebuffer), as before
    2. Specify in which buffer we want to draw:
      1. We do not want to draw in any color buffers!!!
      2. We simply want to create the depth map and this is automatically done by OpenGL during rasterization
      3. Then use glDrawBuffer(GL_NONE);
    3. Clear the depth buffer only! (glClear)
    4. Activate the appropriate shader program
    5. Set the viewport to render in a scene that have exactly the same resolution as the depth texture (glViewport)
    6. Draw the scene from the light (simply call to drawSceneFromLight())
    7. Desactivate the FBO (glBindFramebuffer(GL_FRAMEBUFFER,0))
  2. Fill the function drawSceneFromLight
    1. The function is similar to drawSceneFromCamera, except that
  3. Open the file shadow-map.vert
    1. look at shadow-map.vert and shadow-map.frag.
    2. Explain why there is nothing inside shadow-map.frag!

Exercise 3: testing and using the shadow map

Now the shadow map has been created, we want to send this texture to the second pass (for testing depths inside the rendering shader)
  1. Send the shadow map to the rendering  shader
    1. Choose a name for the shadowmap texture in the shader
    2. In drawSceneFromCamera: send the depth texture to the rendering shader
  2. Test it
    1. Launch the program and press the S key to see if the shadow map is ok.
    2. Warning: the size of the shadow map is different from the size of the viewport

Exercise 4: first shadows

We want to use the shadow map and compare its values with the geometry seen from the camera viewpoint.
  1. Project vertices in the light space (rendering.vert)
    1. In rendering.vert: project the current vertex in the light space using mvpDepthMat (the MVP of the light)
    2. Store the result in another variable that will be sent to the fragment shader
    3. Note: the obtained coordinates are comprised in the range [-1,1] and should be remapped in the range [0,1] before using them
  2. The shadow test (rendering.frag)
    1. Use the received coordinates in the fragment shader to perform the shadow test
    2. Update the visibility coefficient (variable v) according to the result of the test (decrease it in case the current point is in the shadow)
  3. Shadow acne
    1. Results should show the acne effect
    2. remove it by adding a small bias in the depth test:

Exercise 4: Percentage Closer Filtering

We want to avoid the aliasing effects by using the PCF filtering.
This technique is automatically provided by OpenGL using specific texture parameters
  1. In createFBO (viewer.cpp)
    1. Add the following parameters to the depth texture
    2. It will create a texture that is specialized for comparison tests
  2. In rendering.frag
    1. modify the declaration of the depth texture (sampler2D should be replaced by sampler2DShadow)
    2. use texture(shadowmap,vec3(shadcoord)) to test whether the current point is in the shadow or not. 


BONUS

Exercise 5: Soft shadows

We will simply use multiple PCF at different locations to mimic soft shadow effects.
  1. Poisson sampling
    1. make a loop to sample the shadow map at different locations
      1. You will use the given poissonDiskSamples to modify locations
      2. shadow xy coordinates can be displaced this way:
      3. shadcoord.xy+ poissonDisk[ind]/300.0
        1. ind = the current iteration (in the range [0,15])
        2. 300.0 = controls the size of the penumbra (not too much and not too small)
    2. Try to obtain the best possible shadows by manipulating
      1. the number of iterations
      2. the penumbra size
    3. Note: the visibility should be updated accordingly at each iteration (do not set it to 0 after one positive shadow test)
  2. Stratified poisson sampling
    1. Instead of using always the same samples from the poisson array, try using random samples based on the current screen coordinates
    2. int ind = int(16.0*random(gl_FragCoord.xyy, i))%16; where
    3. i is the current loop index
    4. ind will be used to look-up the randomized poisson sample

 
PREVIOUS: 08 - SHADOWS
NEXT: 09 - POST PROCESS