# How to Configure and Control the Manim Camera System and Camera Frame for Rendering

> Configure Manim camera for rendering. Control field-of-view, orientation, and motion using Camera and CameraFrame classes. Learn essential rendering techniques now.

- Repository: [Grant Sanderson/manim](https://github.com/3b1b/manim)
- Tags: how-to-guide
- Published: 2026-02-28

---

**Manim separates rendering context management into the `Camera` class and geometric viewport control into the `CameraFrame` class, allowing you to configure field-of-view, orientation, and motion via methods like `set_field_of_view()`, `reorient()`, and `add_ambient_rotation()`.**

To configure and control the Manim camera system and camera frame for rendering, you must understand the relationship between the `Camera` class in [`manimlib/camera/camera.py`](https://github.com/3b1b/manim/blob/main/manimlib/camera/camera.py) and the `CameraFrame` class in [`manimlib/camera/camera_frame.py`](https://github.com/3b1b/manim/blob/main/manimlib/camera/camera_frame.py). These two components manage the ModernGL rendering context and the 3D geometric viewport respectively, providing fine-grained control over perspective, orientation, and animation.

## Understanding the Manim Camera Architecture

Manim’s rendering pipeline delegates responsibilities to two cooperating classes that handle distinct aspects of the visualization process.

### The Camera Class

The `Camera` class, defined at `manimlib/camera/camera.py#L25`, holds the ModernGL context, framebuffer objects, and background settings. It delegates all view-related transforms to its internal `CameraFrame` instance. Key methods include `__init__`, `init_frame`, `refresh_uniforms`, `get_location`, and `resize_frame_shape`.

During each render pass, the camera updates shader uniforms—such as the view matrix, pixel size, and camera position—via `Camera.refresh_uniforms` (lines 38‑46). These uniforms are essential for the shaders to project 3D scene geometry onto the 2D framebuffer.

### The CameraFrame Class

The `CameraFrame` class, located at `manimlib/camera/camera_frame.py#L23`, is a subclass of `Mobject` that represents the virtual “screen” in 3‑D space. It stores orientation, field-of-view, focal distance, and computes view matrices used by shaders. Important methods include `reorient`, `set_euler_axes`, `rotate`, `set_focal_distance`, `set_field_of_view`, `increment_theta`, `add_ambient_rotation`, `get_view_matrix`, and `to_fixed_frame_point`.

The view matrix itself is assembled in `CameraFrame.get_view_matrix` (lines 100‑116) as a 4×4 affine transform based on the current orientation, scale, and center.

## Configuring Camera Parameters for Rendering

When a `Scene` or `ThreeDScene` is instantiated, it builds a `Camera` object (see `Scene.__init__` lines 107‑113). The camera receives a *frame configuration* (`frame_config`) forwarded to `CameraFrame.__init__` (line 31), allowing immediate customization of the viewport.

### Setting Field of View and Focal Distance

To achieve specific photographic effects, control the camera’s optical properties directly.

**`set_field_of_view(fov)`** stores the vertical FOV in `uniforms["fovy"]` (lines 22‑24). The view matrix automatically uses this value on the next `refresh_uniforms` call.

**`set_focal_distance(dist)`** computes a new `fovy` from the distance and current frame height (lines 16‑19), effectively zooming the camera without explicit angle calculations.

```python
from manimlib import *

class TelephotoEffect(Scene):
    def construct(self):
        # Narrow the field of view for a telephoto effect

        self.camera.frame.set_field_of_view(30 * DEG)

        # Alternatively, set a specific focal distance (in scene units)

        self.camera.frame.set_focal_distance(8.0)

        # Add a simple object to see the effect

        sphere = Sphere(radius=1, color=BLUE).shift(OUT * 5)
        self.add(sphere)

```

### Adjusting Camera Orientation with Euler Angles

The scene sets a default Euler orientation (`default_frame_orientation = (0, 0)`) and calls `self.frame.reorient(*self.default_frame_orientation)` (lines 13‑14). You can override this at any time.

**`reorient(theta, phi, gamma, center, height)`** is a shortcut for `set_euler_angles` plus optional `move_to` and `set_height`. Angles are interpreted in degrees (`DEG` unit) and passed to `set_euler_angles`, which builds a `scipy.spatial.transform.Rotation` object (lines 172‑185).

**`rotate(angle, axis)`** updates the internal quaternion via `Rotation.from_rotvec` and stores it in `uniforms["orientation"]` (lines 26‑29).

```python
from manimlib import *

class RotatingCamera(Scene):
    def construct(self):
        # Look down the z‑axis, then rotate 45° around x, 30° around y

        self.camera.frame.reorient(theta=45, phi=30)

        # Animate a smooth turn around the scene

        self.play(
            self.camera.frame.animate.increment_theta(PI/2, units=RADIANS),
            run_time=3,
        )

```

### Enabling Ambient Rotation

For continuous, automatic camera motion without explicit animation keys, use ambient rotation.

**`add_ambient_rotation(speed)`** registers an updater that increments `theta` each frame via `increment_theta` (lines 12‑14). The speed is typically specified in degrees per second.

```python
from manimlib import *

class SpinningView(ThreeDScene):
    def construct(self):
        self.camera.frame.add_ambient_rotation(0.2 * DEG)  # 0.2° per second

        cube = Cube(side_length=2, fill_opacity=0.6).rotate(PI/4, axis=UP)
        self.add(cube)

        # Let the ambient rotation run while we animate the cube

        self.play(cube.animate.rotate(2 * PI, axis=OUT), run_time=6)

```

## Controlling the Camera Frame in 3D Scenes

Beyond static configuration, the `CameraFrame` can be manipulated dynamically as a `Mobject`, allowing for complex camera animations and interactive control.

### Shifting and Scaling the Frame

Since `CameraFrame` inherits from `Mobject`, it supports standard geometric operations.

- **`shift(vector)`** moves the frame’s center in 3D space.
- **`scale(factor, about_point=...)`** rescales the frame’s width and height, effectively zooming or widening the view.

These changes propagate to the view matrix on the next render pass via `refresh_uniforms`.

### Switching Floor Planes

The orientation of the ground plane affects how Euler angles are interpreted.

**`Scene.set_floor_plane("xy")`** forces the frame to use the `"zxz"` Euler axes, while `"xz"` selects `"zxy"` (lines 27‑33 in [`manimlib/scene/scene.py`](https://github.com/3b1b/manim/blob/main/manimlib/scene/scene.py)). This is useful when you want the camera to orbit around different axes or when importing models with specific up-vectors.

```python
from manimlib import *

class FloorPlaneDemo(Scene):
    def construct(self):
        # Default is xy (uses "zxz" Euler axes)

        self.set_floor_plane("xy")
        self.camera.frame.shift(OUT * 3)

        # Switch to xz floor (uses "zxy" Euler axes)

        self.wait(2)
        self.set_floor_plane("xz")
        self.camera.frame.shift(UP * 2)

```

### Mouse and Keyboard Interaction

Interactive scenes can respond to user input by manipulating the camera frame directly.

- **Reset key**: Pressing the reset key (`manim_config.key_bindings.reset`) executes `self.play(self.camera.frame.animate.to_default_state())`, restoring the original orientation and frame shape (lines 44‑45).
- **Mouse motion**: In `Scene.on_mouse_motion`, mouse deltas are transformed into the frame’s coordinate system via `frame.to_fixed_frame_point` and applied to `increment_theta`/`increment_phi` when 3‑D pan is active, enabling live rotation control (lines 51‑56).

## Summary

- **Manim’s camera system** splits responsibilities between the `Camera` class ([`manimlib/camera/camera.py`](https://github.com/3b1b/manim/blob/main/manimlib/camera/camera.py)), which manages the ModernGL context and framebuffers, and the `CameraFrame` class ([`manimlib/camera/camera_frame.py`](https://github.com/3b1b/manim/blob/main/manimlib/camera/camera_frame.py)), which handles the geometric viewport.
- **Configure rendering parameters** by calling `set_field_of_view()`, `set_focal_distance()`, or passing `frame_config` during scene initialization to control perspective and zoom.
- **Control orientation** using `reorient()` with Euler angles, `rotate()` for quaternion-based rotation, or `add_ambient_rotation()` for continuous automatic spinning.
- **Manipulate the frame dynamically** via `shift()`, `scale()`, and floor plane switching (`set_floor_plane()`) to adapt the camera to different scene layouts and interaction modes.

## Frequently Asked Questions

### How do I set a custom field of view in Manim?

Call `self.camera.frame.set_field_of_view(fov)` where `fov` is an angle in degrees (e.g., `30 * DEG`). This value is stored in the shader uniforms at `uniforms["fovy"]` and takes effect on the next frame render. For a zoom effect without calculating angles, use `set_focal_distance(distance)` instead, which computes the appropriate FOV based on the frame height.

### What is the difference between Camera and CameraFrame?

The **`Camera`** class ([`manimlib/camera/camera.py`](https://github.com/3b1b/manim/blob/main/manimlib/camera/camera.py)) owns the ModernGL context, framebuffer objects, and background color. It handles low-level tasks like `refresh_uniforms()` and resizing the pixel buffer. The **`CameraFrame`** class ([`manimlib/camera/camera_frame.py`](https://github.com/3b1b/manim/blob/main/manimlib/camera/camera_frame.py)) is a subclass of `Mobject` that represents the virtual screen in 3D space. It stores orientation quaternions, Euler angles, and view matrices, and provides methods like `reorient()` and `get_view_matrix()` that the `Camera` calls during rendering.

### How can I rotate the camera continuously during an animation?

Use `self.camera.frame.add_ambient_rotation(speed)` where `speed` is the rotation rate in degrees per second (e.g., `0.2 * DEG`). This registers an updater that increments the camera’s `theta` angle each frame. To stop the rotation, you would remove the updater or set the speed to zero. For scripted rotation instead of continuous motion, use `self.play(self.camera.frame.animate.increment_theta(angle))`.

### How do I change the floor plane orientation in Manim?

Call `self.set_floor_plane(plane)` where `plane` is either `"xy"` or `"xz"`. This method, defined in [`manimlib/scene/scene.py`](https://github.com/3b1b/manim/blob/main/manimlib/scene/scene.py), changes the Euler axis convention used by the camera frame: `"xy"` uses `"zxz"` axes (default), while `"xz"` uses `"zxy"` axes. This is useful when you want the camera to orbit around a different axis or when aligning the view with models that have a specific "up" vector. After switching, you may need to adjust the camera position using `self.camera.frame.shift()`.