Sign in to follow this  

pssm problems

This topic is 1302 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 am start to implement pssm a few days ago, but i have some problems on it,  when camera look the same direction of light,

 

 the pssm works very well as the image below

[attachment=22290:1.png]

 

but when camera look opposite of the light ,all shadow disappeared

[attachment=22291:3.png]

 

when turn camer to left a bit , the shadow became obscured

[attachment=22292:2.png]

 

if i turn the camera to right, i got this image

[attachment=22293:4.png]

 

 

this is the hlsl code for depth map

struct VS_OUTPUT
{
    float4 posH : POSITION;
    float4 depth : TEXCOORD0;
};

VS_OUTPUT vs_depth(
float3 posL : POSITION0)
{
    VS_OUTPUT o = (VS_OUTPUT) 0;
    o.posH = mul(float4(posL, 1.0f), gWLightVP);
o.tex = tex;
    o.depth = o.posH;
}
float4 ps_depth(VS_OUTPUT i) : COLOR
{
   float z = i.depth.z / i.depth.w;
}

this is the hlsl code of scene

VS_OUTPUT vs(
	float3 posL			: POSITION0,
	float3 Normal		: NORMAL,
	float2 TexCoord		: TEXCOORD0)
{
	VS_OUTPUT o = (VS_OUTPUT) 0;

	o.Position = mul(float4(posL, 1.0f), gWorldViewProj);
	o.TexCoord = TexCoord;
	o.Normal = Normal;

	float4 posW = mul(posL, gWorld);
	float4 posV = mul(posW, gView);
	o.zV = posV.z;

	for (int i = 0; i < 4; ++i)
	{
		o.ScreenPos[i] = mul(float4(posL, 1.0f), gWLightVPs[i]);
	}
    return o;
}

float4 ps(VS_OUTPUT i) : COLOR
{
	float shadow = 0.0f;
	for (int j = 0; j < 4; ++j)
	{
		if (i.zV >= PSSMDistances[j] && i.zV < PSSMDistances[j + 1])
		{
			shadow = process_shadow(j, i.ScreenPos[j]);
		}
	}
}

process_shadow function

float process_shadow(sampler sam, float4 projTex)
{
	// Compute pixel depth for shadowing.
	float depth = projTex.z;
 
	// Transform to texel space
    float2 texelpos = ShadowMapSize * projTex.xy;
        
    // Determine the lerp amounts.           
    float2 lerps = frac( texelpos );
    
    // 2x2 percentage closest filter.
    float dx = 1.0f / ShadowMapSize;
	float s0 = (tex2D(sam, projTex.xy).r + SHADOW_EPSILON < depth) ? 0 : 1;
	float s1 = (tex2D(sam, projTex.xy + float2(dx, 0.0f)).r + SHADOW_EPSILON < depth) ? 0 : 1;
	float s2 = (tex2D(sam, projTex.xy + float2(0.0f, dx)).r + SHADOW_EPSILON < depth) ? 0 : 1;
	float s3 = (tex2D(sam, projTex.xy + float2(dx, dx)).r   + SHADOW_EPSILON < depth) ? 0 : 1;
	return lerp( lerp(s0, s1, lerps.x), lerp(s2, s3, lerps.x), lerps.y );
}

float process_shadow(int partition, float4 screenPos)
{
	float4 projTex = screenPos;
	projTex.xyz /= projTex.w;
	projTex.x =  0.5f*projTex.x + 0.5f; 
	projTex.y = -0.5f*projTex.y + 0.5f;

	float shadow = 1.0f;
	if (partition == 0)
	{
		shadow = process_shadow(shadowmapsam0, projTex);
	}
	if (partition == 1)
	{
		shadow = process_shadow(shadowmapsam1, projTex);
	}
	if (partition == 2)
	{
		shadow = process_shadow(shadowmapsam2, projTex);
	}
	if (partition == 3)
	{
		shadow = process_shadow(shadowmapsam3, projTex);
	}
	return shadow;
}

PSSMUtils.cpp  this code is come from https://code.google.com/p/irrcg/

CPSSMUtils::CPSSMUtils(WSCamera* vLightCamera, int vSplitsCount, float vSplitLambda) : SplitLambda(vSplitLambda), LightCamera(0),
	SplitsCount(0), Near(0), Far(0), Current(0)
{
	for(int i = 0; i < 4; i++)
	{
		FrustumCorner[i] = D3DXVECTOR3(0,0,0);
		//mP[i] = 0;		
		//mV[i] = 0;
		D3DXMatrixIdentity(&mP[i]);
		D3DXMatrixIdentity(&mV[i]);
	}

	setLightCamera(vLightCamera);

	if(vSplitsCount > 0)
	{
		if(vSplitsCount > 4)
			SplitsCount = 4;
		else
			SplitsCount = vSplitsCount;
	}
	else
		SplitsCount = 1;
}

void CPSSMUtils::CalculateSplitDistances(WSCamera* vCamera)
{
	//delete[] SplitDistance;
	//SplitDistance = new float[SplitsCount + 1];

	float vNear = vCamera->getNearValue();
	float vFar = vCamera->getFarValue();

	SplitLambda = Clamp(SplitLambda, 0.0f, 1.0f);

	for(int i = 0; i < SplitsCount; i++)
	{
		float Param = i / (float)SplitsCount;
		float Log = vNear * powf((vFar / vNear), Param);
		float Uniform = vNear + (vFar - vNear) * Param;
		int dist = Log * SplitLambda + Uniform * (1.0 - SplitLambda);
		SplitDistance[i] = dist;
	}

	SplitDistance[0] = vNear;
	SplitDistance[SplitsCount] = vFar;
}

void CPSSMUtils::CalculateFrustumCorners(WSCamera* vCamera, int vCurrent, float vScale)
{
	if(vCurrent < 0 || vCurrent > 3)
		vCurrent = 0;

	Current = vCurrent;

	D3DXVECTOR3 vSource = vCamera->pos();
	D3DXVECTOR3 vTarget = vCamera->look();
	D3DXVECTOR3 vUp = vCamera->up();
	float vFOV = vCamera->getFOV();
	float vAspect = vCamera->getAspectRatio();
	float vNear = SplitDistance[Current];
	float vFar = SplitDistance[Current + 1];

	D3DXVECTOR3 vZ = vTarget - vSource;
	//vZ.normalize();
	D3DXVec3Normalize(&vZ, &vZ);

	//D3DXVECTOR3 vX = vUp.crossProduct(vZ);
	//vX.normalize();
	D3DXVECTOR3 vX;
	D3DXVec3Cross(&vX, &vUp, &vZ);
	D3DXVec3Normalize(&vX, &vX);

	//D3DXVECTOR3 vY = vZ.crossProduct(vX);
	D3DXVECTOR3 vY;
	D3DXVec3Cross(&vY, &vZ, &vX);

	float NearPlaneHeight = tanf(vFOV * 0.5f) * vNear;
	float NearPlaneWidth = NearPlaneHeight * vAspect;

	float FarPlaneHeight = tanf(vFOV * 0.5f) * vFar;
	float FarPlaneWidth = FarPlaneHeight * vAspect;

	D3DXVECTOR3 NearPlaneCenter = vSource + vZ * vNear;
	D3DXVECTOR3 FarPlaneCenter = vSource + vZ * vFar;

	FrustumCorner[0] = D3DXVECTOR3(NearPlaneCenter - vX*NearPlaneWidth - vY*NearPlaneHeight);
	FrustumCorner[1] = D3DXVECTOR3(NearPlaneCenter - vX*NearPlaneWidth + vY*NearPlaneHeight);
	FrustumCorner[2] = D3DXVECTOR3(NearPlaneCenter + vX*NearPlaneWidth + vY*NearPlaneHeight);
	FrustumCorner[3] = D3DXVECTOR3(NearPlaneCenter + vX*NearPlaneWidth - vY*NearPlaneHeight);

	FrustumCorner[4] = D3DXVECTOR3(FarPlaneCenter - vX*FarPlaneWidth - vY*FarPlaneHeight);
	FrustumCorner[5] = D3DXVECTOR3(FarPlaneCenter - vX*FarPlaneWidth + vY*FarPlaneHeight);
	FrustumCorner[6] = D3DXVECTOR3(FarPlaneCenter + vX*FarPlaneWidth + vY*FarPlaneHeight);
	FrustumCorner[7] = D3DXVECTOR3(FarPlaneCenter + vX*FarPlaneWidth - vY*FarPlaneHeight);

	D3DXVECTOR3 vCenter(0,0,0);

	for(int i = 0; i < 8; i++)
		vCenter += FrustumCorner[i];

	vCenter/=8;

	for(int i = 0; i < 8; i++)
		FrustumCorner[i] += (FrustumCorner[i] - vCenter) * (vScale - 1.0);
}

void CPSSMUtils::CalculateLightForFrustum(int vCurrent)
{
	if(vCurrent < 0 || vCurrent > 3)
		vCurrent = 0;

	Current = vCurrent;

	float MaxX = -FLT_MAX;
	float MaxY = -FLT_MAX;
	float MinX = FLT_MAX;
	float MinY = FLT_MAX;
	float MaxZ = 0;

	LightCamera->setNearValue(Near);
	LightCamera->setFarValue(Far);
	//mP[Current].buildProjectionMatrixPerspectiveFovLH(LightCamera->getFOV(),1.0,LightCamera->getNearValue(),LightCamera->getFarValue());
	D3DXMatrixPerspectiveFovLH(&mP[Current], LightCamera->getFOV(), 1.0f, LightCamera->getNearValue(),LightCamera->getFarValue());
	mV[Current] = LightCamera->view();

	//D3DXMATRIX mLVP = mP[Current];
	//mLVP *= mV[Current];
	D3DXMATRIX mLVP = mV[Current] * mP[Current];
	for(int i = 0; i < 8; i++)
	{
		float X = FrustumCorner[i].x * mLVP[0] + FrustumCorner[i].y * mLVP[4] + FrustumCorner[i].z * mLVP[8] + mLVP[12];
		float Y = FrustumCorner[i].x * mLVP[1] + FrustumCorner[i].y * mLVP[5] + FrustumCorner[i].z * mLVP[9] + mLVP[13];
		float Z = FrustumCorner[i].x * mLVP[2] + FrustumCorner[i].y * mLVP[6] + FrustumCorner[i].z * mLVP[10] + mLVP[14];
		float W = FrustumCorner[i].x * mLVP[3] + FrustumCorner[i].y * mLVP[7] + FrustumCorner[i].z * mLVP[11] + mLVP[15];

		X /= W;
		Y /= W;

		if(X > MaxX)
			MaxX = X;

		if(Y > MaxY)
			MaxY = Y;

		if(X < MinX)
			MinX = X;

		if(Y < MinY)
			MinY = Y;

		if(Z > MaxZ)
			MaxZ = Z;
	}

	MaxX = Clamp(MaxX, -1.0f, 1.0f);
	MaxY = Clamp(MaxY, -1.0f, 1.0f);
	MinX = Clamp(MinX, -1.0f, 1.0f);
	MinY = Clamp(MinY, -1.0f, 1.0f);

	float nFar = MaxZ + Near + 1.5f;

	LightCamera->setNearValue(Near);
	LightCamera->setFarValue(Far);
	//LightCamera->setNearValue(SplitDistance[Current]);
	//LightCamera->setFarValue(SplitDistance[Current + 1]);
	//mP[Current].buildProjectionMatrixPerspectiveFovLH(LightCamera->getFOV(),1.0,LightCamera->getNearValue(),LightCamera->getFarValue());
	D3DXMatrixPerspectiveFovLH(&mP[Current], LightCamera->getFOV(), 1.0f, LightCamera->getNearValue(),LightCamera->getFarValue());
	mV[Current] = LightCamera->view();

	float ScaleX = 2.0f / (MaxX - MinX);
	float ScaleY = 2.0f / (MaxY - MinY);

	float OffsetX = -0.5f * (MaxX + MinX) * ScaleX;
	float OffsetY = -0.5f * (MaxY + MinY) * ScaleY;

	D3DXMATRIX cropMatrix = D3DXMATRIX(
		ScaleX,		0,			0,		0,
		0,			ScaleY,		0,		0,
		0,			0,			1,		0,
		OffsetX,	OffsetY,	0,		1);
	mP[Current] = mP[Current] * cropMatrix;

	//mP[Current][10] /= nFar;
	//mP[Current][14] /= nFar;
}

WSCamera* CPSSMUtils::getLightCamera()
{
	return LightCamera;
}

void CPSSMUtils::setLightCamera(WSCamera* vLightCamera)
{
	if(vLightCamera)
	{
		LightCamera = vLightCamera;
		Near = LightCamera->getNearValue();
		Far = LightCamera->getFarValue();
	}
}

D3DXMATRIX & CPSSMUtils::getProjectionMatrix(int vCurrent)
{
	return mP[vCurrent];
}

D3DXMATRIX & CPSSMUtils::getViewMatrix(int vCurrent)
{
	return mV[vCurrent];
}

int CPSSMUtils::getSplitsCount()
{
	return SplitsCount;
}

void CPSSMUtils::setSplitsCount(int vSplitsCount)
{
	if(vSplitsCount > 0)
	{
		if(vSplitsCount > 4)
			SplitsCount = 4;
		else
			SplitsCount = vSplitsCount;
	}
}

float CPSSMUtils::getSplitLambda()
{
	return SplitLambda;
}

void CPSSMUtils::setSplitLambda(float vSplitLambda)
{
	SplitLambda = vSplitLambda;
}

float CPSSMUtils::getSplitDistance(int vCurrent)
{
	return SplitDistance[vCurrent];
}

int CPSSMUtils::getCurrentPass()
{
	return Current;
}

float CPSSMUtils::Clamp(float A, float Min, float Max)
{
	if(A < Min)
		return Min;

	if(A > Max)
		return Max;

	return A;
}

render the scene

mPSSMUtils->CalculateSplitDistances(&mCamera);


	for (int i = 0; i < 4; ++i)
	{
		mShadowMapRTT[i].beginScene();
		{
			WSShader *shader = WSResourceManager::inst()->getShader(EShaderDepth);
			
				mPSSMUtils->CalculateFrustumCorners(&mCamera, i, 1.1f);
				mPSSMUtils->CalculateLightForFrustum(i);
				mRootNode->render(shader, mPSSMUtils->getViewMatrix(i) * mPSSMUtils->getProjectionMatrix(i))
		}
		mShadowMapRTT[i].endScene();
	}

 

this werid of pssm drive me crazy, i can't find which part is wrong, is any one can help me , any reply will be appreciated!

Edited by dreamjourney

Share this post


Link to post
Share on other sites

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