Jump to content
  • Advertisement
Sign in to follow this  
TwistedPix

Omnidirectional Shadows Problem

This topic is 3615 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

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
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?

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
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!