Sign in to follow this  

[DX9][C++] Deffered shadows troubles [SOLVED]

This topic is 2819 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I was "following" MJP's XNA "DeferredCascadedShadowMaps" and tried to "convert" it to C++ project except that i will render only 1 shadow, but i have trouble to get proper shadow coords: Full screen quad:
extern int ScreenWidth;//1024
extern int ScreenHeight;//1024

struct FSVertex
{
	D3DXVECTOR3 Position;
	D3DXVECTOR3 TexCoord0;
};

class FSQuad
{
private:
    D3DXVECTOR3 Corners[4];//frustum corners

...
    D3DXVECTOR3* GetCorners() { return &Corners[0]; }
...
// init
    D3DVERTEXELEMENT9 VertexElements[] =
    {
        {0,   0,  D3DDECLTYPE_FLOAT3,  D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,  0},
	  {0,  12,  D3DDECLTYPE_FLOAT3,  D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,  0},
	  D3DDECL_END()
    };
    hr = D3D9Device->CreateVertexDeclaration(VertexElements, &VDeclaration);
...
    D3DPOOL pool  = D3DPOOL_DEFAULT;
    DWORD usage   = D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC;
    UINT length   = sizeof(FSVertex) * 4;
    hr = D3D9Device->CreateVertexBuffer(length, usage, NULL, pool, &VBuffer, NULL);
...
    float   x1 = ((0.0f - 0.5f) * ((1.0f / (float)ScreenWidth) * 2.0f)) - 1.0f;
    float	x2 = (((float)ScreenWidth - 0.5f) * ((1.0f / (float)ScreenWidth) * 2.0f)) - 1.0f; 
    float	y1 = 1.0f - ((0.0f - 0.5f) * ((1.0f / (float)ScreenHeight) * 2.0f));
    float	y2 = 1.0f - (((float)ScreenHeight - 0.5f) * ((1.0f / (float)ScreenHeight) * 2.0f));
    float	z  = 0.0f;

    float    FOV   = D3DXToRadian(45.0f);//Copied fov value from my camera class(this is small project and i didnt want (yet) to pass camera until i got all this working)
    float    Near  = 1.0f;//also this
    float    Far   = 1500.0f;//also this
    float    NearH = 2 * tan(FOV) * Near;
    float    NearW = NearH;
    float    FarH  = 2 * tan(FOV) * Far;
    float    FarW  = FarH;
    float    NearX = NearW * 0.5f;
    float    NearY = NearH * 0.5f;
    float    FarX  = FarW * 0.5f;
    float    FarY  = FarH * 0.5f;

  //everything below goes CW:
  //              0---------1 
  //              |         | 
  //              |         |  
  //              |         | 
  //              3---------2

    Corners[0] = D3DXVECTOR3(-FarX,  FarY, Far);
    Corners[1] = D3DXVECTOR3( FarX,  FarY, Far);
    Corners[2] = D3DXVECTOR3( FarX, -FarY, Far);
    Corners[3] = D3DXVECTOR3(-FarX, -FarY, Far);

    PPVertex* pVertices = 0;
    VBuffer->Lock(0, 0, (LPVOID*)&pVertices, 0);
    pVertices[0].Position   = D3DXVECTOR3( x1,  y1,  z);
    pVertices[1].Position   = D3DXVECTOR3( x2,  y1,  z);
    pVertices[2].Position   = D3DXVECTOR3( x2,  y2,  z);
    pVertices[3].Position   = D3DXVECTOR3( x1,  y2,  z);

    pVertices[0].TexCoord0  = D3DXVECTOR3(0.0f, 0.0f, 0.0f);//3rd component is index (as in MJP's demo)
    pVertices[1].TexCoord0  = D3DXVECTOR3(1.0f, 0.0f, 1.0f);
    pVertices[2].TexCoord0  = D3DXVECTOR3(1.0f, 1.0f, 2.0f);
    pVertices[3].TexCoord0  = D3DXVECTOR3(0.0f, 1.0f, 3.0f);
    VBuffer->Unlock();

...//indices
    USHORT* pIndices = 0;
    IBuffer->Lock(0, 0, (LPVOID*)&pIndices, 0);
    pIndices[0]       = 0;
    pIndices[1]       = 1;
    pIndices[2]       = 2;
    pIndices[3]       = 0;
    pIndices[4]       = 2;
    pIndices[5]       = 3;
    IBuffer->Unlock();
};


send transformed corners
D3DXVECTOR3 TransformVector3(D3DXMATRIX mat, D3DXVECTOR3 vec)
{
	D3DXVECTOR3 tmp0 = vec;
	vec.x = tmp0.x*mat.m[0][0] + tmp0.y*mat.m[1][0] + tmp0.z*mat.m[2][0] + mat.m[3][0];
	vec.y = tmp0.x*mat.m[0][1] + tmp0.y*mat.m[1][1] + tmp0.z*mat.m[2][1] + mat.m[3][1];
	vec.z = tmp0.x*mat.m[0][2] + tmp0.y*mat.m[1][2] + tmp0.z*mat.m[2][2] + mat.m[3][2];
	return vec;
}

void RenderShadowsToFS()
{
      ...
      D3DXVECTOR3* Corners = fsQuad->GetCorners();
	D3DXVECTOR3 FCorners[4];
	FCorners[0] = TransformVector3(gCamera->View, Corners[0]);
	FCorners[1] = TransformVector3(gCamera->View, Corners[1]);
	FCorners[2] = TransformVector3(gCamera->View, Corners[2]);
	FCorners[3] = TransformVector3(gCamera->View, Corners[3]);
      gShadowedEffect->SetValue("FrustumCorners", &FCorners[0], sizeof(D3DXVECTOR3) * 4);
      ...
}


All shaders are the same except "ShadowMap.fx" pixel shader:
//global
float3 FrustumCorners[4];
...vertex shader
    OUT.FrustumC               = FrustumCorners[IN.TexCoord0.z];
..pixel shader
    float fPixelDepth     = tex2D(DepthSamp, IN.TexCoord0).r;// DepthSamp rendered from "player" camera (R32F, size same as screen 1024x1024)
    float4 vPositionVS    = float4(fPixelDepth * IN.FrustumC.xyz, 1.0f);

    float4x4 matViewToLightViewProj = mul(InvView, LightViewProj);//only one shadow light view proj
    float4 vPositionLightCS         = mul(vPositionVS, matViewToLightViewProj);

   float2 vShadowTexCoord          = 0.5 * vPositionLightCS.xy / vPositionLightCS.w + float2(0.5f, 0.5f);
   vShadowTexCoord.y               = 1.0f - vShadowTexCoord.y;
   vShadowTexCoord                += (0.5f / 1024.0f);
   float Shadow                    = tex2D(ShadowSamp, vShadowTexCoord).r;// ShadowSamp rendered from "light" camera (R32F, size same as screen 1024x1024)


   OUT.Color                       = Shadow;
   OUT.Color.a                     = 1.0f;


then i combine above in other shader:
...pixel shader
    float4 diffuse = tex2D(allModelsDifffuseSamp, tc);
    float4 shadow  = tex2D(shadowSamp, tc);// from prev. shader
    OUT.Color      = diffuse * shadow;
    OUT.Color.a    = 1.0f;


and i got everything rendered except shadows. This nightmare longs almost two weeks now. [Edited by - belfegor on April 1, 2010 9:51:51 AM]

Share this post


Link to post
Share on other sites
Ok. i got this working by using MJP's "Reconstructing position from depth"
without "frustum corners" method.


float3 VSPositionFromDepth(float2 vTexCoord)
{
float z = tex2D(DepthSamp, vTexCoord);
float x = vTexCoord.x * 2 - 1;
float y = (1 - vTexCoord.y) * 2 - 1;
float4 vProjectedPos = float4(x, y, z, 1.0f);
float4 vPositionVS = mul(vProjectedPos, InvProjection);
return vPositionVS.xyz / vPositionVS.w;
}



but i would like to know what am i doing wrong with previous "corners" method.

Also i use :

float fNear = 1.0f;
float fFar = 1500.0f;
float aspect = 1.0f;
float Fov = D3DXToRadian(45.0f);
D3DXMatrixPerspectiveFovLH(&gLightProjection, Fov, aspect, fNear, fFar);



instead:

D3DXMatrixOrthoLH(&gLightProjection, 1500.0f, 1500.0f, 0.0f, 1.0f);



because i got nothing rendered to rt with it???

Can someone provide code/hint for proper 4 corners that i have trouble with.

Share this post


Link to post
Share on other sites
To simplify my question i just need to know how to
calculate 4 needed corners based on this:

light projection matrix

float fNear = 1.0f;
float fFar = 1500.0f;
float aspect = (float)SHADOW_RT_SIZE / (float)SHADOW_RT_SIZE;//1.0f
float Fov = D3DXToRadian(45.0f);
D3DXMatrixPerspectiveFovLH(&gLightProjection, Fov, aspect, fNear, fFar);





screen quad

float c = 1.0f;
float z = 0.0f;

SSVertex* pVertices = 0;
VBuffer->Lock(0, 0, (LPVOID*)&pVertices, 0);

pVertices[0].Position = D3DXVECTOR3( -c, c, z);
pVertices[1].Position = D3DXVECTOR3( c, c, z);
pVertices[2].Position = D3DXVECTOR3( c, -c, z);
pVertices[3].Position = D3DXVECTOR3( -c, -c, z);

pVertices[0].TexCoord0 = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
pVertices[1].TexCoord0 = D3DXVECTOR3(1.0f, 0.0f, 1.0f);
pVertices[2].TexCoord0 = D3DXVECTOR3(1.0f, 1.0f, 2.0f);
pVertices[3].TexCoord0 = D3DXVECTOR3(0.0f, 1.0f, 3.0f);

VBuffer->Unlock();





render

...
D3DXVECTOR3 Corners[4] = ???
Effect->SetValue("corners", &Corners, sizeof(D3DXVECTOR3) * 4);
...





so that i can reconstruct position in shder

float3 corners[4];
...vertex shader
OUT.Corners = corners[IN.TexCoord0.z];
...pixel shader
float fPixelDepth = tex2D(DepthSamp, IN.TexCoord0.xy).r;
float4 vPositionVS = float4(fPixelDepth * IN.Corners.xyz, 1.0f);
...





Please.

EDIT; i made i mistake. I ve posted light camera projection instead "player"
camera, but they are basicly same except aspect:


D3DXMatrixPerspectiveFovLH(&Projection, D3DXToRadian(45.0f), (float)ScreenWidth / (float)ScreenHeight, fNear, fFar);




EDIT2; and if you need shader that render depth from "player" cam view:

...vertex shader
float4x4 wv = mul(World, View);
float4 wvPos = mul(float4(IN.Position.xyz, 1.0f), wv);
OUT.Position = mul(wvPos, Projection);
OUT.Depth = OUT.Position.zw;
...pixel shader
float d = IN.Depth.x / IN.Depth.y;// z/w
OUT.Color = float4(d, 1.0f, 1.0f, 1.0f);



[Edited by - belfegor on April 1, 2010 4:15:42 AM]

Share this post


Link to post
Share on other sites
OK. Forget about everything above.
I have started this project from beg.

Can you confirm this information below to be correct?:

axis aligned far frustum corners (how to call them otherwise)

float c = 1.0f;
float z = 0.0f;

float Fov = cameraFov;//D3DX_PI / 4.0f;
float Far = camFar;//1500
float FarY = tan(Fov / 2.0f) * Far;
float FarX = FarY * (cameraAspect);

// going CW same as i build my quad vertices/texcoords
FrustumCorners[0] = D3DXVECTOR3(-FarX, FarY, Far);
FrustumCorners[1] = D3DXVECTOR3( FarX, FarY, Far);
FrustumCorners[2] = D3DXVECTOR3( FarX, -FarY, Far);
FrustumCorners[3] = D3DXVECTOR3(-FarX, -FarY, Far);



then i transform these corners by "player" camera view matrix
and send them to shader:


float3 corners[4];
...vertex shader
OUT.Corners = corners[IN.TexCoord0.z];
...pixel shader
float fPixelDepth = tex2D(DepthSamp, IN.TexCoord0.xy).r;
float4 vPositionVS = float4(fPixelDepth * IN.Corners.xyz, 1.0f);



and if all this is correct how do i build proper light ortho projection matrix
because i got nothing rendered (on this rt) from light point of view if i use this:


float arbitaryValue = 1000.0f;// dont know what to store here
D3DXMatrixOrthoLH(&gLightProjection, arbitaryValue , arbitaryValue , 0.0f, 1.0f);


I am rendering (centered at origin) simple plane (100.0x100.0) and sphere
above it (radius 30.0).

when i run this with PIX (using above ortho projection) RT is completly white
but when i use
D3DXMatrixPerspectiveFovLH(&gLightProjection, Fov, aspect, fNear, fFar);
projection RT looks ok but final output is
wrong.

Share this post


Link to post
Share on other sites
EDIT;
shader that renders depth from "player" camera view:

float4x4 World;
float4x4 View;
float4x4 Projection;
float4x4 WorldViewProj;

struct A2V
{
float3 Position : POSITION;
};

struct V2P
{
float4 Position : POSITION;
float Depth : TEXCOORD0;
};

struct P2A
{
float4 Color : COLOR;
};

void VertexMain(in A2V IN, out V2P OUT)
{
float4x4 wv = mul(World, View);
float4 wvPos = mul(float4(IN.Position.xyz, 1.0f), wv);
OUT.Position = mul(wvPos, Projection);
OUT.Depth = wvPos.z;
}

void PixelMain(in V2P IN, out P2A OUT)
{
float d = IN.Depth.x / 1500.0f;
OUT.Color = float4(d, 1.0f, 1.0f, 1.0f);
}

technique tDepthMain
{
pass p0
{
VertexShader = compile vs_3_0 VertexMain();
PixelShader = compile ps_3_0 PixelMain();

ZEnable = true;
ZWriteEnable = true;
CullMode = CCW;
FillMode = Solid;
AlphaBlendEnable = false;
AlphaTestEnable = false;
}
}



shader that renders depth from light view:

float4x4 WorldViewProjection;

struct A2V
{
float3 Position : POSITION;
};

struct V2P
{
float4 Position : POSITION;
float2 Depth : TEXCOORD0;
};

struct P2A
{
float4 Color : COLOR;
};

void VertexMain(in A2V IN, out V2P OUT)
{
OUT.Position = mul(float4(IN.Position, 1.0f), WorldViewProjection);
OUT.Depth = OUT.Position.zw;
}

void PixelMain(in V2P IN, out P2A OUT)
{
float d = IN.Depth.x / IN.Depth.y;
OUT.Color = float4(d, 1.0f, 1.0f, 1.0f);
}

technique tDepth
{
pass p0
{
VertexShader = compile vs_3_0 VertexMain();
PixelShader = compile ps_3_0 PixelMain();
ZEnable = true;
ZWriteEnable = true;
CullMode = CCW;
FillMode = Solid;
AlphaBlendEnable = false;
AlphaTestEnable = false;
}
}

Share this post


Link to post
Share on other sites

This topic is 2819 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this