Sign in to follow this  
TwistedPix

Omnidirectional Shadows Problem

Recommended Posts

Hi I tried to implement shadows for point lights as suggested by this article but after two days of trying to figure out whats wrong, I totally lost. Here is what i do: I'm rendering the light distance from pixel to cube map (the cube texture format is D3DFMT_R32F). In second pass I'm sampling the depth from cube map using the negative light vector. But i getting strange results. Here is my depth pass shader:
uniform extern float4x4 World;
uniform extern float4x4 LWorldViewProj;//Light World View Projection Matrix
uniform extern float3   LightPos;

struct VS_INPUT
{
	float3 Position : POSITION0;
};

struct VS_OUTPUT
{
	float4 Position  : POSITION;
	float3 Depth     : TEXCOORD0;
};

VS_OUTPUT VS_DepthMap(VS_INPUT IN)
{
	VS_OUTPUT OUT = (VS_OUTPUT)0;
	
	OUT.Position    = mul(float4(IN.Position, 1.0f), LWorldViewProj);
	
	float3 worldPos = mul(float4(IN.Position, 1.0f), World).xyz;
	OUT.Depth       = LightPos - worldPos;
	
	return OUT;
}

float4 PS_DepthMap(VS_OUTPUT IN) : COLOR
{
	return length(IN.Depth);
}


And second pass (some codes omitted):
uniform extern float4x4 WorldViewProj;
uniform extern float4x4 WorldMatrix;
uniform extern float4x4 NormalMatrix;
uniform extern textureCUBE ShadowMap;

uniform extern float3   LightPos;
uniform extern float3   CamPos;

static const float SHADOW_EPSILON = 0.5f;

samplerCUBE ShadowSampler = sampler_state
{
	Texture   = <ShadowMap>;
	MinFilter = NONE;
	MagFilter = NONE;
	MipFilter = NONE;
	AddressU  = WRAP;
        AddressV  = WRAP;
};

struct VS_OUTPUT
{
	float4 Position : POSITION;
	float2 TexCoord : TEXCOORD0;
	float3 ViewDir  : TEXCOORD1;
	float3 LightDir : TEXCOORD2;
	float3 Normal   : TEXCOORD3; 
};

struct VS_INPUT
{
	float3 Position   : POSITION0; 
	float3 Normal     : NORMAL; 
	float2 TexCoord   : TEXCOORD0;
};

VS_OUTPUT VS_Diffuse(VS_INPUT IN)
{
	VS_OUTPUT OUT = (VS_OUTPUT)0;
	
	float3 worldPos = mul(float4(IN.Position, 1.0f), WorldMatrix).xyz;

	OUT.Position = mul(float4(IN.Position, 1.0f), WorldViewProj);
	OUT.ViewDir  = CamPos   - worldPos;
	OUT.LightDir = LightPos - worldPos;
	OUT.Normal   = mul(IN.Normal, NormalMatrix);
	OUT.TexCoord = IN.TexCoord;
	
	return OUT;
}

float4 PS_Diffuse(VS_OUTPUT IN) : COLOR
{

    float dist  = length(IN.LightDir);
    float3 l    = normalize(IN.LightDir);
    
    float depth = texCUBE(ShadowSampler, -l).x + SHADOW_EPSILON;

    float shadowFactor = 1.0f;

    if(dist > depth) shadowFactor = 0.1f;

    float4 diffuse  = NL * tex * atten;
    float4 specular = specularC * atten;
    float4 color    = ambient + shadowFactor * (diffuse + specular);

    return color;
}


Screen Shots: Free Image Hosting at www.ImageShack.us Free Image Hosting at www.ImageShack.us I'd greatly appreciate any help.

Share this post


Link to post
Share on other sites
Sure!


Code That renders to shadow map:


void Demo4::RenderShadowScene()
{
static D3DXMATRIX World;

D3DXMatrixIdentity(&World);

HR(mFX[mSHFX]->SetFloatArray("LightPos", mSunPos, 3));
HR(mFX[mSHFX]->SetMatrix("World", &(World)));
HR(mFX[mSHFX]->SetMatrix("LWorldViewProj", &(World*mLViewProjMat)));

HR(mFX[mSHFX]->CommitChanges());

HR(mFX[mSHFX]->BeginPass(0));

HR(mScene->DrawSubset(0));
HR(mScene->DrawSubset(1));
HR(mScene->DrawSubset(2));

HR(mFX[mSHFX]->EndPass());
}

void Demo4::CreateShadowMap()
{
static D3DXMATRIX ViewMat;
static D3DXMATRIX ProjMat;
static UINT totalPasses;

float farZ = 5000.0f;

static D3DXVECTOR3 PositiveLookX = D3DXVECTOR3(1.0f, 0.0f, 0.0f);
static D3DXVECTOR3 PositiveLookY = D3DXVECTOR3(0.0f, 1.0f, 0.0f);
static D3DXVECTOR3 PositiveLookZ = D3DXVECTOR3(0.0f, 0.0f, 1.0f);

static D3DXVECTOR3 NegativeLookX = D3DXVECTOR3(-1.0f, 0.0f, 0.0f);
static D3DXVECTOR3 NegativeLookY = D3DXVECTOR3(0.0f, -1.0f, 0.0f);
static D3DXVECTOR3 NegativeLookZ = D3DXVECTOR3(0.0f, 0.0f, -1.0f);


mLightCam.SetPosition(mSunPos);

D3DXMatrixPerspectiveFovLH( &ProjMat, D3DX_PI / 2.0f,
1.0f, 1.0f, farZ );

//enable red channel for color write
HR(mD3dDevice->SetRenderState(D3DRS_COLORWRITEENABLE,
D3DCOLORWRITEENABLE_RED ));


HR(mFX[mSHFX]->SetTechnique("TechDepthOut"));
HR(mFX[mSHFX]->Begin(&totalPasses, 0));

//Render To Positive X Face
mLightCam.SetLook(PositiveLookX);
mLightCam.SetUp(PositiveLookY);
mLightCam.SetRight(NegativeLookZ);
ViewMat = mLightCam.GetMatrix();

mCubeDepthMap.SetActiveFace(CubeRenderTarget::CUBEMAP_FACE_P_X);

HR(mD3dDevice->Clear(0,0,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
0x00000000, 1.0f, 0));

mLViewProjMat = ViewMat*ProjMat;

RenderShadowScene();


//Render To Negative X Face
mLightCam.SetLook(NegativeLookX);
mLightCam.SetUp(PositiveLookY);
mLightCam.SetRight(PositiveLookZ);
ViewMat = mLightCam.GetMatrix();

mCubeDepthMap.SetActiveFace(CubeRenderTarget::CUBEMAP_FACE_N_X);

HR(mD3dDevice->Clear(0,0,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
0x00000000, 1.0f, 0));

mLViewProjMat = ViewMat*ProjMat;

RenderShadowScene();


//Render To Positive Y Face
mLightCam.SetLook(PositiveLookY);
mLightCam.SetUp(NegativeLookZ);
mLightCam.SetRight(PositiveLookX);
ViewMat = mLightCam.GetMatrix();

mCubeDepthMap.SetActiveFace(CubeRenderTarget::CUBEMAP_FACE_P_Y);

HR(mD3dDevice->Clear(0,0,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
0x00000000, 1.0f, 0));

mLViewProjMat = ViewMat*ProjMat;

RenderShadowScene();


//Render To Negative Y Face
mLightCam.SetLook(NegativeLookY);
mLightCam.SetUp(NegativeLookZ);
mLightCam.SetRight(NegativeLookX);
ViewMat = mLightCam.GetMatrix();

mCubeDepthMap.SetActiveFace(CubeRenderTarget::CUBEMAP_FACE_N_Y);

HR(mD3dDevice->Clear(0,0,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
0x00000000, 1.0f, 0));

mLViewProjMat = ViewMat*ProjMat;

RenderShadowScene();



//Render To Positive Z Face
mLightCam.SetLook(PositiveLookZ);
mLightCam.SetUp(PositiveLookY);
mLightCam.SetRight(PositiveLookX);
ViewMat = mLightCam.GetMatrix();

mCubeDepthMap.SetActiveFace(CubeRenderTarget::CUBEMAP_FACE_P_Z);

HR(mD3dDevice->Clear(0,0,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
0x00000000, 1.0f, 0));

mLViewProjMat = ViewMat*ProjMat;

RenderShadowScene();


//Render To Negative Z Face
mLightCam.SetLook(NegativeLookZ);
mLightCam.SetUp(PositiveLookY);
mLightCam.SetRight(NegativeLookX);
ViewMat = mLightCam.GetMatrix();

mCubeDepthMap.SetActiveFace(CubeRenderTarget::CUBEMAP_FACE_N_Z);

HR(mD3dDevice->Clear(0,0,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
0x00000000,1.0f, 0));

mLViewProjMat = ViewMat*ProjMat;

RenderShadowScene();


mFX[mSHFX]->End();

//enable color writes
HR(mD3dDevice->SetRenderState(D3DRS_COLORWRITEENABLE,
D3DCOLORWRITEENABLE_ALPHA|
D3DCOLORWRITEENABLE_RED|
D3DCOLORWRITEENABLE_GREEN|
D3DCOLORWRITEENABLE_BLUE));
}




The camera class GetMatrix() Function (i use same class for my viewer camera):

D3DXMATRIX Camera::GetMatrix()
{
if(mChanged)//Little optimization
{
//Get right vector
D3DXVec3Cross(&mRight, &mUp, &mLook);
D3DXVec3Normalize(&mRight, &mRight);

//Get look vector
D3DXVec3Cross(&mLook, &mRight, &mUp);
D3DXVec3Normalize(&mLook, &mLook);

//Get up vector
D3DXVec3Cross(&mUp, &mLook, &mRight);
D3DXVec3Normalize(&mUp, &mUp);


mMat(0, 0) = mRight.x;
mMat(1, 0) = mRight.y;
mMat(2, 0) = mRight.z;
mMat(3, 0) = -D3DXVec3Dot(&mPos, &mRight);;

mMat(0, 1) = mUp.x;
mMat(1, 1) = mUp.y;
mMat(2, 1) = mUp.z;
mMat(3, 1) = -D3DXVec3Dot(&mPos, &mUp);;

mMat(0, 2) = mLook.x;
mMat(1, 2) = mLook.y;
mMat(2, 2) = mLook.z;
mMat(3, 2) = -D3DXVec3Dot(&mPos, &mLook);;

mMat(0,3) = 0.0f;
mMat(1,3) = 0.0f;
mMat(2,3) = 0.0f;
mMat(3,3) = 1.0f;

mChanged = false;
}

return mMat;
}




Thanks! :)

PS: sorry for the long code though.

Share this post


Link to post
Share on other sites
Thanks for such great replies.

Alright, I solved the problem. The author of that article didn't set the viewport and depth buffer surface for cube render target in his code and wonderfully it worked in that demo, and unfortunately or thankfully it showed up in my code.

And one question for moderators: Aside from the great articles hosted here, few (like above article) written poorly (thus making confusion for someone who is new to the technique, like me). I wonder if there are some quality standards for writing articles and if so, how it passed them?

Thanks.

Share this post


Link to post
Share on other sites

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