9.2. Correct shadows from multiple light sources

A texture may be a shadow map projected from a light source. In our paper [X3D Shadow Maps] we have noted that the shadow should scale only the appropriate light source contribution. This allows to observe correct shadows from multiple light sources. This means that shadow map textures must be used in a different stage of the calculation than normal textures.

Our plugs idea allows to do this, in a clean and concise way. At the place where TextureShader is created in the pseudo-code from the previous section, we treat shadow maps specially. If the light source corresponding to the shadow map affects our shape then we do not apply the texture in a usual way. Instead, we call the Plug function to augment the specific light source shader with a shadow check, like this:

if Texture is GeneratedShadowMap and
   Texture.light affects the shape then
  Plug(fragment,
    'uniform sampler2DShadow shadowMap01;
     void PLUG_light_scale(inout float scale, ...)
     {
       scale *= shadow2DProj(shadowMap01, shadowMap01TexCoord).r;
     }', LightShader);

The simple call to shadow2DProj may be replaced with a variant of the Percentage Closer Filtering (see [GPU Gems PCF]).

The calculation of light effects has to be complicated a little to make it work. In our simple pseudo-code, we added the effects to the LightShader and then we immediately merged LightShader with the FinalShader. Now, we need to remember the LightShader value for a longer time, in case it should be augmented with a shadow map. Alternatively, we could search for corresponding shadow maps at the moment when LightShader is created.