Cameras define the viewpoint from which your scene is rendered. Babylon.js offers various camera types to suit different application needs, from traditional gaming perspectives to VR experiences.

All cameras share certain core properties:

// Core camera properties
camera.position = new BABYLON.Vector3(0, 5, -10); // Position in 3D space
camera.target = new BABYLON.Vector3(0, 0, 0);    // Look-at target
camera.fov = 0.8;                               // Field of view in radians
camera.minZ = 0.1;                              // Near clipping plane
camera.maxZ = 1000;                             // Far clipping plane

Field of View (FOV) controls the camera's viewing angle, measured in radians. A wider FOV (higher value) creates a fisheye-like effect showing more of the scene but with more distortion. A narrower FOV (lower value) creates a telescopic effect with less distortion but shows less of the scene. Typical values range from 0.5 to 1.2 radians (approximately 30° to 70°).

Near and Far Clipping Planes define the viewing frustum's boundaries:

  • The Near Clipping Plane (minZ) is the minimum distance from the camera at which objects become visible. Objects closer than this distance won't be rendered. It should be set as large as possible (typically 0.1-1.0) while still including all necessary objects to avoid precision issues.
  • The Far Clipping Plane (maxZ) is the maximum distance from the camera at which objects are still visible. Objects beyond this distance won't be rendered. Setting this value appropriately (typically 100-2000) can improve performance and depth buffer precision.

The ArcRotateCamera is one of the most versatile and widely used cameras in Babylon.js. It orbits around a target point, making it ideal for object viewing, 3D modeling applications, and orbital gameplay.

// Create ArcRotateCamera: name, alpha, beta, radius, target, scene
const camera = new BABYLON.ArcRotateCamera("camera", 
    Math.PI / 2, // Alpha (horizontal rotation)
    Math.PI / 4, // Beta (vertical angle)
    10,          // Radius (distance from target)
    new BABYLON.Vector3(0, 0, 0), // Target
    scene);

// Enable camera controls
camera.attachControl(canvas, true);

// Configure mouse/touch behavior
camera.inputs.attached.mousewheel.detachControl(canvas); // Disable zoom with mouse wheel
camera.inputs.addMouseWheel();                           // Re-add with custom settings
camera.wheelPrecision = 50;                              // Lower value = faster zoom

// Constrain camera movement
camera.lowerRadiusLimit = 5;   // Minimum zoom distance
camera.upperRadiusLimit = 20;  // Maximum zoom distance
camera.lowerBetaLimit = 0.1;   // Limit vertical rotation (lower)
camera.upperBetaLimit = Math.PI / 2.2; // Limit vertical rotation (upper)

// Camera inertia (smooth movement)
camera.inertia = 0.7; // Higher = more inertia

// Adjust rotation speed
camera.angularSensibilityX = 500; // Horizontal rotation sensitivity
camera.angularSensibilityY = 500; // Vertical rotation sensitivity

Animate the camera for cinematic effects or guided tours:

// Animate the camera orbit
let alpha = 0;
scene.onBeforeRenderObservable.add(() => {
    alpha += 0.01;
    camera.alpha = alpha;
});

// Or use the animation system
const rotationAnimation = new BABYLON.Animation(
    "cameraRotation",
    "alpha",
    30, // frames per second
    BABYLON.Animation.ANIMATIONTYPE_FLOAT,
    BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE
);

const keyFrames = [];
keyFrames.push({ frame: 0, value: 0 });
keyFrames.push({ frame: 120, value: Math.PI * 2 });
rotationAnimation.setKeys(keyFrames);

camera.animations = [rotationAnimation];
scene.beginAnimation(camera, 0, 120, true); // true = loop
// Auto-rotation when idle
camera.useAutoRotationBehavior = true;
camera.autoRotationBehavior.idleRotationSpeed = 0.2;
camera.autoRotationBehavior.idleRotationWaitTime = 3000; // ms

// Bouncing behavior when hitting limits
camera.useBouncingBehavior = true;
camera.bouncingBehavior.transitionDuration = 150; // ms

The FreeCamera (or Universal Camera) provides first-person movement, ideal for exploration and FPS-style games:

// Create FreeCamera: name, position, scene
const camera = new BABYLON.FreeCamera("camera", 
    new BABYLON.Vector3(0, 2, -10), // Position
    scene);

// Set camera direction
camera.setTarget(BABYLON.Vector3.Zero());

// Enable controls
camera.attachControl(canvas, true);

// Configure keyboard controls
camera.keysUp = [87];    // W key
camera.keysDown = [83];  // S key
camera.keysLeft = [65];  // A key
camera.keysRight = [68]; // D key

// Adjust movement speed
camera.speed = 0.5;
camera.angularSensibility = 1000; // Mouse look sensitivity

// Add WASD movement for FPS style controls
camera.inputs.addKeyboard();

The FollowCamera tracks a target object while maintaining a specified offset, perfect for third-person games:

// Create target object
const player = BABYLON.MeshBuilder.CreateBox("player", {size: 1}, scene);

// Create FollowCamera
const camera = new BABYLON.FollowCamera("followCam", 
    new BABYLON.Vector3(0, 10, -10), // Initial position
    scene);

// Configure follow behavior
camera.lockedTarget = player;      // Target to follow
camera.radius = 10;                // Distance from target
camera.heightOffset = 5;           // Height above target
camera.rotationOffset = 180;       // Rotation around target in degrees
camera.cameraAcceleration = 0.05;  // Camera acceleration
camera.maxCameraSpeed = 10;        // Maximum speed of camera

// Animate the player to see the camera follow
scene.onBeforeRenderObservable.add(() => {
    player.position.x = Math.sin(Date.now() / 1000) * 5;
});

Babylon.js 7 includes enhanced support for Virtual Reality and Augmented Reality through the WebXR standard:

// Create default experience helper
const xrHelper = await scene.createDefaultXRExperienceAsync({
    floorMeshes: [ground] // Optional meshes to use as floor reference
});

// Check if XR is available
if (xrHelper.isSupported) {
    // Create button for VR entry
    const vrButton = document.createElement("button");
    vrButton.textContent = "Enter VR";
    vrButton.style.position = "absolute";
    vrButton.style.bottom = "10px";
    vrButton.style.right = "10px";
    document.body.appendChild(vrButton);
    
    vrButton.addEventListener("click", async () => {
        await xrHelper.enterXRAsync("immersive-vr", "local-floor");
    });
}

Customize camera controls for different devices and user preferences:

// Remove default inputs
camera.inputs.clear();

// Add only the inputs you need
camera.inputs.add(new BABYLON.ArcRotateCameraKeyboardMoveInput());
camera.inputs.add(new BABYLON.ArcRotateCameraMouseWheelInput());
camera.inputs.add(new BABYLON.ArcRotateCameraPointersInput());

// Create custom camera controls
class CustomCameraInput implements BABYLON.ICameraInput<BABYLON.ArcRotateCamera> {
    camera: BABYLON.ArcRotateCamera;
    
    getClassName(): string {
        return "CustomCameraInput";
    }
    
    getSimpleName(): string {
        return "custom";
    }
    
    attachControl(element: HTMLElement, noPreventDefault?: boolean): void {
        // Custom control logic here
    }
    
    detachControl(element: HTMLElement): void {
        // Clean up event listeners
    }
}

// Add custom input
camera.inputs.add(new CustomCameraInput());

Babylon.js 7 includes enhanced camera features for better control and performance, making cameras more versatile across different device capabilities.