# Frustum Culling

This topic is 3835 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I have been trying to research ways to do Frustum Culling in DirectX, however, I can not find a tutorial anywhere. Does anyone know where I can figure out how to do this?

##### Share on other sites
lighthouse3d has a good tutorial, although it's for OpenGL. This is the code I used to use in native D3D9:

-Called when the camera is create or when projection parameters change:

void CAE3Camera::SetProjectionPerspective (FLOAT aspectRatio, FLOAT fieldOfView, FLOAT nearClip, FLOAT farClip){	D3DXMatrixPerspectiveFovLH( &matProj, fieldOfView, aspectRatio, nearClip, farClip );	aspect = aspectRatio;	fov = fieldOfView;	nearZ = nearClip;	farZ = farClip;	//generate coordinates for perspective projection volume	nearH = 2 * tanf(fov / 2.0f) * nearClip;	nearW = nearH * aspect;	farH = 2 * tanf(fov / 2.0f) * farClip;	farW = farH * aspect;	FLOAT nearX = nearW / 2.0f;	FLOAT nearY = nearH / 2.0f;	FLOAT farX = farW / 2.0f;	FLOAT farY = farH / 2.0f;		//near clip plane first, top-left then clockwise	frustumCoordsVS[0] = D3DXVECTOR3(-nearX, nearY, nearZ);	frustumCoordsVS[1] = D3DXVECTOR3(nearX, nearY, nearZ);	frustumCoordsVS[2] = D3DXVECTOR3(nearX, -nearY, nearZ);	frustumCoordsVS[3] = D3DXVECTOR3(-nearX, -nearY, nearZ);	//now far clip plane	frustumCoordsVS[4] = D3DXVECTOR3(-farX, farY, farZ);	frustumCoordsVS[5] = D3DXVECTOR3(farX, farY, farZ);	frustumCoordsVS[6] = D3DXVECTOR3(farX, -farY, farZ);	frustumCoordsVS[7] = D3DXVECTOR3(-farX, -farY, farZ);	}

-Called every frame
void CAE3Camera::Update (){	matViewProj = matView * matProj;	//calculate view frustum coordinates in world space	D3DXVec3TransformCoordArray(	frustumCoordsWS, 									sizeof(D3DXVECTOR3), 									frustumCoordsVS, 									sizeof(D3DXVECTOR3), 									&worldMatrix,									8 );		D3DXVECTOR3 nc = pos + lookDirection * nearZ;	D3DXVECTOR3 fc = pos + lookDirection * farZ;	frustumCentroid = pos + lookDirection * ((nearZ + farZ)/2.0f);	//near plane	frustumPlaneNormals[0] = lookDirection;	D3DXPlaneFromPointNormal(&frustumPlanes[0], &nc, &frustumPlaneNormals[0]);		//far plane	frustumPlaneNormals[1] = -lookDirection;	D3DXPlaneFromPointNormal(&frustumPlanes[1], &fc, &frustumPlaneNormals[1]);		//right plane	D3DXVECTOR3 a = frustumCoordsWS[5] - frustumCoordsWS[1];	D3DXVec3Normalize(&a, &a);	D3DXVECTOR3 b = frustumCoordsWS[2] - frustumCoordsWS[1];	D3DXVec3Normalize(&b, &b);	D3DXVec3Cross(&frustumPlaneNormals[2], &b, &a);	D3DXPlaneFromPointNormal(&frustumPlanes[2], &frustumCoordsWS[1], &frustumPlaneNormals[2]);	//left plane	a = frustumCoordsWS[3] - frustumCoordsWS[0];	D3DXVec3Normalize(&a, &a);	b = frustumCoordsWS[4] - frustumCoordsWS[0];	D3DXVec3Normalize(&b, &b);	D3DXVec3Cross(&frustumPlaneNormals[3], &b, &a);	D3DXPlaneFromPointNormal(&frustumPlanes[3], &frustumCoordsWS[0], &frustumPlaneNormals[3]);	//top plane	a = frustumCoordsWS[4] - frustumCoordsWS[0];	D3DXVec3Normalize(&a, &a);	b = frustumCoordsWS[1] - frustumCoordsWS[0];	D3DXVec3Normalize(&b, &b);	D3DXVec3Cross(&frustumPlaneNormals[4], &b, &a);	D3DXPlaneFromPointNormal(&frustumPlanes[4], &frustumCoordsWS[0], &frustumPlaneNormals[4]);	//bottom plane	a = frustumCoordsWS[2] - frustumCoordsWS[3];	D3DXVec3Normalize(&a, &a);	b = frustumCoordsWS[7] - frustumCoordsWS[3];	D3DXVec3Normalize(&b, &b);	D3DXVec3Cross(&frustumPlaneNormals[5], &b, &a);	D3DXPlaneFromPointNormal(&frustumPlanes[5], &frustumCoordsWS[3], &frustumPlaneNormals[5]);

-The actual frustum culling test for visibility
bool CAE3Camera::TestObjectForVisibiity (boost::shared_ptr<CAE3Object> object){	D3DXVECTOR3 objectCenter = object->GetBoundingCenterWS();	FLOAT objectRadius = object->GetBoundingRadius();	// Test the bounding sphere against the six frustum planes	for (UINT i = 0; i < 6; i++)	{		FLOAT dist = DistPointFromPlane(&objectCenter, &frustumPlanes, &frustumPlaneNormals);		if (dist < -objectRadius)		{			return false		}	}	return true;}FLOAT DistPointFromPlane (const D3DXVECTOR3* point, const D3DXPLANE* plane, const D3DXVECTOR3* planeNormal){	FLOAT dist = point->x * planeNormal->x;	dist += point->y * planeNormal->y;	dist += point->z * planeNormal->z;	dist += plane->d;	return (dist);}

##### Share on other sites
Thanks for the help, I have just a few questions about your code.

1) When I build my camera I only make a view matrix and a project matrix, so I do not have a look direction. However, isn't the look directions vector just the -z axis of the view matrix?

2) I do not have a world matrix, so could I just have that be an identity matrix?

3) Is the pos variable just the position of the camera? (So in this case 41, 42, 43 of my view matrix).

##### Share on other sites
Here is an easier way using and View and Projection matrix.
void UpdateViewingPlanes(Matrix4x4& ViewMatrix,Matrix4x4 ProjectionMatrix){	//Reset All the Visible Objects.	numVerticesVisible=0;	numObjectsVisible=0;	numFacesVisible=0;		Matrix4x4 ViewProjection=ViewMatrix*ProjectionMatrix;	clippingplanes[OAGE_FRONT_PLANE].a=ViewProjection._14+ViewProjection._13;	clippingplanes[OAGE_FRONT_PLANE].b=ViewProjection._24+ViewProjection._23;	clippingplanes[OAGE_FRONT_PLANE].c=ViewProjection._34+ViewProjection._33;	clippingplanes[OAGE_FRONT_PLANE].d=ViewProjection._44+ViewProjection._43;	clippingplanes[OAGE_BACK_PLANE].a=ViewProjection._14-ViewProjection._13;	clippingplanes[OAGE_BACK_PLANE].b=ViewProjection._24-ViewProjection._23;	clippingplanes[OAGE_BACK_PLANE].c=ViewProjection._34-ViewProjection._33;	clippingplanes[OAGE_BACK_PLANE].d=ViewProjection._44-ViewProjection._43;	clippingplanes[OAGE_LEFT_PLANE].a=ViewProjection._14+ViewProjection._11;	clippingplanes[OAGE_LEFT_PLANE].b=ViewProjection._24+ViewProjection._21;	clippingplanes[OAGE_LEFT_PLANE].c=ViewProjection._34+ViewProjection._31;	clippingplanes[OAGE_LEFT_PLANE].d=ViewProjection._44+ViewProjection._41;	clippingplanes[OAGE_RIGHT_PLANE].a=ViewProjection._14-ViewProjection._11;	clippingplanes[OAGE_RIGHT_PLANE].b=ViewProjection._24-ViewProjection._21;	clippingplanes[OAGE_RIGHT_PLANE].c=ViewProjection._34-ViewProjection._31;	clippingplanes[OAGE_RIGHT_PLANE].d=ViewProjection._44-ViewProjection._41;	clippingplanes[OAGE_BOTTOM_PLANE].a=ViewProjection._14+ViewProjection._12;	clippingplanes[OAGE_BOTTOM_PLANE].b=ViewProjection._24+ViewProjection._22;	clippingplanes[OAGE_BOTTOM_PLANE].c=ViewProjection._34+ViewProjection._32;	clippingplanes[OAGE_BOTTOM_PLANE].d=ViewProjection._44+ViewProjection._42;	clippingplanes[OAGE_TOP_PLANE].a=ViewProjection._14-ViewProjection._12;	clippingplanes[OAGE_TOP_PLANE].b=ViewProjection._24-ViewProjection._22;	clippingplanes[OAGE_TOP_PLANE].c=ViewProjection._34-ViewProjection._32;	clippingplanes[OAGE_TOP_PLANE].d=ViewProjection._44-ViewProjection._42;	//Normalize all the planes.	for(int i=0;i<6;++i)		clippingplanes.Normalize();}

• ### What is your GameDev Story?

In 2019 we are celebrating 20 years of GameDev.net! Share your GameDev Story with us.

• 10
• 11
• 13
• 9
• 11
• ### Forum Statistics

• Total Topics
634092
• Total Posts
3015437
×