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

Filed under:
|

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

Related posts about c++

Related posts about directx