diff --git a/src/main/java/bdv/tools/transformation/TransformedSource.java b/src/main/java/bdv/tools/transformation/TransformedSource.java
index 4c91204a9e8fc2862b1d8d00b3d0c8aa2915513e..0d84ea5c9ae15ecdf14e3dc585f006b18bdaae5a 100644
--- a/src/main/java/bdv/tools/transformation/TransformedSource.java
+++ b/src/main/java/bdv/tools/transformation/TransformedSource.java
@@ -121,6 +121,12 @@ public class TransformedSource< T > implements Source< T >, MipmapOrdering
 		this.composed = new AffineTransform3D();
 	}
 
+	@Override
+	public boolean doBoundingBoxCulling()
+	{
+		return source.doBoundingBoxCulling();
+	}
+
 	/*
 	 * EXTRA TRANSFORMATION methods
 	 */
diff --git a/src/main/java/bdv/util/RealRandomAccessibleSource.java b/src/main/java/bdv/util/RealRandomAccessibleSource.java
index 6c011e1ab0481030aa624627b213fb78fc98162d..7c337ee3a23a72618f9de9fc4b2d163fa339b430 100644
--- a/src/main/java/bdv/util/RealRandomAccessibleSource.java
+++ b/src/main/java/bdv/util/RealRandomAccessibleSource.java
@@ -57,17 +57,25 @@ public abstract class RealRandomAccessibleSource< T extends Type< T > > implemen
 
 	protected final VoxelDimensions voxelDimensions;
 
+	protected final boolean doBoundingBoxIntersectionCheck;
+
 	public RealRandomAccessibleSource( final RealRandomAccessible< T > accessible, final T type, final String name )
 	{
-		this( accessible, type, name, null );
+		this( accessible, type, name, null, false );
 	}
 
 	public RealRandomAccessibleSource( final RealRandomAccessible< T > accessible, final T type, final String name, final VoxelDimensions voxelDimensions )
+	{
+		this( accessible, type, name, voxelDimensions, false );
+	}
+
+	public RealRandomAccessibleSource( final RealRandomAccessible< T > accessible, final T type, final String name, final VoxelDimensions voxelDimensions, final boolean doBoundingBoxIntersectionCheck )
 	{
 		this.accessible = accessible;
 		this.type = type.createVariable();
 		this.name = name;
 		this.voxelDimensions = voxelDimensions;
+		this.doBoundingBoxIntersectionCheck = doBoundingBoxIntersectionCheck;
 	}
 
 	@Override
@@ -125,4 +133,10 @@ public abstract class RealRandomAccessibleSource< T extends Type< T > > implemen
 	{
 		return 1;
 	}
+
+	@Override
+	public boolean doBoundingBoxCulling()
+	{
+		return doBoundingBoxIntersectionCheck;
+	}
 }
diff --git a/src/main/java/bdv/viewer/Source.java b/src/main/java/bdv/viewer/Source.java
index 9cd100c4c6a673d391b532f8cb8d8c7234e33445..63885f00ff6ddfe90eadf24fe63738dff8f74dd6 100644
--- a/src/main/java/bdv/viewer/Source.java
+++ b/src/main/java/bdv/viewer/Source.java
@@ -68,6 +68,22 @@ public interface Source< T >
 	 */
 	public RandomAccessibleInterval< T > getSource( int t, int level );
 
+	/**
+	 * Whether this source participates in bounding box culling.
+	 * <p>
+	 * If {@code true}, then this source will only be rendered if its bounding
+	 * box, i.e., the interval of {@link #getSource}, intersects the
+	 * current screen area (when transformed to viewer coordinates).
+	 * <p>
+	 * If {@code false}, then this source will be always rendered (if it is
+	 * set to be visible.)
+	 *
+	 * @return {@code true}, if this source participates in bounding box culling.
+	 */
+	public default boolean doBoundingBoxCulling()
+	{
+		return true;
+	}
 
 	/**
 	 * Get the 3D stack at timepoint index t, extended to infinity and interpolated.
diff --git a/src/main/java/bdv/viewer/render/VisibilityUtils.java b/src/main/java/bdv/viewer/render/VisibilityUtils.java
index ee222a2b790e6457bad650dffaa83a807a998881..3568be69b86bf756eb55950a7c5e73f17eebc503 100644
--- a/src/main/java/bdv/viewer/render/VisibilityUtils.java
+++ b/src/main/java/bdv/viewer/render/VisibilityUtils.java
@@ -83,6 +83,12 @@ class VisibilityUtils
 
 		for ( final SourceAndConverter< ? > source : sources )
 		{
+			if( !source.getSpimSource().doBoundingBoxCulling() )
+			{
+				result.add( source );
+				continue;
+			}
+
 			final Source< ? > spimSource = source.getSpimSource();
 			final int level = MipmapTransforms.getBestMipMapLevel( screenTransform, spimSource, t );
 			spimSource.getSourceTransform( t, level, sourceToScreen );