I implemented planar shadows with the function D3DXMatrixShadow.

As you know, we need plane and light factor to calculate a shadow matrix.

The problem is that when I set the plane as D3DXPLANE p(0, -1, 0, 0.1f), the shadows by directional light are correctly rendered, but the shadows by point light are not rendered.

However, if I use D3DXPLANE p(0, 1, 0, 0.1f), the situation is reversed, shadows by directional light are not drawn, the shadows by point light are ok.

I cannot understand why it happens. Is it normal or am i missing something? Please explain to me why this happens.

Thanks in advance.


ID3D10EffectTechnique* oldTech = meshes[i]->technique;

D3DXPLANE groundPlane(0, -1, 0, 0.01f);
D3DXMATRIX S;//shadow matrix
D3DXVECTOR4 light;
if(lightType != 2) //2 here means point light
    light.x = lightDirection.x;
    light.y = lightDirection.y;
    light.z = lightDirection.z;
    light.w = 0;
    light.x = lightPosition.x;
    light.y = lightPosition.y;
    light.z = lightPosition.z;
    light.w = 1;
    groundPlane.b = 1;

D3DXMatrixShadow(&S, &light, &groundPlane);
D3DXMATRIX W = meshes[i]->GetWorldMatrix();
D3DXMATRIX matWorld = W * S;

meshes[i]->technique = shadowTechnique;
//Meshes here are drawn by ID3DX10Mesh, 
//but I tested other code with LPD3DXMESH, it has the same problem. 

meshes[i]->technique = oldTech;

 //shader code(.fx file)
 PS_Input VS_Shadow(VS_Input input)
    PS_Input output = (PS_Input)0;
    output.pos = mul(float4(input.pos, 1), matWorld);
    output.pos.y = 0.1;
    output.pos = mul(mul(output.pos, matView), matProjection);
    output.normal = mul( input.normal, (float3x3)matWorld );
    output.color = input.color;
    output.worldPos = (float3)mul(input.pos, matWorld);
    output.tex = input.tex; 
    return output;

 float4 PS_Shadow( PS_Input input) : SV_Target
    return float4(0,0,0,0.5f);

 DepthStencilState StencilIncreaseOnce {
    DepthEnable = true;
    DepthWriteMask = ALL;
    DepthFunc = LESS_EQUAL;

    StencilEnable = true;
    FrontFaceStencilFunc = EQUAL;
        FrontFaceStencilPass = INCR;
    FrontFaceStencilFail = Keep;

 BlendState BlendAlpha {
    AlphaToCoverageEnable = FALSE;
    BlendEnable[0] = TRUE;
    SrcBlend = SRC_ALPHA ;
    DestBlend = INV_SRC_ALPHA ;
    BlendOp = ADD;
    SrcBlendAlpha = ONE;
    DestBlendAlpha = ZERO;
    BlendOpAlpha = ADD;
    RenderTargetWriteMask[0] = 0x0F;

 technique10 ShadowRender
    pass P0
        SetVertexShader( CompileShader( vs_4_0, VS_Shadow() ) );
        //SetVertexShader( CompileShader( vs_4_0, VS() ) );
        SetGeometryShader( NULL );
        SetPixelShader( CompileShader( ps_4_0, PS_Shadow() ) );     

        SetDepthStencilState( StencilIncreaseOnce, 0x0 );
        SetBlendState( BlendAlpha, float4( 0.0f, 0.0f, 0.0f, 0.0f ),
                   0xFFFFFFFF ); //blendState, blendFactor, sampleMask
  • \$\begingroup\$ Can you post the relevant parts of your code? Such as how you set up the light positions, calculate the shadow matrix, and render the shadows? \$\endgroup\$ Nov 19, 2011 at 4:53
  • \$\begingroup\$ @NathanReed I added my code. \$\endgroup\$
    – DevExcite
    Nov 19, 2011 at 9:02

1 Answer 1


Your code looks mostly correct to me. One thing that's a little weird is the output.pos.y = 0.1; in your VS. The reason this concerns me is that when you're using a point light, the shadow matrix is a projection matrix, and that means that after going through it your points are going to come out with w != 1.0. So you can't just set y to 0.1 to make them come out at y = 0.1...you'd have to set y to w * 0.1.

Another thing that might be an issue is a possible mismatch in the convention of lightDirection. I believe the function expects a vector pointing toward the light, but some people prefer to define it in terms of the direction the light is traveling, which the opposite. But if this was the probem I'd expect to see the shadows appearing to the lit side of the object instead of the shadowed side, since the whole vector would be negated and not just the y component.

  • \$\begingroup\$ I think your second paragraph contains the answer. We use the lightDirection as the direction of the light, not the opposite. I think that made the difference. Thank you! \$\endgroup\$
    – DevExcite
    Nov 20, 2011 at 7:24

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .