Thread: Direct3D Alpha Blend with Lighting ?

  1. #1
    Registered User
    Join Date
    Oct 2008
    Posts
    84

    Direct3D Alpha Blend with Lighting ?

    Hi,

    I was working with the microsoft shadow volume demo and I was trying to modify the alpha blending states so that i could load a png with a transparent background. I am trying to texture it onto a 3D model. It works fine but the moment I turn the lights on, the transparent background starts to become visible.

    My blending states are like this

    Code:
    pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
    pd3dDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
    pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
    pd3dDevice->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA);
    I am using the microsoft shadow volume demo and did not write the lighting shader myself but I believe it is per pixel lighting. I have attached the shader.

    Could someone please let me know how I can maintain the transparency of the png when the lights are turned on ?

    Also, does anyone know if theres a way to ignore black pixels or to conduct a color key without using the LoadTextureFromFile method ?

    Any help is appreciated.
    Thank You.

  2. #2
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Code:
    pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
    pd3dDevice->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA);
    Should be:
    Code:
    pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
    pd3dDevice->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA);
    If the alpha value is not exactly 0 then you will see the quad around the object albeit very faint.

  3. #3
    Registered User
    Join Date
    Oct 2008
    Posts
    84
    Thank you for your reply. I tried it but I'm still getting the same result. I've checked the file has an alpha of zero and It works fine as long as the lights are off. As soon as I turn on a light and its within the range of the png..I start to see a quad fading in as I turn on more lights.

    I'm guessing that the quad is still there even though its not being rendered, so when it comes in range of the light, it gets lit up causing its alpha to change.

    Is there any way to make the light not affect transparent pixels ? Please let me know ?

    Thanks!

  4. #4
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    It should not affect transparent pixels. Lighting has nothing to do with transparency. Transparency is figured out at the rasterization level. If you have the alpha set to 0 for transparent then those two render states should work. Alpha has nothing to do with lighting.

    Perhaps you should post the shader code - most importantly the pixel shader since per-pixel lighting will be done there.
    Last edited by VirtualAce; 07-05-2009 at 10:16 AM.

  5. #5
    Registered User
    Join Date
    Oct 2008
    Posts
    84
    Oh..I see,I dont know why its not working then. I attached the shader in the first post. The only techniques being used are the renderscene and rendercsene ambient. Could you please let me know theres something in it which is causing this ? I haven't done much shader programming before and not quite sure how it works!..thank you!

    here is the main code for computing the ligthting..

    Code:
    void VertSceneAmbient( float4 vPos : POSITION,
                           float2 vTex0 : TEXCOORD0,
                           out float4 oPos : POSITION,
                           out float2 oTex0 : TEXCOORD0 )
    {
        // Transform the position from object space to homogeneous projection space
        oPos = mul( vPos, g_mWorldViewProjection );
    
        // Just copy the texture coordinate through
        oTex0 = vTex0;
    }
    
    
    float4 PixSceneAmbient( float2 Tex0 : TEXCOORD0 ) : COLOR0
    {
        // Lookup mesh texture and modulate it with material and ambient amount
        return g_vAmbient * tex2D( g_samScene, Tex0 ) * g_vMatColor;
    }
    
    
    void VertScene( float4 vPos : POSITION,
                    float3 vNormal : NORMAL,
                    f
    Last edited by VirtualAce; 07-05-2009 at 09:23 PM.

  6. #6
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Could you please repost with code tags? I tried to add them but my internet locked up during the submit. It obviously did not send all of the data during the lock up b/c it messed your original post up.

  7. #7
    Registered User
    Join Date
    Oct 2008
    Posts
    84
    Oh, I am extremely sorry. Here is the edited version
    Code:
    void VertSceneAmbient( float4 vPos : POSITION,
    float2 vTex0 : TEXCOORD0,
    out float4 oPos : POSITION,
    out float2 oTex0 : TEXCOORD0 )
    {
                // Transform the position from object space to homogeneous projection space
               oPos = mul( vPos, g_mWorldViewProjection );
    
               // Just copy the texture coordinate through
               oTex0 = vTex0;
    }
    
    
    float4 PixSceneAmbient( float2 Tex0 : TEXCOORD0 ) : COLOR0
    {
          // Lookup mesh texture and modulate it with material and ambient amount
          return g_vAmbient * tex2D( g_samScene, Tex0 ) * g_vMatColor;
    }
    
    
    void VertScene( float4 vPos : POSITION,
    float3 vNormal : NORMAL,
    float2 vTex0 : TEXCOORD0,
    out float4 oPos : POSITION,
    out float4 ViewPos : TEXCOORD0,
    out float3 ViewNormal : TEXCOORD1,
    out float2 oTex0 : TEXCOORD2,
    out float4 oDiffuse : TEXCOORD3 )
    {
         // Transform the position from view space to homogeneous projection space
          oPos = mul( vPos, g_mWorldViewProjection );
    
    // Compute view space position ViewPos = mul( vPos, g_mWorldView ); // Compute world space normal ViewNormal = normalize( mul( vNormal, (float3x3)g_mWorldView ) ); // Modulate material with light to obtain diffuse oDiffuse = g_vMatColor * g_vLightColor; // Just copy the texture coordinate through oTex0 = vTex0;
    } float4 PixScene( float4 ViewPos : TEXCOORD0, float3 ViewNormal : TEXCOORD1, float2 Tex0 : TEXCOORD2, float4 Diffuse : TEXCOORD3 ) : COLOR0 {
    // Pixel to light vector float3 L = g_vLightView - ViewPos; float LenSq = dot( L, L ); L = normalize( L ); // Compute lighting amount float4 I = saturate( dot( normalize( ViewNormal ), L ) ) * Diffuse * (LIGHT_FALLOFF * LIGHT_FALLOFF) / LenSq; // Lookup mesh texture and modulate it with diffuse // return float4( tex2D( g_samScene, Tex0 ).xyz, 1.0f ) * I; float4 returnColor = tex2D( g_samScene, Tex0 ); returnColor.rgb *= I; return returnColor;
    } technique RenderScene { pass P0 {
    VertexShader = compile vs_2_0 VertScene(); PixelShader = compile ps_2_0 PixScene(); ZEnable = true; ZFunc = LessEqual; StencilEnable = true; AlphaBlendEnable = true; BlendOp = Add; SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; StencilRef = 1; StencilFunc = Greater; StencilPass = Keep;
    } }
    Last edited by rocketman03; 07-05-2009 at 09:36 PM.

  8. #8
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    The pixel shader is doing standard cosine lighting and standard falloff calculations.

    This:
    Code:
    returnColor.rgb *= I;
    ...looks a bit suspect. The commented line above it is even more suspect since it will always return 1.0f in alpha if the alpha in the diffuse is 1.0f.

    Try multiplying returnColor by I but don't specify which components to multiply.

    Code:
    ...
    return returnColor * I;
    This should return:

    float4(returnColor.r * I.r,returnColor.g * I.g,returnColor.b * I.b,returnColor.a * I.a);

    Therefore if returnColor or more appropriately the source texture alpha is 0.0f and diffuse alpha is 1.0f you will get a returnColor alpha of 0.0f. The only condition in which you will get a non-zero alpha in returnColor is if both source color alpha is non-zero and diffuse color alpha is non-zero. Any other combination will yield zero alpha.

    I'm also assuming you are using ID3DXEffect and are allowing it to handle the state changes. You can tell ID3DXEffect to not save state changes. In this case you would want to ensure that alpha testing was off otherwise you will get incorrect results. Make sure that alpha test and alpha blend are never both enabled at the same time.
    Last edited by VirtualAce; 07-06-2009 at 12:15 AM.

  9. #9
    Registered User
    Join Date
    Oct 2008
    Posts
    84
    Oh..I see..Thank you so much!..although..I'm still seeing a translucent quad when I have more than 6 lights on(it becomes more opaque as I turn more Lights on)..I havent set the effect file not to save the state..I'll try that..although I dont see an alpha test anywhere..the only techniques being passes are..

    Code:
    technique RenderScene
    {
        pass P0
        {
            VertexShader = compile vs_2_0 VertScene();
            PixelShader  = compile ps_2_0 PixScene();
            ZEnable = true;
            ZFunc = LessEqual;
            StencilEnable = true;
            
            AlphaBlendEnable = true;
            BlendOp = Add;
            SrcBlend = SrcAlpha;
            DestBlend = InvSrcAlpha;
                    
            StencilRef = 1;
            StencilFunc = Greater;
            StencilPass = Keep;
        }
    }
    and..

    Code:
    technique RenderSceneAmbient
    {
        pass P0
        {
            VertexShader = compile vs_2_0 VertSceneAmbient();
            PixelShader  = compile ps_2_0 PixSceneAmbient();
            StencilEnable = false;
            ZFunc = LessEqual;
                    
        }
    }
    The code works with upto 4 lights(basically when png is not in the radius of the lights)..but its still affected when the lights are in range..is this because of the state changes ?

  10. #10
    Registered User
    Join Date
    Oct 2008
    Posts
    84
    After removing the ZFunc = LessEqual , I am getting full transparency when the lights are in front of the model. But when I turn on the lights behind the model, I start seeing the quad again. Do you know what could be causing this ?

    Thank you!

  11. #11
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    You should be rendering these in back to front order anyways. The only thing I could think of would be back lighting when the wrong side of the poly is lit, but your formula in the pixel shader would still return an alpha of 0.0f.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 23
    Last Post: 07-09-2007, 04:49 AM
  2. D3DXSprite and alpha blend
    By Magos in forum Game Programming
    Replies: 1
    Last Post: 05-23-2006, 04:55 AM
  3. Lighting in Managed Direct3d
    By Rune Hunter in forum Game Programming
    Replies: 0
    Last Post: 04-30-2006, 07:40 AM
  4. Lighting a Direct3D 9 mesh sphere
    By bennyandthejets in forum Game Programming
    Replies: 12
    Last Post: 02-14-2005, 01:19 AM
  5. Creating a 2D GUI using Direct3D
    By codec in forum Game Programming
    Replies: 8
    Last Post: 09-23-2004, 11:57 AM