1

I recently made an application with C# and OpenGL using OpenTK. I've integrated a frustum culling system in order to improve performance, but for some reasons, objects aren't culled correctly. What I mean is that instead of showing all visibles objects nicely, it just cull random objects and when I rotate the camera, some objects appears and disappears. I know it's normal but not when I should see them. The actual frustum culling code is a C# port of my working C++/DirectXMath code used in something else.
Here's how I create the six frustum planes :

        // Create a new view-projection matrices.
        var vp = viewMatrix * projMatrix;

        // Left plane.
        frustumPlanes[0] = new Vector4
        {
            X = vp.M14 + vp.M11,
            Y = vp.M24 + vp.M21,
            Z = vp.M34 + vp.M31,
            W = vp.M44 + vp.M41
        };
        // Right plane.
        frustumPlanes[1] = new Vector4
        {
            X = vp.M14 - vp.M11,
            Y = vp.M24 - vp.M21,
            Z = vp.M34 - vp.M31,
            W = vp.M44 - vp.M41
        };
        // Top plane.
        frustumPlanes[2] = new Vector4
        {
            X = vp.M14 - vp.M12,
            Y = vp.M24 - vp.M22,
            Z = vp.M34 - vp.M32,
            W = vp.M44 - vp.M42
        };
        // Bottom plane.
        frustumPlanes[3] = new Vector4
        {
            X = vp.M14 + vp.M12,
            Y = vp.M24 + vp.M22,
            Z = vp.M34 + vp.M32,
            W = vp.M44 + vp.M42
        };
        // Near plane.
        frustumPlanes[4] = new Vector4
        {
            X = vp.M13,
            Y = vp.M23,
            Z = vp.M33,
            W = vp.M43,
        };
        // Far plane.
        frustumPlanes[5] = new Vector4
        {
            X = vp.M14 - vp.M13,
            Y = vp.M24 - vp.M23,
            Z = vp.M34 - vp.M33,
            W = vp.M44 - vp.M43
        };

        // Normalize all the planes.
        for (int i = 0; i < 6; i++)
            frustumPlanes[i] = Vector4.Normalize(frustumPlanes[i]);

And I check if a sphere should be culled here :

    public bool CullSphere(Vector3 position, float radius = 0.0f)
    {
        foreach (var plane in frustumPlanes)
        {
            // Verify if the point is behind the plane.
            if (Vector3.Dot(plane.Xyz, position) + plane.W < -radius)
                return true;
        }

        return false;
    }

I saw on some other posts people multiplying the view and projection matrices manually, but I'm not sure that it's the cause of the problem. What I did wrong ? Thanks

ThePatchou
  • 21
  • 3

1 Answers1

0

Try use my code implementation https://github.com/ALEXGREENALEX/LED_Engine/tree/master/LED_Engine/LED_Engine ("FrustumCulling.cs" and Draw call in "Game.cs"):

static void Draw(Mesh m)
{
    m.CalculateMatrices(MainCamera);
    FrustumCulling.ExtractFrustum(MainCamera.GetViewMatrix() * MainCamera.GetProjectionMatrix());
    float Scale = Math.Max(m.Scale.X, Math.Max(m.Scale.Y, m.Scale.Z));

    if (FrustumCulling.SphereInFrustum(m.Position, m.BoundingSphere.Outer * Scale))
        for (int i = 0; i < m.Parts.Count; i++)
            // ...
                Draw(m, m.Parts[i]);
}

P.S.

1) After extracting frustum you must check intersection with Scaled objects (take maximum value of skale and multiply it by outer BoundingSphere radius).

2) In some old examples we can see MVP matrix in ExtractFrustum function (like there: http://www.codesampler.com/oglsrc/oglsrc_12.htm#ogl_frustum_culling). That's wrong name! They are use old API and Model matrix in this calculation is identity matrix (they call MV - ModelView matrix, but really thats only View matrix):

glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
updateViewMatrix();
calculateFrustumPlanes();

void calculateFrustumPlanes(void)
{
    float p[16];   // projection matrix
    float mv[16];  // **VIEW MATRIX!!!**
    float mvp[16]; // **View-Projection matrix!!!**

    glGetFloatv( GL_PROJECTION_MATRIX, p );
    glGetFloatv( GL_MODELVIEW_MATRIX, mv );
    //...
}
Alex Green
  • 123
  • 8