
Hard shadows destroy the realism of a scene. Soft shadows give a better clue about relation ship between objects in scene than hard shadows, the shadows become shaper when objects contact with others and softer when they goes away. Hence, we need soft shadows in order to improve the visual quality of the scene. In my final project I try to implement the Percentage Closer Soft Shadow method (PCSS) that combine hardware shadow mapping with adaptive percentage closer filter to archive a perceptually accurate soft shadow. That method was proposed by Randima Fernando from NVIDIA Corporation, in the paper "Percentage-Closer Soft Shadows". This approach has some advantages:
Fast rendering time : this method can be done in hardware and for real-time applications like games as shadow map has fixed size, the complexity of algorithms is linear depend on the average depth complexity of the scene not the whole scene complexity
Generates perceptually accurate soft shadows
Easy setup : Requires no preprocessing, post-processing, or additional geometry (like in shadow volume)
Uses a single light source sample : one shadow map
Ease of integration : works with alpha testing, displacement mapping, bump mapping
The idea of PCSS is based on the observation that when the size of Percentage Closer Filter increases, the resulting shadow become softer, so that we could simulate the soft shadow by adaptive changing the size of filter. The algorithm requires 3 steps :
Blocker search :search the shadow map and average the depths that are closer to the light source than to the point being shaded
Penumbra estimation : Using a parallel planes approximation, we estimate the penumbra width based on the light size and blocker/receiver distances from the light
Filtering: perform a typical PCF on the shadow map using a kernel size proportional to the penumbra estimate from Step 2


2.1 Development Platform
Operating System: Window XP Media Center
Microsoft Visual Studio 6.0
OpenGL version 2.0, Glut version 2.7.6, Glew 1.3.3
GLSL shading languages
Geforce 6600 GT
2.2 Compile
Project file include:
OpenGL4.cpp: main program
v1.c,f1.c: Vertex shader / fragment shader for one pass reflect/refract combine effect for glass Dragon base on Fresnel Method
v2.c,f2.c: Vertex shader / fragment shader for bump mappinng the floor, the cube and torus
v3.c,f3.c: Vertex shader / fragment shader for reflective bump mappinng the sphere
”Texture.cpp” : texture reading function. “Texture.h” is the suppoting header
“glm.cpp”: model reading functions “glm.h” is the supporting header
"glext.h": the file prototype for OpenGL extention function
"texfile.cpp","texfile.h" read the GLSL file to compile
"Quaternion.cpp" to compute the inverse view matrix
Compiling:
Double-clicking on OpenGL5.sln. The Visual C++ workspace will open
Fress F7 to compile
Fress F5 to run
Control Key
Press arrow key to manipulate the camera view
Manipulation of the whole scene using the mouse (rotate, pan, zoom)
Change the size of the light source by "+" : increase size, '-' reduce size
Stop/ start animation by the key stroke 's'
Press "x","y", "z "/ "X","Y","Z" to manipulate the light source position
To make the demonstration more interesting (like in a real games) I have incorporated the shadow mapping with some special effects like:
Projective texture to simulate spot light effect
Skybox to improve the scene
Bump mapping the floor, cube, donut and sphere, it takes time to figured out the parametric equations for each surface to compute the tangent , normal and bi normal vectors.
Reflective bump mapping for the sphere to make it look like a real metal sphere, you can see the reflected image of box on the surface of the sphere. This effect is the combiner effect between environment mapping and bump mapping with the third texture that contains the reflective factor of the surface that have value 1 if the surface is reflective and 0 if not.

Fresnel Reflection for glass dragon: I use one pass reflection technique, one of interesting properties of this effect is that it has different refract angle for each of light components so that it look much cooler than simple refraction.


Complete reflect image / refract image with the same index for each color components RGB

Partial reflect/refract image with the same index for each color components RGB

Fresnel Reflection image with the different index for each color components RGB
Glowing light source: I myself invent this technique. When I try to simulate a glowing light source by drawing a solid sphere at the light source, I realize that because the sphere and the light source share the same position, it could not be lit by the light source that results a dark sphere. There are some solutions : make another light source near the position of the sphere, or just disable lighting and draw a white sphere. However this two approach don't give good result: the first one will produce some reflective light sources like Moon (however you know there always a part of moon receive no light so that it emits nothing), the second method give no glowing light. The solution I proposed is that : simulating glowing light by drawing a light glowing textured polygon at the position of the light source that always faced to the eye and adaptively changing the size of polygon base on the size of light source. The final result is satisfied. (as you can see in the result figures when the light size is changed)
The idea is quite simple, however it 's not easy to implement. To archive the fast rendering time for real time applications we have to implement this algorithm in hardware shading language. There are 3 common use hardware languages: HLSL developed by Microsoft that well incorporated with Direct X, CG from Nvidia work well both with DirectX and OpenGL and especially for Nvidia Card, and GLSL (OpenGL Shading Language) defined by the Architectural Review Board of OpenGL a new standard to the OpenGL 2.0 which includes the GPU based shading into the traditional OpenGL pipeline. These shading languages generally very similar include those function call. However, from a language point of view, I personally find GLSL a little nicer some some reasons:
GLSL is directed by the OpenGL ARB, rather than a single company
Code is passed directly to the GL driver as ASCII, you don't have compile your GLSL code and you don't have to link any other libraries or include new headers.
It well integrate with OpenGL and share common knowledge, you can access the traditional state variables of the fixed function pipeline from GLSL, something similar is not possible with DirectX HLSL or CG.
Better debugging : it's very hard to debug Shading Languages program, however for some bugs like languages grammar GLSL give a better solution that I can quickly identify the errors.
However GLSL could not be compile with older graphic card (like in the Window Labs)
Learning experiences:
Working with shading languages is not easy, there's some common difficulties:
Hard to debug program: there's no debugging tools for shading languages, when something happens It takes a lot of time to understanding why
There a lot of bug with compiler: some program could compiled well in some graphic card but maybe produced some rubbish in other machines. And the same machine could produced different results with different profiles and most of them make no sense.
Bad division: I have some terrible experience with division, it's likely that CG and GLSL don't complied well with division so that you could have totally different result with division by 2.0 and multiplication by 0.5, so that for almost case i chose multiplication as the alternate methods.
Bad loop: for some graphic card that don't compatible with Open Shading languages 2.0, using loop in program could produce unpredictable result (however this phenomenon still happened with some modern card, like the one I have GForce 6600 GT)
Poorly precision float: this is the main reason for some unpredictable result and a lot of bugs. You have to know some techniques from Scientific Computing to ensure a good results. This take me a lot of time to apply blocker finding method because it require the division between 2 factor that have totally different magnitude so that it's always overflow the float precision.
Debugging time take more than 60% time I spend for project (approximately 30 hours). It takes time to learn a new languages and more time to use it efficiently.

a. Hard shadow Mapping (size of light source is approximately 0)
the light appear as a small dot on the screen

b. Fake soft shadow using uniform PCF filter
The shadow edge become softer every where even where two object get in touch, it still look good for most of the games.
A good new is that uniform PCF filter now can be apply with no cost with new graphic card from nVida and ATI.

c. Soft Shadow using Adaptive PCF filter with different light size
the shadow become softer at the edge especially for edges near the light (shadow edges near the viewer) and near the hard shadow for edges that touch other objects

an even become more softer with the change of size of the light source
A current updated demo results:

One of the problem with shadow mapping method is that when the light source is very far away like sun like the resolution of shadow map goes down so that the result is become more coarse, shadow quality reduce a lot. There are some solution for this problem such as Perspective Shadow Mapping, or Trapezoidal Shadow Maps. Other approach are hybrid method that integrate both shadow mapping and shadow volume to reach higher shadow qualities. I would like to try all this method, and do some research to make a comparison and may find a better (quality/speed) for shadow issue.
FERNANDO, R, Percentage-Closer Soft Shadows, NVIDIA Corporation
HASENFRATZ, J., A Survey of Real Time Soft Shadow Algorithms. Computer Graphics Forum, Vol. 22, No. 4 (December 2003)
Light House, GLSL Turorial, www.lighthouse3d.com/opengl/glsl
EVERITT , Hardware Shadow Mapping , http://developer.nvidia.com/object/hwshadowmap_paper.html
MARCO, Skyboxes without Seams, http://home.planet.nl/~monstrous/skybox.html
DREIJER, Bump Mapping Using CG, http://www.blacksmith-studios.dk/projects/downloads/bumpmapping_using_cg.php
WLOKA, M., Freshnel Reflection , NVIDIA Corporation