Download - Shadow Mapping
Shadow Mapping
RTR Team 2009 1
RTR Team 2009 2
Why Shadows?
3
Why Shadows?
RTR Team 2009
4
Why Shadows?
Shadows ...... make a scene look more three-dimensional
... tell us about the positions of objects relative to each other
... tell us where the light comes from
... should really be there
RTR Team 2009
5
Shadow Determination
Several techniques, e.g.Shadow Mapping
Shadow Volumes
Let’s take a closer look at shadow mapping2 pass algorithm
fast on today’s GPUs
relatively easy to implement
RTR Team 2009
6
Shadow Mapping Overview
1st pass:we assume the light source has a “view frustum” just like a camerarender scene from light source’s positionsave depth values onlywe end up with a shadow (depth-) map
2nd pass:render scene as usual, but transform vertices to light space, toofor each fragment, compare rasterized fragment depth to previously stored depth (read it from shadow map)
zfragment > zfrom_shadow_map => fragment lies in shadow
both fragments must be in light space!!!RTR Team 2009
7
Scene – “Meta” View
EyeLight Source
RTR Team 2009
8
Scene – Light Source View
RTR Team 2009
9
Scene – Light Source View (Depth Only)
RTR Team 2009
10
Scene – Eye View
RTR Team 2009
11
Shadowed Fragment
Eye View
“Meta“ View
RTR Team 2009
12
Shadowed Fragment
“Meta“ View
Fragment DistanceDistance
from Shadow
Map
Eye View
RTR Team 2009
13
Lit Fragment
“Meta“ View
Eye View
RTR Team 2009
14
Lit Fragment
“Meta“ View
Fragment Distance Distancefrom
ShadowMap
RTR Team 2009
Eye View
15
Coordinate Systems
Eye Light World
Model
RTR Team 2009
16
Coordinate Systems
Eye
Light
World
Model
RTR Team 2009
17
Transforming to World Space
Eye
Light
World
Model
RTR Team 2009
18
Transforming to Light Space
Eye
Light
World
Model
Light (Vlight)
rendering from the light source‘s point of view
RTR Team 2009
19
Transforming to Eye Space
Eye
Light
World
Model
rendering from the eye‘s point of view
RTR Team 2009
20
1st pass: Create Shadow Map
Create an FBO
// create the texture we'll use for the shadowmapglGenTextures(1, &shadow_tex_ID);glBindTexture(GL_TEXTURE_2D, shadow_tex_ID);glTexImage2D (GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, SM_width, SM_height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
glGenFramebuffers(1, &shadow_FBO); glBindFramebuffer(GL_FRAMEBUFFER, shadow_FBO);glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadow_tex_ID, 0);glDrawBuffer(GL_NONE); // essential for depth-only FBOs!!!glReadBuffer(GL_NONE); // essential for depth-only FBOs!!!
// then, just before renderingglBindFramebuffer(GL_FRAMEBUFFER, shadow_FBO);
// create the texture we'll use for the shadowmapglGenTextures(1, &shadow_tex_ID);glBindTexture(GL_TEXTURE_2D, shadow_tex_ID);glTexImage2D (GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, SM_width, SM_height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
glGenFramebuffers(1, &shadow_FBO); glBindFramebuffer(GL_FRAMEBUFFER, shadow_FBO);glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadow_tex_ID, 0);glDrawBuffer(GL_NONE); // essential for depth-only FBOs!!!glReadBuffer(GL_NONE); // essential for depth-only FBOs!!!
// then, just before renderingglBindFramebuffer(GL_FRAMEBUFFER, shadow_FBO);
RTR Team 2009
21
1st pass: Create Shadow Map
The “view” matrix must be set to Vlight
Note: No projection matrix used up to now!but light-”camera” involves another projection!
Turn off all effects when rendering to the shadow map
No textures, lighting, etc.
RTR Team 2009
22
2nd pass: Render from Eye’s POV
Transform vertices to eye space and project as usual
p‘ = Pcam * Vcam * M * p
RTR Team 2009
23
2nd pass: Render from Eye’s POV
Also transform vertices to light space and projectone possibility: Use Vcam
-1, the inverse view matrix of the camera
pproj_lightspace = (Plight * Vlight * Vcam-1) * Vcam * M * p
save as texture coordinates for accessing shadow map
Note: the light‘s projection matrix may be different from the eye‘s projection matrix
RTR Team 2009
24
2nd pass: Render from Eye’s POV
one last issue...
plightspace is in the interval [-1…..+1]
shadow map coordinates in range [0….+1]
scaling/translation necessary (*0.5, +0.5)
SMtexcoords = (Mtranslate*Mscale*Plight*Vlight*Vcam-1)* Vcam * M * p
RTR Team 2009
Shadow Mapping: Vertex Shader
texture_matrix = (Mtranslate*Mscale*Plight*Vlight*Vcam-1)
#version 140uniform mat4 M; // model matrixuniform mat4 V_cam; // view matrix for the camerauniform mat4 P_cam; // projection matrix for the camerauniform mat4 texture_matrix;
in vec4 vertex; // from the applicationout vec4 SM_tex_coord; // pass on to the FS
void main(void) {// standard transformation gl_Position = P_cam * V_cam * M * vertex;
// shadow texture coords in projected light space
SM_tex_coord = texture_matrix * V_cam * M * vertex;}
#version 140uniform mat4 M; // model matrixuniform mat4 V_cam; // view matrix for the camerauniform mat4 P_cam; // projection matrix for the camerauniform mat4 texture_matrix;
in vec4 vertex; // from the applicationout vec4 SM_tex_coord; // pass on to the FS
void main(void) {// standard transformation gl_Position = P_cam * V_cam * M * vertex;
// shadow texture coords in projected light space
SM_tex_coord = texture_matrix * V_cam * M * vertex;}
25RTR Team 2009
Shadow Mapping: Fragment Shader
Fragment Shader:
#version 140uniform sampler2D shadow_map;
in vec4 SM_tex_coord; // passed on from VSout vec4 fragment_color; // final fragment color destination
void main(void) {// note the perspective division!vec3 tex_coords =
SM_tex_coord.xyz/SM_tex_coord.w;
// read depth value from shadow map float depth = texture(shadow_map,
tex_coords.xy).r;
float inShadow = (depth < tex_coords.z) ? 1.0 : 0.0;
// do something with that value ...}
#version 140uniform sampler2D shadow_map;
in vec4 SM_tex_coord; // passed on from VSout vec4 fragment_color; // final fragment color destination
void main(void) {// note the perspective division!vec3 tex_coords =
SM_tex_coord.xyz/SM_tex_coord.w;
// read depth value from shadow map float depth = texture(shadow_map,
tex_coords.xy).r;
float inShadow = (depth < tex_coords.z) ? 1.0 : 0.0;
// do something with that value ...}
26RTR Team 2009
Add Offset to polygons when rendering shadow map
Artifacts
glPolygonOffset(1.1, 4.0); // these values work wellglPolygonOffset(1.1, 4.0); // these values work well
27RTR Team 2009
Decrease ambient term
Filter shadow map ...
Artifacts
28RTR Team 2009
GPU can do depth compare in hardware
and also PCF!
Filter shadow map
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
29RTR Team 2009
Shadow Mapping: Fragment Shader
Fragment Shader for Hardware PCF:
#version 140uniform sampler2DShadow shadow_map;
in vec4 SM_tex_coord; // passed on from VSout vec4 fragment_color; // final fragment color destination
void main(void) {
float shadow = textureProj(shadow_map, SM_tex_coord); // do something with that value ...
}
#version 140uniform sampler2DShadow shadow_map;
in vec4 SM_tex_coord; // passed on from VSout vec4 fragment_color; // final fragment color destination
void main(void) {
float shadow = textureProj(shadow_map, SM_tex_coord); // do something with that value ...
}
30RTR Team 2009
References
www.opengl.org/registryhttp://www.opengl.org/registry/doc/glspec31undep.20090528.pdf
http://www.opengl.org/registry/doc/GLSLangSpec.Full.1.40.07.pdf
31RTR Team 2009