Jump to content
  • Advertisement
Sign in to follow this  
Hurp

Frustum Culling

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

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 this post


Link to post
Share on other sites
Advertisement
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 this post


Link to post
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 this post


Link to post
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();
}

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.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!