Omnidirectional Shadows Problem

Started by
2 comments, last by TwistedPix 15 years, 2 months ago
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.
[Blog]
Advertisement
Looks like your close...could you post your code for setting up the view/projection matrices you use for rendering the scene into the shadow map?
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.
[Blog]
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.
[Blog]

This topic is closed to new replies.

Advertisement