ugluk

08-11-2010, 02:27 PM

I've been experimenting with an extremely simple frustum cull algorithm I've developed. The frustum is approximated as a Minkowski sum of the center line of the frustum and ever increasing spheres (since the frustum also expands), truncated by near and far planes. The intersection test between this frustum approximation and a sphere costs just 2 dot products:

returns true if sphere s intersects frustum approximation:

GLfloat frustum[6]; // L, R, B, T, N, F of the frustum

Sphere s; // a struct of center and radius

Vector <GLfloat, 3> view_origin; // origin of the viewing system

Vector <GLfloat, 3> frustum_d; // negated view_matrix's 3rd column

GLfloat frustum_r(std::sqrt(GetR(frustum) * GetR(frustum) + GetT(frustum) * GetT(frustum)) / GetN(frustum));

GLfloat da(dot(sphere_center - view_origin, frustum_d));

if ((da + s.radius < 0) || (da - s.radius > GetF(frustum)))

{

return false;

}

else

{

Vector<GLfloat, 3> dc(s.center - view_origin - da * frustum_d);

GLfloat rs(frustum_radius * (da + s.radius) + s.radius);

return dot(dc, dc) <= rs * rs;

}

The code assumes a symmetric orthogonal frustum.

So what do you think, is the idea useful? I've tested it in my code and it works, but for my purposes it is slower than the usual frustum-AABB test and slightly worse than the usual frustum-sphere test, as regards rendering performance. Maybe other simple culls exist?

UPDATE: I think this is just the old trick of using a truncated circular cone instead of the real frustum.

returns true if sphere s intersects frustum approximation:

GLfloat frustum[6]; // L, R, B, T, N, F of the frustum

Sphere s; // a struct of center and radius

Vector <GLfloat, 3> view_origin; // origin of the viewing system

Vector <GLfloat, 3> frustum_d; // negated view_matrix's 3rd column

GLfloat frustum_r(std::sqrt(GetR(frustum) * GetR(frustum) + GetT(frustum) * GetT(frustum)) / GetN(frustum));

GLfloat da(dot(sphere_center - view_origin, frustum_d));

if ((da + s.radius < 0) || (da - s.radius > GetF(frustum)))

{

return false;

}

else

{

Vector<GLfloat, 3> dc(s.center - view_origin - da * frustum_d);

GLfloat rs(frustum_radius * (da + s.radius) + s.radius);

return dot(dc, dc) <= rs * rs;

}

The code assumes a symmetric orthogonal frustum.

So what do you think, is the idea useful? I've tested it in my code and it works, but for my purposes it is slower than the usual frustum-AABB test and slightly worse than the usual frustum-sphere test, as regards rendering performance. Maybe other simple culls exist?

UPDATE: I think this is just the old trick of using a truncated circular cone instead of the real frustum.