Parallel SPlit Variance Shadow Map projection problem

daisydude

Newcomer
Hello everyone,
Ok, well I have successfully uh, correction partially done Parallel Split Variance shadow map. I have got the split working with transition between the shadows. However I am having a problem like this:
ab22010091520235633.jpg


You can see that in the above image the palm's shadow appear 2 times. The shadow which is on the bottom of the scrren should not be there. Also it moves as my camera moves. Other shadow(the correct one) is stable.
What could be the problem?? Also the game uses deferred rendering..
Here is the code

Code:
ClearTexture(materialMap, device, 0xFFFFFFFF);
    ClearTexture(normalMap, device, 0xFFFFFFFF);
    ClearTexture(positionXYMap, device, 0xFFFFFFFF);
    ClearTexture(shadowOcclusionMap, device, 0xFFFFFFFF);
    ClearTexture(positionZMap, device, 0xFFFFFFFF);
    
    
    LPDIRECT3DSURFACE9 bb;
    device->GetRenderTarget(0, &bb);

    SetRenderTarget(0, materialMap, device);
    SetRenderTarget(1, normalMap, device);
    SetRenderTarget(2, positionXYMap, device);

    DrawDefferedGeometry(device, V, projectionMatrix);    
    
    device->SetRenderTarget(0, bb);    
    device->SetRenderTarget(1, NULL);
    device->SetRenderTarget(2, NULL);
    //device->GetDepthStencilSurface(&oldDepthStencilSurface);
    //device->SetDepthStencilSurface(depthStencilSurface);

    D3DVIEWPORT9 oldViewPort;

    SetRenderTarget(0, positionZMap, device);    

    for(int splitCount = 0 ; splitCount < _iNumSplits ; splitCount++)
    {
        float fNear = _pSplitDistances[splitCount];
        float fFar  = _pSplitDistances[splitCount + 1];

        float fScale=1.1f;
        D3DXVECTOR3 pCorners[8];
        CalculateFrustumCorners(pCorners, TheCamera.cameraPosition, TheCamera.cameraPosition+TheCamera.look, 
                                TheCamera.up, fNear,fFar,45,w/h,fScale, V);

        CalculateLightForFrustum(pCorners);

        lightVM[splitCount] = lightViewMatrix;
        lightPM[splitCount] = lightProjectionMatrix;

        D3DVIEWPORT9 CameraViewport;
        device->GetViewport(&CameraViewport);        
        CameraViewport.MinZ=splitCount/(float)_iNumSplits;
        CameraViewport.MaxZ=(splitCount+1)/(float)_iNumSplits;
        CameraViewport.Width = 1024;
        CameraViewport.Height = 1024;
        device->SetViewport(&CameraViewport);

        DrawShadowedGeometry(device);
    }
    device->SetViewport(&oldViewPort);

    device->Clear(0, 0,D3DCLEAR_ZBUFFER, 0xFFFFFFFF, 1.f, 0);
    
    //device->SetDepthStencilSurface(oldDepthStencilSurface);
    SetRenderTarget(0, shadowOcclusionMap, device);
    DrawShadowOcclusionMap(device, V);    

    device->SetRenderTarget(0, bb);    

        //Draw Full Screen Quad

//....
//....
DrawShadowOcclusionMap function:
Code:
void DrawShadowOcclusionMap(LPDIRECT3DDEVICE9 device, D3DXMATRIX V)
{

    static float fWidth = params.BackBufferWidth;
    static float fHeight = params.BackBufferHeight;

    
    static PlaneVertex axPlaneVertices[] =
    {
        { 0,         0,          .5f, 1, 0 + .5f / fWidth,    0 + .5f / fHeight },
        { fWidth, 0,          .5f, 1, 1 + .5f / fWidth,    0 + .5f / fHeight },
        { fWidth, fHeight,    .5f, 1, 1 + .5f / fWidth,    1 + .5f / fHeight },
        { 0,         fHeight, .5f, 1, 0 + .5f / fWidth,    1 + .5f / fHeight }
    };    D3DXVECTOR4 lightClipPlanes[_iNumSplits];    for(int splitCount = 0 ; splitCount < _iNumSplits ; splitCount++)
    {
        lightClipPlanes[splitCount].x = _pSplitDistances[splitCount];
        lightClipPlanes[splitCount].y = _pSplitDistances[splitCount + 1];        
    }

    D3DXMATRIX inverseView;
    D3DXMatrixInverse(&inverseView, NULL, &V);
    effect->SetTechnique("ShadowTech");        
    effect->SetMatrixArray("lightView", lightVM, _iNumSplits);
    effect->SetMatrixArray("lightProjection", lightPM, _iNumSplits);    
    
    effect->SetVectorArray("g_vClipPlanes", lightClipPlanes, _iNumSplits);
    effect->SetTexture("scenePositionXYMap", positionXYMap);
    effect->SetTexture("shadowMap", positionZMap);
    effect->SetTexture("sceneMaterialMap", materialMap);
    effect->SetMatrix("inverseView", &inverseView);    
    effect->SetValue("farFrustumCoords", &farFrustumCoords, sizeof(D3DXVECTOR3) * 4);

    
    

    D3DXMATRIX TexProj;
    float tex_offset = 0.5f + (0.5f / 1024);
    TexProj = D3DXMATRIX(    0.5f,            0.0f,        0.0,    0.0f,
                            0.0f,            -0.5f,        0.0f,    0.0f,
                            0.0f,            0.0f,        1.0f,    0.0f,
                            tex_offset,        tex_offset, 0.0f,    1.0f);

    effect->SetMatrix("TexProj", &TexProj);
    

    UINT numPasses;
    effect->Begin(&numPasses, 0);
    effect->BeginPass(0);
    effect->CommitChanges();
    device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
    device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, axPlaneVertices, sizeof(PlaneVertex));

    effect->EndPass();
    effect->End();        

}
And here is the shader code:

Code:
float4x4 world;
float4x4 view;
float4x4 projection;
float3   eyePos;
bool lod;
bool leaves;
float Time;
bool tree;
bool light;
float4x4 InverseTransposeView;


float3 lightDir = float3(0.0f, 10000.0f, 2000.0f);
float4 lightColor = float4(1.0f, 1.0f, 1.0f, 1.0f);
float4 materialAmbient = float4(0.8f, 0.8f, 0.8f, 1.0f);
float4 materialDiffuse = float4(0.8f, 0.8f, 0.8f, 1.0f);

//-----------------------------------------------------------------------------
// Textures.
//-----------------------------------------------------------------------------

texture colorMap;
sampler colorMapSampler = sampler_state
{
    Texture = <colorMap>;
    MinFilter = Anisotropic;
    MagFilter = Linear;
    MipFilter = Point;
    MaxAnisotropy = 16;
};


struct OutputVS
{
    float4    vPos            : POSITION0;
    float2  vTex0           : TEXCOORD0;
    float3    vWorldPos        : TEXCOORD1;
    float3    vWorldNrm        : TEXCOORD2;
    float3  eyeVec            : TEXCOORD3;
    float4  vPos1            : TEXCOORD4;
    
    
};


struct OutputPS
{
    float4    vMaterial        : COLOR0;
    float4    vWorldNrm        : COLOR1;
    float4    vWorldPosXY        : COLOR2;
    
};



OutputVS VS_Lambert(float3 posL      : POSITION0, 
                     float3 tangentL  : TANGENT0,
                     float3 binormalL : BINORMAL0,
                     float3 normalL   : NORMAL0, 
                     float2 tex0      : TEXCOORD0)
{
    
    OutputVS outVS = (OutputVS)0;
    
    float4 vertex = mul(float4(posL, 1), world);
    /*if(leaves)
    {
        //float amplitude = magnitude * (vertex.y + 20);
        float4 wave = 0.06 * float4(1.5 * sin(Time + vertex.x),
            0,
            1.5 * cos(Time + vertex.z),
            0);
            
        
        vertex = vertex + wave;
    }*/
    float4x4 ViewSpace = mul(world, view);
    outVS.vWorldPos = mul(float4(posL, 1), ViewSpace);
    float3 vWorldPos = mul(float4(posL, 1), ViewSpace);
    outVS.eyeVec = vertex.xyz - eyePos;
    float4x4 viewProjection = mul(view, projection);
    outVS.vPos = mul(float4(outVS.vWorldPos, 1), projection);
    outVS.vPos1 = outVS.vPos;
    outVS.vTex0 = tex0;
    
    outVS.vWorldNrm = normalize(mul(float4(normalL, 0), (float3x3) InverseTransposeView));
    
    return outVS;    
}

//-----------------------------------------------------------------------------
// Pixel shader.
//-----------------------------------------------------------------------------

OutputPS PS_Lambert(OutputVS i) : COLOR
{
    OutputPS o;
    
    float distance1 = distance(i.eyeVec, float3(0, 0, 0));
    
    float3 texColor = tex2D(colorMapSampler, i.vTex0);    
    
    distance1 /= 460;
    
    //clip(texColor - distance1/2);

    /*if(!lod)
    {
    
        if(!tree)
            distance1 /= 330;
        else
            distance1 /= 460;                
    
    }
    
    if(!lod)
    {
        if(!leaves)
        {        
            clip(texColor - distance1);
        }
        else
        {
            clip(texColor - distance1/2);
        }
    }
    else
    {
        if(tree)                
            clip(texColor - 28/distance1);        
    
    }*/
    
    //clip(texColor.a - 0.2f);
    
    
    
    o.vMaterial.rgb = texColor;
    o.vMaterial.a = tex2D(colorMapSampler, i.vTex0).a;
    
    o.vWorldNrm.xyz = 0.5f * (i.vWorldNrm  + 1.0f);
    o.vWorldNrm.w = 0.0;
    
    o.vWorldPosXY = float4(i.vWorldPos.xyz, 0);
    

    return o;
}

technique Lambert
{
    pass
    {
        VertexShader = compile vs_3_0 VS_Lambert();
        PixelShader = compile ps_3_0 PS_Lambert();
        AlphaTestEnable = true;
        AlphaFunc = GreaterEqual;
        AlphaRef = 150;
        CullMode = None;
        

    }
}
It appears that the shadow map of the secons plit is again drawn which is the problem. Because if I allow the first split to cover the whole are then the problem is gone.
Please help. Thanks.
 
I think I have posted wrong shader code. I was in a hurry, sorry for that. Her is the corect one:
Code:
[SIZE=2]
struct Mtrl
{
float4 ambient;
float4 diffuse;
float4 spec;
float specPower;
};
struct DirLight
{
float4 ambient;
float4 diffuse;
float4 spec;
float3 dirW; 
};
float epsilon = 0.000000001f;
float max_depth = 100;
float offset_bias = 0.01f;
static const int NUM_SPLITS = 2;
uniform extern float g_sample_rad;
uniform extern float g_scale;
uniform extern float g_bias;
uniform extern float g_intensity;
uniform extern float4x4 InverseTransposeView;
uniform extern float4x4 gWorld;
uniform extern float4x4 gWorldInv;
uniform extern float4x4 gWVP;
uniform extern Mtrl gMtrl;
uniform extern DirLight gLight;
uniform extern float3 gEyePosW;
uniform extern texture gTex;
uniform extern texture gNormalMap;
uniform extern float4x4 gView;
uniform extern float4x4 worldView;
uniform extern float4x4 WorldViewProjection;
float4x4 TexProj;
float4x4 lightView [NUM_SPLITS];
float4x4 lightProjection [NUM_SPLITS];
float4 g_vClipPlanes[NUM_SPLITS];
float4x4 inverseView;
float3 farFrustumCoords [4];
float3 cameraPosition;

uniform extern texture sceneMaterialMap, sceneNormalMap, scenePositionXYMap, scenePositionZMap, gEnvMap, randomNormalMap;
texture shadowMap, shadowOcclusionMap;
sampler shadowOcclusionMapSampler = sampler_state
{
Texture = <shadowOcclusionMap>;
MinFilter = Anisotropic;
MagFilter = Linear;
MipFilter = Linear;
AddressU = CLAMP; 
AddressV = CLAMP;
MaxAnisotropy = 16; 
};
sampler shadowMapSampler = sampler_state
{ 
Texture = <shadowMap>;
MinFilter = ANISOTROPIC;
MaxAnisotropy = 16;
MagFilter = LINEAR;
MipFilter = POINT;
//AddressU = WRAP; 
//AddressV = WRAP;


/*MinFilter = Point;
MagFilter = Point;
MipFilter = None;
AddressU = Border;
AddressV = Border;
BorderColor = 0xFFFFFFFF;*/
};
sampler randomNormalSampler = sampler_state
{
Texture = <randomNormalMap>;
MinFilter = LINEAR; 
MagFilter = LINEAR;
MipFilter = LINEAR;
AddressU = WRAP;
AddressV = WRAP;

};
sampler EnvMapS = sampler_state
{
Texture = <gEnvMap>;
MinFilter = Anisotropic; 
MagFilter = LINEAR;
MipFilter = LINEAR;
AddressU = WRAP;
AddressV = WRAP;
};
sampler textureSampler = sampler_state
{
Texture = <sceneMaterialMap>;
MinFilter = ANISOTROPIC;
MaxAnisotropy = 16;
MagFilter = LINEAR;
MipFilter = LINEAR;
AddressU = WRAP;
AddressV = WRAP;
};
sampler normalSampler = sampler_state
{
Texture = <sceneNormalMap>;
MinFilter = ANISOTROPIC;
MaxAnisotropy = 16;
MagFilter = LINEAR;
MipFilter = LINEAR;
AddressU = WRAP;
AddressV = WRAP;
};
sampler positionXYSampler = sampler_state
{
Texture = <scenePositionXYMap>;
MinFilter = ANISOTROPIC;
MaxAnisotropy = 16;
MagFilter = LINEAR;
MipFilter = LINEAR;
AddressU = CLAMP;
AddressV = CLAMP;
};
sampler positionZSampler = sampler_state
{
Texture = <scenePositionZMap>;
MinFilter = ANISOTROPIC;
MaxAnisotropy = 16;
MagFilter = LINEAR;
MipFilter = LINEAR;
AddressU = CLAMP;
AddressV = CLAMP;
};
sampler TexS = sampler_state
{
Texture = <gTex>;
MinFilter = ANISOTROPIC;
MaxAnisotropy = 16;
MagFilter = LINEAR;
MipFilter = LINEAR;
AddressU = WRAP;
AddressV = WRAP;
};
sampler NormalMapS = sampler_state
{
Texture = <gNormalMap>;
MinFilter = ANISOTROPIC;
MaxAnisotropy = 16;
MagFilter = LINEAR;
MipFilter = LINEAR;
//AddressU = WRAP;
//AddressV = WRAP; 
};

struct OutputVS
{
float4 vPos : POSITION0;
float2 vTex0 : TEXCOORD0;
float3 vWorldPos : TEXCOORD1;
float3 vWorldNrm : TEXCOORD2;

};

struct OutputPS
{
float4 vMaterial : COLOR0;
float4 vWorldNrm : COLOR1;
float4 vWorldPosXY : COLOR2; 
};


OutputVS NormalMapVS(float3 posL : POSITION0, 
float3 tangentL : TANGENT0,
float3 binormalL : BINORMAL0,
float3 normalL : NORMAL0, 
float2 tex0 : TEXCOORD0)
{


OutputVS outVS = (OutputVS)0;
float4x4 worldView = mul(gWorld, gView); 
outVS.vWorldPos = mul(float4(posL, 1), worldView);
float3 vWorldPos1 = mul(float4(posL, 1), gWorld);
outVS.vPos = mul(float4(vWorldPos1, 1), gWVP);
outVS.vTex0 = tex0;
outVS.vWorldNrm = normalize(mul(float4(normalL, 0), (float3x3) InverseTransposeView));

return outVS; 
}
OutputPS NormalMapPS(OutputVS i) : COLOR
{
OutputPS o;
float4 vDiffuseMaterial = tex2D(TexS, i.vTex0);
clip(vDiffuseMaterial.a - 0.2f);

o.vMaterial.rgb = vDiffuseMaterial;
o.vMaterial.a = 1.0;

o.vWorldNrm.xyz = 0.5f * (i.vWorldNrm + 1.0);
o.vWorldNrm.w = 0.0; 

o.vWorldPosXY = float4(i.vWorldPos.xyz, 0);
return o; 
}
float3 getPosition(in float2 texCoord)
{
float3 position;
position = tex2D(positionXYSampler, texCoord).xyz;
//position.z = tex2D(positionZSampler, texCoord).x; 
return position;
}
float doAmbientOcclusion(in float2 tcoord,in float2 uv, in float3 p, in float3 cnorm)
{
float3 diff = getPosition( tcoord + uv ) - p;
const float3 v = normalize(diff);
const float d = length(diff)*g_scale;
return max( 0.0, dot(cnorm,v) - g_bias )*( 1.0 / (1.0+d) ) * g_intensity;
}

float4 deferredLightingAO(float2 tex0:TEXCOORD0):COLOR
{
float3 diffuseMaterial = tex2D(textureSampler, tex0);
float3 worldNormal = 2*tex2D(normalSampler, tex0) - 1; 


float3 worldPos;
worldPos = getPosition(tex0);
float2 rand = normalize(tex2D(randomNormalSampler, (1024 * 1024) * tex0 / (64 * 64)).xy * 2.0f - 1.0f);
float d = worldPos.z;
if (d < 2.0f)
discard;
d = max(d, 500.0);

float ao = 0.0f;
float rad = g_sample_rad / d; 

int iterations = 16; 
float ang = 0.0;
for(int j=0 ; j < iterations ; ++j)
{
float a = radians(ang);
float2 b = float2(cos(a), sin(a));
float2 coord1 = reflect(b, rand/1024) * rad;
float2 coord2 = float2(coord1.x * 0.707f - coord1.y * 0.707f, coord1.x * 0.707f + coord1.y * 0.707f);

ao += doAmbientOcclusion( tex0, coord1 * 0.25f, worldPos, worldNormal );
/*ao += doAmbientOcclusion( tex0, coord2 * 0.50f, worldPos, worldNormal );
ao += doAmbientOcclusion( tex0, coord1 * 0.75f, worldPos, worldNormal );
ao += doAmbientOcclusion( tex0, coord2, worldPos, worldNormal );*/

ang+=360.0/16;
}

ao /= (float)iterations;


ao = (1 - ao) * (1 - ao) * (1 - ao); 


float3 lightDir = mul(gLight.dirW , worldView);
lightDir = normalize(lightDir);
//float3 lightDir = normalize(gLight.dirW);
float4 color;
color.rgb = ao * diffuseMaterial +
saturate(dot(lightDir, worldNormal)) * gLight.diffuse * diffuseMaterial * 0.6f; 

//color.rgb = ao;
color.a = 1.0f;


return color;

}
float4 deferredLighting(float2 tex0:TEXCOORD0):COLOR
{
float3 diffuseMaterial = tex2D(textureSampler, tex0);
float3 worldNormal = 2*tex2D(normalSampler, tex0) - 1; 

float3 lightDir = mul(gLight.dirW , worldView);
lightDir = normalize(lightDir);

float shadowOcclusion = tex2D(shadowOcclusionMapSampler, tex0).r;
//if(shadowOcclusion <= 1.5f)
diffuseMaterial *= shadowOcclusion; 

float4 color;
color.rgb = float3(0.7f, 0.7f, 0.7f) * diffuseMaterial +
saturate(dot(lightDir, worldNormal)) * gLight.diffuse * diffuseMaterial; 
color.a = 1.0f;


return color;

}
struct VS_INPUT_Shadow
{
float4 Pos : POSITION;
float2 Tex : TEXCOORD0;
};
struct VS_OUTPUT_Shadow
{
float4 Pos : POSITION;
float2 Tex : TEXCOORD0;
float4 PosProj : TEXCOORD1;
};
struct PS_OUTPUT_Shadow
{
float4 Color : COLOR0;
};


void ShadowTechVS ( in float3 in_vPositionOS : POSITION,
in float3 in_vTexCoordAndCornerIndex : TEXCOORD0, 
out float4 out_vPositionCS : POSITION,
out float2 out_vTexCoord : TEXCOORD0,
out float3 out_vFrustumCornerVS : TEXCOORD1 )
{
// Offset the position by half a pixel to correctly align texels to pixels
out_vPositionCS.x = in_vPositionOS.x - (1.0f / 1024);
out_vPositionCS.y = in_vPositionOS.y + (1.0f / 768);
out_vPositionCS.z = in_vPositionOS.z;
out_vPositionCS.w = 1.0f;

// Pass along the texture coordiante and the position of the frustum corner
out_vTexCoord = in_vTexCoordAndCornerIndex.xy;
out_vFrustumCornerVS = farFrustumCoords[in_vTexCoordAndCornerIndex.z];
} 
float4 ShadowTechPS(float2 tex0:TEXCOORD0, float3 a1:TEXCOORD1):COLOR0
{ 
float3 diffuseMaterial = tex2D(textureSampler, tex0);
float3 position;
position = tex2D(positionXYSampler, tex0).xyz;

float d = tex2D(positionXYSampler, tex0).w;
float4 vPositionVS = float4(d * a1, 1.0f);


float4x4 lightVM = lightView[0];
float4x4 lightPM = lightProjection[0];

float fOffset = 0;
bool a = false; 

/*if(position.z <= g_vClipPlanes[0].y)
{
lightVM = lightView[0];
lightPM = lightProjection[0]; 
}
else
{
lightVM = lightView[1];
lightPM = lightProjection[1]; 
}*/

for (int i = 1; i < NUM_SPLITS; i++)
{ 
if (position.z >= g_vClipPlanes[i].x && position.z <= g_vClipPlanes[i].y)
{
lightVM = lightView[i];
lightPM = lightProjection[i]; 
fOffset = i / (float)NUM_SPLITS; 

a = true; 
} 

} 

float4 lightViewPos = mul(float4(position, 1), inverseView);
lightViewPos = mul(lightViewPos, lightVM); 
float4 TexLookUpPos = mul(mul(lightViewPos, lightPM), TexProj); 

TexLookUpPos.x = TexLookUpPos.x/NUM_SPLITS + fOffset; 


float2 shadowCoords = TexLookUpPos.xy/TexLookUpPos.w; 
float light;

float depth = (length(lightViewPos) - offset_bias) / max_depth;
float2 moments = tex2Dproj(shadowMapSampler, TexLookUpPos).rg;



if(depth <= moments.x)
light = 1;

else
{ 
float variance = moments.y - moments.x * moments.x;
variance = min(max(variance, 0.002) + epsilon, 1);
float depth_diff = moments.x - depth;
float p_max = variance/(variance + depth_diff * depth_diff);
light = max(depth <= moments.x, p_max);
light = max(0.2f, light);
}


float4 outColor;
outColor.rgb = light;
outColor.a = 1.0f;
return outColor;
}
technique ShadowTech
{
pass P0
{

CullMode = none;
FillMode = solid;
Zenable = false; 


vertexShader = compile vs_3_0 ShadowTechVS();
pixelShader = compile ps_3_0 ShadowTechPS(); 


}
}
technique NormalMapTech
{
pass P0
{

vertexShader = compile vs_3_0 NormalMapVS();
pixelShader = compile ps_3_0 NormalMapPS();
}
}
technique DeferredLightTechniqueWithAmbientOcclusion
{
pass p0
{
VertexShader = NULL;
PixelShader = compile ps_3_0 deferredLightingAO();

CullMode = none;
FillMode = solid;
Zenable = false;
StencilEnable = false; 
AlphaBlendEnable = true;
Srcblend = One;
Destblend = One;
AlphaTestEnable = false; 
ColorWriteEnable = red | green | blue;
}
}
technique DeferredLightTechnique
{
pass p0
{
VertexShader = NULL;
PixelShader = compile ps_3_0 deferredLighting();

CullMode = none;
FillMode = solid;
Zenable = false;
StencilEnable = true;
StencilFunc = Always;
StencilPass = Replace;
StencilRef = 0; 
AlphaBlendEnable = true;
Srcblend = One;
Destblend = One;
AlphaTestEnable = false; 
ColorWriteEnable = red | green | blue;
}
}
[/SIZE]

Please help, Thanks..
 
There's clearly something wrong with your partition matrices. Shouldn't be too hard to debug on the CPU.

Also I'll warn you early... parallel split shadow maps + filtering will require you to fix derivatives at partition boundaries. The easiest way is to take the derivatives of the base texture coordinates in light space and them scale them by the appropriate values for each partition and use tex2dgrad.
 
First of all thanks for replying.
What can be the problem with different projection matrices?? Here is the code for calculating light view and projection matrices:: based upon different splits fNear ad fFar I first calculate the light frustum corners andthen pass it to the below function.
Code:
void CalculateLightForFrustum(D3DXVECTOR3 *pCorners)
{
 D3DXMATRIX worldMatrix;
 D3DXMatrixIdentity(&worldMatrix);
 D3DXMatrixRotationX(&worldMatrix, D3DX_PI/2);
 D3DXVECTOR4 transformed;
 D3DXVec3Transform(&transformed, &TheCamera.up, &worldMatrix);
 D3DXVECTOR3 upVector = D3DXVECTOR3(transformed.x, transformed.y, transformed.z);
  // calculate standard view and projection matrices for light
  CalculateViewProj(lightViewMatrix,lightProjectionMatrix,
                    lightPosition, lightTarget, D3DXVECTOR3(0,1,0),
                    90, _fLightNear, 4000, 1);

  // Next we will find the min and max values of the current
  // frustum split in lights post-projection space
  // (where coordinate range is from -1.0 to 1.0)
  //
 float fMaxX=-FLT_MAX;
 float fMaxY=-FLT_MAX;
 float fMinX=FLT_MAX;
 float fMinY=FLT_MAX;
 float fMaxZ=0;

  D3DXMATRIX mLightViewProj=lightViewMatrix * lightProjectionMatrix;
  // for each corner point
  for(int i=0;i<8;i++)
  {
    // transform point
    D3DXVECTOR4 vTransformed;
    D3DXVec3Transform(&vTransformed,&pCorners[i],&mLightViewProj);
    // project x and y
    vTransformed.x/=vTransformed.w;
    vTransformed.y/=vTransformed.w;
    // find min and max values
    if(vTransformed.x>fMaxX) fMaxX=vTransformed.x;
    if(vTransformed.y>fMaxY) fMaxY=vTransformed.y;
    if(vTransformed.y<fMinY) fMinY=vTransformed.y;
    if(vTransformed.x<fMinX) fMinX=vTransformed.x;
    // find largest z distance
    if(vTransformed.z>fMaxZ) fMaxZ=vTransformed.z;
  }

  // set values to valid range (post-projection)
  fMaxX=Clamp(fMaxX,-1.0f,1.0f);
  fMaxY=Clamp(fMaxY,-1.0f,1.0f);
  fMinX=Clamp(fMinX,-1.0f,1.0f);
  fMinY=Clamp(fMinY,-1.0f,1.0f);
  // Adjust the far plane of the light to be at the farthest
  // point of the frustum split. Some bias may be necessary.
  //
  _fLightFar=fMaxZ+_fLightNear+1.5f;
  
  // re-calculate lights matrices with the new far plane
  D3DXMATRIX lightViewMatrix1;
  CalculateViewProj(lightViewMatrix,lightProjectionMatrix,
                    lightPosition,lightTarget, D3DXVECTOR3(0,1,0),
                    90, _fLightNear, _fLightFar, 1); 

  // Next we build a special matrix for cropping the lights view
  // to only contain points of the current frustum split
  //
  
  float fScaleX = 2.0f / (fMaxX - fMinX);
  float fScaleY = 2.0f / (fMaxY - fMinY);
  float fOffsetX = -0.5f * (fMaxX + fMinX) * fScaleX;
  float fOffsetY = -0.5f * (fMaxY + fMinY) * fScaleY; 

  D3DXMATRIX mCropView(  fScaleX,     0.0f,  0.0f,   0.0f,
                            0.0f,  fScaleY,  0.0f,   0.0f,
                            0.0f,     0.0f,  1.0f,   0.0f,
                        fOffsetX, fOffsetY,  0.0f,   1.0f );
  // multiply the projection matrix with it
  lightProjectionMatrix*=mCropView;
  // finally modify projection matrix for linearized depth
  lightProjectionMatrix._33/=_fLightFar;
  lightProjectionMatrix._43/=_fLightFar;
}
......
......

Or is there a problem with the viewport.X ??
Thanks.
 
Back
Top