Quick solution for 3D culling in libGDX

By default, libGDX does not perform any kind of culling when rendering models via the ModelBatch. This blog post by @xoppa shows how it can be implemented with game logic specific knowledge. That means it is not generic and can make use game specific information, because the models will be culled before they actually reach the ModelBatch.

However, we have tried a more generic approach by extending ModelBatch and implementing culling right here and there. The following CullingModelBatch is optimized for speed, but also has some limitations:

public class CullingModelBatch extends ModelBatch {

    private ObjectMap<Mesh, Float> radiuses = new ObjectMap<Mesh, Float>();

    private Vector3 tmp = new Vector3();

    public void flush() {
        Iterator<Renderable> iter = renderables.iterator();

        while (iter.hasNext()) {
            Renderable renderable = iter.next();
            if (!camera.frustum.sphereInFrustumWithoutNearFar(tmp, getRadiusOfMesh(renderable.mesh))) {

    private float getRadiusOfMesh(Mesh mesh) {
        Float radius = radiuses.get(mesh);
        if (radius != null) {
            return radius;

        Vector3 dimensions = mesh.calculateBoundingBox().getDimensions();
        radius = Math.max(Math.max(dimensions.x, dimensions.y), dimensions.z);

        radiuses.put(mesh, radius);
        return radius;



  • Easy to activate culling just by replacing your standard batch with this one
  • Lightning fast
    • Because of the sphereInFrustumWithoutNearFar test
    • Because of the caching mechanism
    • Because of the Mesh check instead of the MeshPart check


  • Does not work with animations
  • Can produce false positives (not everything that could be culled, will be culled)
    • Because of the sphere check
    • Because we check the whole Mesh and not the rendered MeshPart
  • Small memory footprint

The memory overhead of this approach might very well be neglected. In total it is a trade-off between CPU processing time and GPU rendering time. To get more accurate results one might replace the sphere check with a bounding box check, or check the actual MeshPart of the renderable instead of the complete Mesh.

This apprach might not produce the optimal results, but it is a very quick solution which you can try just by replacing new ModelBatch() with new CullingModelBatch() in your game. In many games this might very well be sufficient because it does get rid of a lot of models very quickly and in our upcoming game Pocket Galaxy it was completely sufficient.

Leave a Reply

Your email address will not be published. Required fields are marked *