I am using a Deferred Rendering engine from Catalin Zima's tutorial:
His lighting shader returns the color of the light in the rgb channels and the specular component in the alpha channel. Here is how light gets accumulated:
Game.GraphicsDevice.SetRenderTarget(LightRT);
Game.GraphicsDevice.Clear(Color.Transparent);
Game.GraphicsDevice.BlendState = BlendState.AlphaBlend;
// Continuously draw 3d spheres with lighting pixel shader.
...
Game.GraphicsDevice.BlendState = BlendState.Opaque;
MSDN states that AlphaBlend field of the BlendState class uses the next formula for alphablending:
(source × Blend.SourceAlpha) + (destination × Blend.InvSourceAlpha),
where "source" is the color of the pixel returned by the shader and "destination" is the color of the pixel in the rendertarget.
My question is why do my colors are accumulated correctly in the Light rendertarget even when the new pixels' alphas equal zero? As a quick sanity check I ran the following code in the light's pixel shader:
float specularLight = 0;
float4 light4 = attenuation * lightIntensity * float4(diffuseLight.rgb,specularLight);
if (light4.a == 0)
light4 = 0;
return light4;
This prevents lighting from getting accumulated and, subsequently, drawn on the screen. But when I do the following:
float specularLight = 0;
float4 light4 = attenuation * lightIntensity * float4(diffuseLight.rgb,specularLight);
return light4;
The light is accumulated and drawn exactly where it needs to be. What am I missing? According to the formula above:
(source x 0) + (destination x 1) should equal destination, so the "LightRT" rendertarget must not change when I draw light spheres into it!
It feels like the GPU is using the Additive blend instead:
(source × Blend.One) + (destination × Blend.One)