Download the sources at
http://romain.vergne.free.fr/teaching/IS/data08/TP08.tgz
If needed, edit the file main.pro to change paths
To compile: qmake && make
To run: ./tp08 file.off
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
3 shaders are created:
the shader that will compute the shadow map (shadow-map.{vert,frag})
the shader that performs the rendering of the scene
(rendering.{vert,frag})
a shader that will only be used as a test shader for displaying the
created shadow map
In the function paintGL:
the rendering shader is activated
buffers are cleared
the scene is drawn from the camera (drawSceneFromCamera)
note, that, when pressing the S key, the test shader is activated
and a quad is drawn on the screen to show the shadow map
In the function drawSceneFromCamera:
The MVP matrix for the light point of view is computed (using an
orthographic projection for a directional light)
This matrix, as well as the camera matrices are sent to the
rendering shader
Other useful uniforms are also sent: textures and light
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.
Look at the function createFBO:
What is the role of the texture called _texDepth?
What is the size of this texture (see _depthResol)?
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!
Fill the function paintGL
Bind the FBO (glBindFramebuffer), as before
Specify in which buffer we want to draw:
We do not want to draw in any color buffers!!!
We simply want to create the depth map and this is automatically
done by OpenGL during rasterization
Then use glDrawBuffer(GL_NONE);
Clear the depth buffer only! (glClear)
Activate the appropriate shader program
Set the viewport to render in a scene that have exactly the same
resolution as the depth texture (glViewport)
Draw the scene from the light (simply call to drawSceneFromLight())
Desactivate the FBO (glBindFramebuffer(GL_FRAMEBUFFER,0))
Fill the function drawSceneFromLight
The function is similar to drawSceneFromCamera, except that
only the uniform MVP light matrix is sent to the shader (since we
only want to project vertices, without lighting/rendering anything)
Open the file shadow-map.vert
look at shadow-map.vert and shadow-map.frag.
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)
Send the shadow map to the rendering
shader
Choose a name for the shadowmap texture in the shader
In drawSceneFromCamera: send the depth texture to the rendering
shader
Test it
Launch the program and press the S key to see if the shadow map is
ok.
Warning: the size of the shadow map is different from the size of
the viewport
Set the viewport as fullscreen to see everything well
Exercise 4: first shadows
We want to use the shadow map and compare its values with the geometry seen
from the camera viewpoint.
Project vertices in the light space
(rendering.vert)
In rendering.vert: project the current vertex in the light space
using mvpDepthMat (the MVP of the light)
It will allow to compare depth values in the same space (the space
of the light)
Store the result in another variable that will be sent to the
fragment shader
Note: the obtained coordinates are comprised in the range [-1,1] and
should be remapped in the range [0,1] before using them
Because the depth texture has also been remapped this way!
Remember that we have to compare values in exactly the same space.
The shadow test (rendering.frag)
Use the received coordinates in the fragment shader to perform the
shadow test
the xy values can be used to access the texture (the xy
coordinates of the current point in light space)
the z value should be compared with the one that in in the shadow
map
Update the visibility coefficient (variable v) according to the
result of the test (decrease it in case the current point is in the
shadow)
Test the result
Shadow acne
Results should show the acne effect
remove it by adding a small bias in the depth test:
bias = 0.005; for instance
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