Jump to content

  • Log In with Google      Sign In   
  • Create Account

Awesome job so far everyone! Please give us your feedback on how our article efforts are going. We still need more finished articles for our May contest theme: Remake the Classics

#Actuallipsryme

Posted 27 November 2012 - 11:22 AM

Update: Well now this seems to look a lot better.
http://cl.ly/image/170r1c2L0y0a/Project%202012-11-27%2016-11-13-27.jpg
What I did was invert the light direction. Not sure why MJP's light direction was already inverted there(?).
Plus these values:
const float CascadeSplits[4] = { 0.125f, 0.25f, 0.5f, 1.0f };
const float Bias = 0.005f;
const float ShadowDist = 0.4f;
const float BackupDistance = -1.0f;
The only question left now is how do I make this deferred...

#8lipsryme

Posted 27 November 2012 - 11:21 AM

Update: Well now this seems to look a lot better.
http://cl.ly/image/170r1c2L0y0a/Project%202012-11-27%2016-11-13-27.jpg
What I did was invert the light direction. Not sure why MJP's light direction was already inverted there(?)

The only question left now is how do I make this deferred...

#7lipsryme

Posted 27 November 2012 - 11:20 AM

Update: Well now this seems to look a lot better.
http://cl.ly/image/170r1c2L0y0a/Project%202012-11-27%2016-11-13-27.jpg
What I did was invert the light direction. Not sure why MJP's light direction was already inverted there(?)

The only question left now is how do I make this deferred...

For completeness I'm going to post the function that constructs the light's view and projection matrix again:
void DirectionalLight::CalculateLightProjection(BaseCamera* camera, UINT &cascadeIdx,
												const float &sMapSize)
{
	const float CascadeSplits[4] = { 0.125f, 0.25f, 0.5f, 1.0f };
	const float Bias = 0.005f;
	const float ShadowDist = 0.2f;
	const float BackupDistance = -20.0f;

	// Get the 8 points of the view frustum in world space
	XMFLOAT3 corner[8];
	XMVECTOR frustumCornersWS[8];
	camera->ExtractFrustumCorner(corner);
	for(UINT i = 0; i < 8; i++)
	{
		frustumCornersWS[i] = XMLoadFloat3(&amp;amp;corner[i]);
	}


	float prevSplitDist = cascadeIdx == 0 ? 0.0f : CascadeSplits[cascadeIdx - 1] * ShadowDist;
	float splitDist = CascadeSplits[cascadeIdx] * ShadowDist;

	// Scale by the shadow view distance
	for(UINT i = 0; i < 4; ++i)
	{
		XMVECTOR cornerRay = XMVectorSubtract(frustumCornersWS[i + 4], frustumCornersWS[i]);
		XMVECTOR nearCornerRay = XMVectorScale(cornerRay, prevSplitDist);
		XMVECTOR farCornerRay = XMVectorScale(cornerRay, splitDist);
		frustumCornersWS[i + 4] = XMVectorAdd(frustumCornersWS[i], farCornerRay);
		frustumCornersWS[i] = XMVectorAdd(frustumCornersWS[i], nearCornerRay);
	}

	// Calculate the centroid of the view frustum
	XMVECTOR sphereCenterVec = XMVectorZero();
	for(UINT i = 0; i < 8; ++i)
	{
		sphereCenterVec = XMVectorAdd(sphereCenterVec, frustumCornersWS[i]);
	}
	sphereCenterVec = XMVectorScale(sphereCenterVec, 1.0f / 8.0f);

	// Calculate the radius of a bounding sphere
	XMVECTOR sphereRadiusVec = XMVectorZero();
	for(UINT i = 0; i < 8; ++i)
	{
		XMVECTOR dist = XMVector3Length(XMVectorSubtract(frustumCornersWS[i], sphereCenterVec));
		sphereRadiusVec = XMVectorMax(sphereRadiusVec, dist);
	}

	float nearClip = camera->GetNearClip();
	sphereRadiusVec = XMVectorRound(sphereRadiusVec);
	const float sphereRadius = XMVectorGetX(sphereRadiusVec);
	const float backupDist = sphereRadius + nearClip + BackupDistance;

	// Get Position of the shadow camera
	XMVECTOR shadowCameraPosVec = sphereCenterVec;
	XMVECTOR backupDirVec = XMLoadFloat3(&amp;amp;this->direction);
	backupDirVec = XMVectorScale(backupDirVec, backupDist);
	shadowCameraPosVec = XMVectorAdd(shadowCameraPosVec, backupDirVec);

	// Create Orthographic Projection
	XMMATRIX orthoProj = XMMatrixOrthographicOffCenterLH(-sphereRadius, sphereRadius, -sphereRadius, sphereRadius,
														 nearClip, backupDist + sphereRadius);



	// Create View Matrix
	XMVECTOR up = XMVectorSet(0.0f, 1.0f, 0.0f, 1.0f);
	shadowCameraPosVec = XMVectorSetW(shadowCameraPosVec, 1.0f);
	sphereCenterVec = XMVectorSetW(sphereCenterVec, 1.0f);
	XMMATRIX lightView = XMMatrixLookAtLH(shadowCameraPosVec, sphereCenterVec, up);

	// Create the rounding matrix, by projecting the world-space origin and determining
	// the fractional offset in texel space
	XMMATRIX shadowMatrix = lightView * orthoProj;
	XMVECTOR shadowOrigin = XMVectorSet(0.0f, 0.0f, 0.0f, 1.0f);
	shadowOrigin = XMVector4Transform(shadowOrigin, shadowMatrix);
	shadowOrigin = XMVectorScale(shadowOrigin, sMapSize / 2.0f);

	XMVECTOR roundedOrigin = XMVectorRound(shadowOrigin);
	XMVECTOR roundOffset = XMVectorSubtract(roundedOrigin, shadowOrigin);
	roundOffset = XMVectorScale(roundOffset, 2.0f / sMapSize);
	roundOffset = XMVectorSetZ(roundOffset, 0.0f);
	roundOffset = XMVectorSetW(roundOffset, 0.0f);

	orthoProj.r[3] = XMVectorAdd(orthoProj.r[3], roundOffset);
	shadowMatrix = XMMatrixMultiplyTranspose(lightView, orthoProj);


	// Copy the data into the constant buffer
	XMStoreFloat4x4(&amp;amp;this->lightTransformProperties.ViewProjection, shadowMatrix);
}

#6lipsryme

Posted 27 November 2012 - 11:20 AM

Update: Well now this seems to look a lot better.
http://cl.ly/image/170r1c2L0y0a/Project%202012-11-27%2016-11-13-27.jpg
What I did was invert the light direction. Not sure why MJP's light direction was already inverted there(?)

The only question left now is how do I do this deferred...

For completeness I'm going to post the function that constructs the light's view and projection matrix again:
void DirectionalLight::CalculateLightProjection(BaseCamera* camera, UINT &amp;amp;cascadeIdx,
												const float &amp;amp;sMapSize)
{
	const float CascadeSplits[4] = { 0.125f, 0.25f, 0.5f, 1.0f };
	const float Bias = 0.005f;
	const float ShadowDist = 0.2f;
	const float BackupDistance = -20.0f;

	// Get the 8 points of the view frustum in world space
	XMFLOAT3 corner[8];
	XMVECTOR frustumCornersWS[8];
	camera->ExtractFrustumCorner(corner);
	for(UINT i = 0; i < 8; i++)
	{
		frustumCornersWS[i] = XMLoadFloat3(&amp;amp;corner[i]);
	}


	float prevSplitDist = cascadeIdx == 0 ? 0.0f : CascadeSplits[cascadeIdx - 1] * ShadowDist;
	float splitDist = CascadeSplits[cascadeIdx] * ShadowDist;

	// Scale by the shadow view distance
	for(UINT i = 0; i < 4; ++i)
	{
		XMVECTOR cornerRay = XMVectorSubtract(frustumCornersWS[i + 4], frustumCornersWS[i]);
		XMVECTOR nearCornerRay = XMVectorScale(cornerRay, prevSplitDist);
		XMVECTOR farCornerRay = XMVectorScale(cornerRay, splitDist);
		frustumCornersWS[i + 4] = XMVectorAdd(frustumCornersWS[i], farCornerRay);
		frustumCornersWS[i] = XMVectorAdd(frustumCornersWS[i], nearCornerRay);
	}

	// Calculate the centroid of the view frustum
	XMVECTOR sphereCenterVec = XMVectorZero();
	for(UINT i = 0; i < 8; ++i)
	{
		sphereCenterVec = XMVectorAdd(sphereCenterVec, frustumCornersWS[i]);
	}
	sphereCenterVec = XMVectorScale(sphereCenterVec, 1.0f / 8.0f);

	// Calculate the radius of a bounding sphere
	XMVECTOR sphereRadiusVec = XMVectorZero();
	for(UINT i = 0; i < 8; ++i)
	{
		XMVECTOR dist = XMVector3Length(XMVectorSubtract(frustumCornersWS[i], sphereCenterVec));
		sphereRadiusVec = XMVectorMax(sphereRadiusVec, dist);
	}

	float nearClip = camera->GetNearClip();
	sphereRadiusVec = XMVectorRound(sphereRadiusVec);
	const float sphereRadius = XMVectorGetX(sphereRadiusVec);
	const float backupDist = sphereRadius + nearClip + BackupDistance;

	// Get Position of the shadow camera
	XMVECTOR shadowCameraPosVec = sphereCenterVec;
	XMVECTOR backupDirVec = XMLoadFloat3(&amp;amp;this->direction);
	backupDirVec = XMVectorScale(backupDirVec, backupDist);
	shadowCameraPosVec = XMVectorAdd(shadowCameraPosVec, backupDirVec);

	// Create Orthographic Projection
	XMMATRIX orthoProj = XMMatrixOrthographicOffCenterLH(-sphereRadius, sphereRadius, -sphereRadius, sphereRadius,
														 nearClip, backupDist + sphereRadius);



	// Create View Matrix
	XMVECTOR up = XMVectorSet(0.0f, 1.0f, 0.0f, 1.0f);
	shadowCameraPosVec = XMVectorSetW(shadowCameraPosVec, 1.0f);
	sphereCenterVec = XMVectorSetW(sphereCenterVec, 1.0f);
	XMMATRIX lightView = XMMatrixLookAtLH(shadowCameraPosVec, sphereCenterVec, up);

	// Create the rounding matrix, by projecting the world-space origin and determining
	// the fractional offset in texel space
	XMMATRIX shadowMatrix = lightView * orthoProj;
	XMVECTOR shadowOrigin = XMVectorSet(0.0f, 0.0f, 0.0f, 1.0f);
	shadowOrigin = XMVector4Transform(shadowOrigin, shadowMatrix);
	shadowOrigin = XMVectorScale(shadowOrigin, sMapSize / 2.0f);

	XMVECTOR roundedOrigin = XMVectorRound(shadowOrigin);
	XMVECTOR roundOffset = XMVectorSubtract(roundedOrigin, shadowOrigin);
	roundOffset = XMVectorScale(roundOffset, 2.0f / sMapSize);
	roundOffset = XMVectorSetZ(roundOffset, 0.0f);
	roundOffset = XMVectorSetW(roundOffset, 0.0f);

	orthoProj.r[3] = XMVectorAdd(orthoProj.r[3], roundOffset);
	shadowMatrix = XMMatrixMultiplyTranspose(lightView, orthoProj);


	// Copy the data into the constant buffer
	XMStoreFloat4x4(&amp;amp;this->lightTransformProperties.ViewProjection, shadowMatrix);
}

#5lipsryme

Posted 27 November 2012 - 11:20 AM

Update: Well now this seems to look a lot better.
http://cl.ly/image/170r1c2L0y0a/Project%202012-11-27%2016-11-13-27.jpg
What I did was invert the light direction. Not sure why MJP's light direction was already inverted there(?)

The only question now is how do I do this deferred...

For completeness I'm going to post the function that constructs the light's view and projection matrix again:
void DirectionalLight::CalculateLightProjection(BaseCamera* camera, UINT &amp;amp;cascadeIdx,
												const float &amp;amp;sMapSize)
{
	const float CascadeSplits[4] = { 0.125f, 0.25f, 0.5f, 1.0f };
	const float Bias = 0.005f;
	const float ShadowDist = 0.2f;
	const float BackupDistance = -20.0f;

	// Get the 8 points of the view frustum in world space
	XMFLOAT3 corner[8];
	XMVECTOR frustumCornersWS[8];
	camera->ExtractFrustumCorner(corner);
	for(UINT i = 0; i < 8; i++)
	{
		frustumCornersWS[i] = XMLoadFloat3(&amp;amp;corner[i]);
	}


	float prevSplitDist = cascadeIdx == 0 ? 0.0f : CascadeSplits[cascadeIdx - 1] * ShadowDist;
	float splitDist = CascadeSplits[cascadeIdx] * ShadowDist;

	// Scale by the shadow view distance
	for(UINT i = 0; i < 4; ++i)
	{
		XMVECTOR cornerRay = XMVectorSubtract(frustumCornersWS[i + 4], frustumCornersWS[i]);
		XMVECTOR nearCornerRay = XMVectorScale(cornerRay, prevSplitDist);
		XMVECTOR farCornerRay = XMVectorScale(cornerRay, splitDist);
		frustumCornersWS[i + 4] = XMVectorAdd(frustumCornersWS[i], farCornerRay);
		frustumCornersWS[i] = XMVectorAdd(frustumCornersWS[i], nearCornerRay);
	}

	// Calculate the centroid of the view frustum
	XMVECTOR sphereCenterVec = XMVectorZero();
	for(UINT i = 0; i < 8; ++i)
	{
		sphereCenterVec = XMVectorAdd(sphereCenterVec, frustumCornersWS[i]);
	}
	sphereCenterVec = XMVectorScale(sphereCenterVec, 1.0f / 8.0f);

	// Calculate the radius of a bounding sphere
	XMVECTOR sphereRadiusVec = XMVectorZero();
	for(UINT i = 0; i < 8; ++i)
	{
		XMVECTOR dist = XMVector3Length(XMVectorSubtract(frustumCornersWS[i], sphereCenterVec));
		sphereRadiusVec = XMVectorMax(sphereRadiusVec, dist);
	}

	float nearClip = camera->GetNearClip();
	sphereRadiusVec = XMVectorRound(sphereRadiusVec);
	const float sphereRadius = XMVectorGetX(sphereRadiusVec);
	const float backupDist = sphereRadius + nearClip + BackupDistance;

	// Get Position of the shadow camera
	XMVECTOR shadowCameraPosVec = sphereCenterVec;
	XMVECTOR backupDirVec = XMLoadFloat3(&amp;amp;this->direction);
	backupDirVec = XMVectorScale(backupDirVec, backupDist);
	shadowCameraPosVec = XMVectorAdd(shadowCameraPosVec, backupDirVec);

	// Create Orthographic Projection
	XMMATRIX orthoProj = XMMatrixOrthographicOffCenterLH(-sphereRadius, sphereRadius, -sphereRadius, sphereRadius,
														 nearClip, backupDist + sphereRadius);



	// Create View Matrix
	XMVECTOR up = XMVectorSet(0.0f, 1.0f, 0.0f, 1.0f);
	shadowCameraPosVec = XMVectorSetW(shadowCameraPosVec, 1.0f);
	sphereCenterVec = XMVectorSetW(sphereCenterVec, 1.0f);
	XMMATRIX lightView = XMMatrixLookAtLH(shadowCameraPosVec, sphereCenterVec, up);

	// Create the rounding matrix, by projecting the world-space origin and determining
	// the fractional offset in texel space
	XMMATRIX shadowMatrix = lightView * orthoProj;
	XMVECTOR shadowOrigin = XMVectorSet(0.0f, 0.0f, 0.0f, 1.0f);
	shadowOrigin = XMVector4Transform(shadowOrigin, shadowMatrix);
	shadowOrigin = XMVectorScale(shadowOrigin, sMapSize / 2.0f);

	XMVECTOR roundedOrigin = XMVectorRound(shadowOrigin);
	XMVECTOR roundOffset = XMVectorSubtract(roundedOrigin, shadowOrigin);
	roundOffset = XMVectorScale(roundOffset, 2.0f / sMapSize);
	roundOffset = XMVectorSetZ(roundOffset, 0.0f);
	roundOffset = XMVectorSetW(roundOffset, 0.0f);

	orthoProj.r[3] = XMVectorAdd(orthoProj.r[3], roundOffset);
	shadowMatrix = XMMatrixMultiplyTranspose(lightView, orthoProj);


	// Copy the data into the constant buffer
	XMStoreFloat4x4(&amp;amp;this->lightTransformProperties.ViewProjection, shadowMatrix);
}

#4lipsryme

Posted 27 November 2012 - 09:14 AM

After randomly playing around with the ShadowDist and BackupDistance I've managed to get a shadow map looking like this:
http://cl.ly/image/1y41393j232e
If not I'd be happy to know what I'm doing wrong, as this seems to be an issue not with the code but the settings.

I'm still not sure if this is a correct image that I should be getting for the shadowmap atlas but I'm going to assume so at the moment and continue implementing the actual shadow projection.
Doing this deferred just means that I have to render the shadows to a texture, that has been cleared white, right ? And afterwards multiply this by the lighting...?

Update: Well now this seems to look a lot better.
http://cl.ly/image/170r1c2L0y0a/Project%202012-11-27%2016-11-13-27.jpg
What I did was invert the light direction. Not sure why MJP's light direction was already inverted there(?)

For completeness I'm going to post the function that constructs the light's view and projection matrix again:
void DirectionalLight::CalculateLightProjection(BaseCamera* camera, UINT &amp;cascadeIdx,
												const float &amp;sMapSize)
{
	const float CascadeSplits[4] = { 0.125f, 0.25f, 0.5f, 1.0f };
	const float Bias = 0.005f;
	const float ShadowDist = 0.2f;
	const float BackupDistance = -20.0f;

	// Get the 8 points of the view frustum in world space
	XMFLOAT3 corner[8];
	XMVECTOR frustumCornersWS[8];
	camera->ExtractFrustumCorner(corner);
	for(UINT i = 0; i < 8; i++)
	{
		frustumCornersWS[i] = XMLoadFloat3(&amp;corner[i]);
	}


	float prevSplitDist = cascadeIdx == 0 ? 0.0f : CascadeSplits[cascadeIdx - 1] * ShadowDist;
	float splitDist = CascadeSplits[cascadeIdx] * ShadowDist;

	// Scale by the shadow view distance
	for(UINT i = 0; i < 4; ++i)
	{
		XMVECTOR cornerRay = XMVectorSubtract(frustumCornersWS[i + 4], frustumCornersWS[i]);
		XMVECTOR nearCornerRay = XMVectorScale(cornerRay, prevSplitDist);
		XMVECTOR farCornerRay = XMVectorScale(cornerRay, splitDist);
		frustumCornersWS[i + 4] = XMVectorAdd(frustumCornersWS[i], farCornerRay);
		frustumCornersWS[i] = XMVectorAdd(frustumCornersWS[i], nearCornerRay);
	}

	// Calculate the centroid of the view frustum
	XMVECTOR sphereCenterVec = XMVectorZero();
	for(UINT i = 0; i < 8; ++i)
	{
		sphereCenterVec = XMVectorAdd(sphereCenterVec, frustumCornersWS[i]);
	}
	sphereCenterVec = XMVectorScale(sphereCenterVec, 1.0f / 8.0f);

	// Calculate the radius of a bounding sphere
	XMVECTOR sphereRadiusVec = XMVectorZero();
	for(UINT i = 0; i < 8; ++i)
	{
		XMVECTOR dist = XMVector3Length(XMVectorSubtract(frustumCornersWS[i], sphereCenterVec));
		sphereRadiusVec = XMVectorMax(sphereRadiusVec, dist);
	}

	float nearClip = camera->GetNearClip();
	sphereRadiusVec = XMVectorRound(sphereRadiusVec);
	const float sphereRadius = XMVectorGetX(sphereRadiusVec);
	const float backupDist = sphereRadius + nearClip + BackupDistance;

	// Get Position of the shadow camera
	XMVECTOR shadowCameraPosVec = sphereCenterVec;
	XMVECTOR backupDirVec = XMLoadFloat3(&amp;this->direction);
	backupDirVec = XMVectorScale(backupDirVec, backupDist);
	shadowCameraPosVec = XMVectorAdd(shadowCameraPosVec, backupDirVec);

	// Create Orthographic Projection
	XMMATRIX orthoProj = XMMatrixOrthographicOffCenterLH(-sphereRadius, sphereRadius, -sphereRadius, sphereRadius,
														 nearClip, backupDist + sphereRadius);



	// Create View Matrix
	XMVECTOR up = XMVectorSet(0.0f, 1.0f, 0.0f, 1.0f);
	shadowCameraPosVec = XMVectorSetW(shadowCameraPosVec, 1.0f);
	sphereCenterVec = XMVectorSetW(sphereCenterVec, 1.0f);
	XMMATRIX lightView = XMMatrixLookAtLH(shadowCameraPosVec, sphereCenterVec, up);

	// Create the rounding matrix, by projecting the world-space origin and determining
	// the fractional offset in texel space
	XMMATRIX shadowMatrix = lightView * orthoProj;
	XMVECTOR shadowOrigin = XMVectorSet(0.0f, 0.0f, 0.0f, 1.0f);
	shadowOrigin = XMVector4Transform(shadowOrigin, shadowMatrix);
	shadowOrigin = XMVectorScale(shadowOrigin, sMapSize / 2.0f);

	XMVECTOR roundedOrigin = XMVectorRound(shadowOrigin);
	XMVECTOR roundOffset = XMVectorSubtract(roundedOrigin, shadowOrigin);
	roundOffset = XMVectorScale(roundOffset, 2.0f / sMapSize);
	roundOffset = XMVectorSetZ(roundOffset, 0.0f);
	roundOffset = XMVectorSetW(roundOffset, 0.0f);

	orthoProj.r[3] = XMVectorAdd(orthoProj.r[3], roundOffset);
	shadowMatrix = XMMatrixMultiplyTranspose(lightView, orthoProj);


	// Copy the data into the constant buffer
	XMStoreFloat4x4(&amp;this->lightTransformProperties.ViewProjection, shadowMatrix);
}

PARTNERS