Screen sized quad blend with rendered scene and shadows

http://i17.photobucket.com/albums/b95/julesthe/scene1.jpg

the url brings you to an image that shows the current problem I am facing.

I render a screen sized quad (background image) and then set some device blending operations before rendering my scene objects. as you can see, where the shadow is cast, the blending behaves as I would expect, making this area show through but it is slightly darker then the background. My problem is that I cannot get rid of the white. If I blend using alpha testing:

device.RenderState.AlphaTestEnable = true;

device.RenderState.ReferenceAlpha = 1;

device.RenderState.AlphaFunction = Compare.Less;

The white "disappears" as I would expect, but the background disappears also. If I blend using the following:

device.RenderState.AlphaBlendEnable = true;

device.RenderState.SourceBlend = Blend.SourceAlpha;

device.RenderState.DestinationBlend = Blend.DestinationColor;

you get the image at the URL posted. In both cases, the shadow being cast behaves as I expected, blending the background color. I just cannot figure out what my setting needs to be to handle the white. Can someone chime in with thoughts



Answer this question

Screen sized quad blend with rendered scene and shadows

  • beezorz

    I understand that the shadow parts have an alpha that's not zero. The non shadow parts have an alpha that's one (opaque). Any reason they're not cleared with a zero alpha

  • PSM

    I'm not sure where values in the alpha and color channels are coming from, could you clarify that a bit

    Your use of Blend.DestinationColor is causing the background to darken in the dark areas of the shadow map, by multiplying the background color by itself, not because the background is blending with the shadow.

    It would be helpful to know what is in the alpha channel. Could you post an image using these blending states, and with a solid white background rather than the current background image:

    device.RenderState.SourceBlend = Blend.Zero
    device.RenderState.DestinationBlend = Blend.SrcAlpha

    That will provide an image representing the alpha channel output, so we can understand what is being rendered better.


  • Beppone

    Tried that along with many other combinations and nothing has worked y et.
  • KarthikNarasimhan

    It's un-clear from your screen shot what the white is, and what is supposed to be shadow, and what is supposed to be background.

    Perahps you could post a number of screen shots, starting with the background, then adding your geometry, then adding what the shadow is supposed to be, and then, last, the entire thing that's not working right. Posting screens in wireframe would help describe the problem, as well.

    It would also help if you described what your inputs are, what you're trying to accomplish, and how you're currently trying to accomplish it.



  • huangyao2005

    Setting SourceBlend to SrcAlpha and DestBlend to InvSrcAlpha will work, but there are requirements for this.

    The requirements are as follows:
    The shadow texture (source in this case) must have it's alpha values set so that the portions that have no shadow have an alpha value of 0 and those that are shadowed have an alpha value > 0. The second requirement is that the color of shadowed areas on the shadow texture are completelly black (0.0, 0.0, 0.0).

    Ok, lets look into the blending function now for a non shadowed area. This is the forumla for blending:

    finalColor = sourceColor x sourceBlendFactor + destColor x destBlendFactor;
    ( x denotes a component wise multiplication)

    In a non shadowed area since we're using SrcAlpha that means sourceBlendFactor = { 0.0, 0.0, 0.0 } and destBlendFactor is 1 - sourceBlendFactor = { 1.0, 1.0, 1.0 }. This would give the following setup, assuming the background color is red ( 1.0, 0.0, 0.0 ) for the given pixel.

    finalColor = { 1.0, 1.0, 1.0 } x { 0.0, 0.0, 0.0 } + { 1.0, 0.0, 0.0 } x { 1.0, 1.0, 1.0 };

    finalColor = { 0.0, 0.0, 0.0 } + { 1.0, 0.0, 0.0 } = { 1.0, 0.0, 0.0 } which is just the same as destColor. In other words the red color your background already had.

    Now lets just say I want to use an alpha value of 0.5 (50%) for the shadowed areas on the shadow texture. Using the same red color for a shadowed pixel we get the following formula (remember shadowed areas are all black):

    finalColor = { 0.0, 0.0, 0.0 } x { 0.5, 0.5, 0.5 } + { 1.0, 0.0, 0.0 } x { 0.5, 0.5, 0.5 };

    finalColor = { 0.0, 0.0, 0.0 } + { 0.5, 0.0, 0.0 } = { 0.5, 0.0, 0.0 };

    This is simply a much darker red color, or a shadowed red if you like. Something you have to notice here is that in fact the color contribution from the shadow texture is zero in both the shadowed and non shadowed case. This is because the shadow color is black (0.0, 0.0, 0.0) and the non shadow alpha value is 0.0. The degree of shadowing is simply decided by the alpha value of shadowed areas of the shadow texture. The alpha value is the percentage the background color will be reduced by, so and alpha value of 0.8 (80%) will reduce the red from { 1.0, 0.0, 0.0 } to { 0.2, 0.0, 0.0 }.

    There's one problem with this approach, and that is that you can't see gradient colors on your shadow texture as shadowed areas have to be all black. If you for some reason would like different color shadows this will also fail, but if the requirements for this do not cause any problems it should be pretty easy to wrap your head around as to how things work behind the scenes.

    Hope this helps,
    /Thomas


  • Scav

    just background:

    http://i17.photobucket.com/albums/b95/julesthe/bg.jpg

    geometry (no background) with shadows:

    http://i17.photobucket.com/albums/b95/julesthe/geo_with_shadows.jpg

    geometry (no background) with shadow on/off (white/black):
    http://i17.photobucket.com/albums/b95/julesthe/geo_alpha.jpg

    bad blend (final attempt):

    http://i17.photobucket.com/albums/b95/julesthe/screen_with_errors.jpg

    shadow map declarations:

    ShadowMap = new Texture(e.Device, SHADOW_MAP_SIZE, SHADOW_MAP_SIZE, 1, Usage.RenderTarget, Format.R32F, Pool.Default);

    StencilSurface = e.Device.CreateDepthStencilSurface(SHADOW_MAP_SIZE, SHADOW_MAP_SIZE, e.Device.PresentationParameters.AutoDepthStencilFormat, MultiSampleType.None, 0, true);

    VertexDeclaration for geometry:

    VertexElement[] decl1 = new VertexElement[]

    {

    new VertexElement(0, 0, DeclarationType.Float3,

    DeclarationMethod.Default,

    DeclarationUsage.Position, 0),

    new VertexElement(0, 12, DeclarationType.Float3,

    DeclarationMethod.Default,

    DeclarationUsage.Normal, 0),

    VertexElement.VertexDeclarationEnd

    };

    Background vertex format: CustomVertex.TransformedTextured.Format

    What I am trying to accomplish:

    Everything in the final shot is working except for the fact that I need the white to "disappear". The darker colors are blending correctly, so I cannot understand why the white isn't blending. How do I make the white blend correctly

    Blend value:

    device.RenderState.AlphaBlendEnable = true;

    device.RenderState.SourceBlend = Blend.SourceAlpha;

    device.RenderState.DestinationBlend = Blend.DestinationColor;


  • GMG_NetCoder

    Just a guess, but this line:

    device.RenderState.DestinationBlend = Blend.DestinationColor;

    Should typically be:

    device.RenderState.DestinationBlend = Blend.InvSrcAlpha;



  • Screen sized quad blend with rendered scene and shadows