Improving the efficiency of frustum culling
Posted
by
DeadMG
on Game Development
See other posts from Game Development
or by DeadMG
Published on 2012-03-27T12:20:53Z
Indexed on
2012/03/27
23:44 UTC
Read the original article
Hit count: 269
I've got some code which performs frustum culling. However, this defines the "frustum" way too broadly- when I have ~10 objects on screen, the code returns 42 objects to be rendered. I've tried taking "slices" through the frustum to attempt to increase the accuracy of the technique, but it doesn't seem to have made much impact. I also significantly reduced the far plane, so that the objects are barely at the edge. Here's my code (where size
is the size in screen space- the resolution of the client area of the window I'm rendering into). Any suggestions?
auto&& size = GetDimensions();
D3DVIEWPORT9 vp = { 0, 0, size.x, size.y, 0, 1 };
D3DCALL(device->SetViewport(&vp));
static const int slices = 10;
std::vector<Object*> result;
for(int i = 0; i < slices; i++) {
D3DXVECTOR3 WorldSpaceFrustrumPoints[8] = {
D3DXVECTOR3(0, size.y, static_cast<float>(i) / slices),
D3DXVECTOR3(size.x, 0, static_cast<float>(i) / slices),
D3DXVECTOR3(size.x, size.y, static_cast<float>(i) / slices),
D3DXVECTOR3(0, 0, static_cast<float>(i) / slices),
D3DXVECTOR3(0, 0, static_cast<float>(i + 1) / slices),
D3DXVECTOR3(size.x, 0, static_cast<float>(i + 1) / slices),
D3DXVECTOR3(size.x, size.y, static_cast<float>(i + 1) / slices),
D3DXVECTOR3(0, size.y, static_cast<float>(i + 1) / slices)
};
D3DXMATRIXA16 Identity;
D3DXMatrixIdentity(&Identity);
D3DXVec3UnprojectArray(
WorldSpaceFrustrumPoints,
sizeof(D3DXVECTOR3),
WorldSpaceFrustrumPoints,
sizeof(D3DXVECTOR3),
&vp,
&Projection,
&View,
&Identity,
8
);
Math::AABB Frustrum;
auto world_begin = std::begin(WorldSpaceFrustrumPoints);
auto world_end = std::end(WorldSpaceFrustrumPoints);
auto world_initial = WorldSpaceFrustrumPoints[0];
Frustrum.BottomLeftClosest.x = std::accumulate(world_begin, world_end, world_initial, [](D3DXVECTOR3 lhs, D3DXVECTOR3 rhs) { return lhs.x < rhs.x ? lhs : rhs; }).x;
Frustrum.BottomLeftClosest.y = std::accumulate(world_begin, world_end, world_initial, [](D3DXVECTOR3 lhs, D3DXVECTOR3 rhs) { return lhs.y < rhs.y ? lhs : rhs; }).y;
Frustrum.BottomLeftClosest.z = std::accumulate(world_begin, world_end, world_initial, [](D3DXVECTOR3 lhs, D3DXVECTOR3 rhs) { return lhs.z < rhs.z ? lhs : rhs; }).z;
Frustrum.TopRightFurthest.x = std::accumulate(world_begin, world_end, world_initial, [](D3DXVECTOR3 lhs, D3DXVECTOR3 rhs) { return lhs.x > rhs.x ? lhs : rhs; }).x;
Frustrum.TopRightFurthest.y = std::accumulate(world_begin, world_end, world_initial, [](D3DXVECTOR3 lhs, D3DXVECTOR3 rhs) { return lhs.y > rhs.y ? lhs : rhs; }).y;
Frustrum.TopRightFurthest.z = std::accumulate(world_begin, world_end, world_initial, [](D3DXVECTOR3 lhs, D3DXVECTOR3 rhs) { return lhs.z > rhs.z ? lhs : rhs; }).z;
auto slices_result = ObjectTree.collision(Frustrum);
result.insert(result.end(), slices_result.begin(), slices_result.end());
}
return result;
© Game Development or respective owner