Skip to content

Cairo does not respect order of mobjects when rendering a 3d scene #4336

@agryman

Description

@agryman

Description of bug / unexpected behavior

I created a 3d scene that contained some Square and Line3D mobjects.
I sorted the mobjects into the correct z-order, but the Cairo renderer always seemed to draw the Square on top of the Line3D mobjects. I then switched to using the OpenGL renderer it produced the correct result.

Is this a known limitation of the Cairo renderer? I will workaround this issue by using the OpenGL rendered for 3d scenes.
However, I thought it was worth reporting this issue.

Expected behavior

I expected the Cairo rendered to drawn the mobjects in the order that I added them to the scene.
Instead, it seems to always draw the Square on top of the Line3D mobjects.
The OpenGL rendered produced the expected result.

How to reproduce the issue

Run the code twice. Once with OPENGL_CONFIG and again with CAIRO_CONFIG.
Note the different results.

Code for reproducing the problem
"""
This module illustrates drawing lines over a square in a 3D scene using Manim.
"""
import numpy as np
from manim import (ThreeDScene, ThreeDAxes, Line3D, Square, config, tempconfig, RendererType,
                   LEFT, RIGHT, UP, OUT, WHITE, RED, BLUE, Text, UL)

class Line3DExample(ThreeDScene):
    def construct(self):

        renderer_str = f"renderer: {config.renderer.value}"
        renderer_text = Text(renderer_str)
        self.add_fixed_in_frame_mobjects(renderer_text)
        renderer_text.to_corner(UL)
        
        axes = ThreeDAxes()
        x_label = axes.get_x_axis_label('x')
        y_label = axes.get_y_axis_label('y')
        z_label = axes.get_z_axis_label('z')
        self.add(axes, x_label, y_label, z_label)
        
        # the square is in the plane z = 0
        square = Square(side_length=3.0, color=RED, fill_opacity=1.0, stroke_color=BLUE, stroke_width=10)

        # the 5 lines are in the planes z = -2, -1, 0, 1, 2
        lines = [Line3D(2.0 * LEFT + t * (UP + OUT), 2.0 * RIGHT + t * (UP + OUT), color=WHITE) 
                 for t in np.linspace(-2.0, 2.0, 5)]

        # square and lines are added in the correct order
        self.add(lines[0], lines[1], lines[2], square, lines[3], lines[4])


# opengl renders the scene correctly
# lines[3] is drawn over the square
OPENGL_CONFIG = {
    "renderer": RendererType.OPENGL
}

# cairo renders the scene incorrectly
# lines[3] is drawn under the square
# this is a bug in cairo renderer
CAIRO_CONFIG = {
    "renderer": RendererType.CAIRO
}

# For running the scene directly
if __name__ == "__main__":
    with tempconfig(OPENGL_CONFIG):
        scene = Line3DExample()
        scene.render(preview=True)

Additional media files

Images/GIFs Image Image

Logs

Terminal output
PASTE HERE OR PROVIDE LINK TO https://pastebin.com/ OR SIMILAR

System specifications

System Details
  • OS: macOS 15.5 (24F74) (Sequoia)
  • RAM: Mac Studio 2023 Apple M2 Max 96 GB
  • Python version: Python 3.13.5
  • Installed modules (provide output from pip list):
Package                   Version        
------------------------- -------------- 
anyio                     4.9.0
appnope                   0.1.4
argon2-cffi               25.1.0
argon2-cffi-bindings      21.2.0
arrow                     1.3.0
asttokens                 3.0.0
async-lru                 2.0.5
attrs                     25.3.0
audioop-lts               0.2.1
av                        13.1.0
babel                     2.17.0
beautifulsoup4            4.13.4
bleach                    6.2.0
certifi                   2025.7.14
cffi                      1.17.1
charset-normalizer        3.4.2
click                     8.2.1
cloup                     3.0.7
comm                      0.2.2
Cython                    3.1.2
debugpy                   1.8.14
decorator                 5.2.1
defusedxml                0.7.1
executing                 2.2.0
fastjsonschema            2.21.1
fqdn                      1.5.1
glcontext                 3.0.0
h11                       0.16.0
httpcore                  1.0.9
httpx                     0.28.1
idna                      3.10
ipykernel                 6.29.5
ipython                   9.4.0
ipython_pygments_lexers   1.1.1
isoduration               20.11.0
isosurfaces               0.1.2
jedi                      0.19.2
Jinja2                    3.1.6
json5                     0.12.0
jsonpointer               3.0.0
jsonschema                4.24.0
jsonschema-specifications 2025.4.1
jupyter_client            8.6.3
jupyter_core              5.8.1
jupyter-events            0.12.0
jupyter-lsp               2.2.5
jupyter_server            2.16.0
jupyter_server_terminals  0.5.3
jupyterlab                4.4.4
jupyterlab_pygments       0.3.0
jupyterlab_server         2.27.3
manim                     0.19.0
ManimPango                0.6.0
mapbox_earcut             1.0.3
markdown-it-py            3.0.0
MarkupSafe                3.0.2
matplotlib-inline         0.1.7
mdurl                     0.1.2
mistune                   3.1.3
moderngl                  5.12.0
moderngl-window           3.1.1
nbclient                  0.10.2
nbconvert                 7.16.6
nbformat                  5.10.4
nest-asyncio              1.6.0
networkx                  3.5
notebook_shim             0.2.4
numpy                     2.3.1
overrides                 7.7.0
packaging                 25.0
pandocfilters             1.5.1
parso                     0.8.4
pexpect                   4.9.0
pillow                    11.3.0
pip                       25.1.1
platformdirs              4.3.8
prometheus_client         0.22.1
prompt_toolkit            3.0.51
psutil                    7.0.0
ptyprocess                0.7.0
pure_eval                 0.2.3
pycairo                   1.28.0
pycparser                 2.22
pydub                     0.25.1
pyglet                    2.1.6
pyglm                     2.8.2
Pygments                  2.19.2
pyobjc-core               11.1
pyobjc-framework-Cocoa    11.1
python-dateutil           2.9.0.post0
python-json-logger        3.3.0
PyYAML                    6.0.2
pyzmq                     27.0.0
referencing               0.36.2
requests                  2.32.4
rfc3339-validator         0.1.4
rfc3986-validator         0.1.1
rich                      14.0.0
rpds-py                   0.26.0
scipy                     1.16.0
screeninfo                0.8.1
Send2Trash                1.8.3
setuptools                80.9.0
six                       1.17.0
skia-pathops              0.8.0.post2
sniffio                   1.3.1
soupsieve                 2.7
srt                       3.5.3
stack-data                0.6.3
svgelements               1.9.6
terminado                 0.18.1
tinycss2                  1.4.0
tornado                   6.5.1
tqdm                      4.67.1
traitlets                 5.14.3
types-python-dateutil     2.9.0.20250708
typing_extensions         4.14.1
uri-template              1.3.0
urllib3                   2.5.0
watchdog                  6.0.0
wcwidth                   0.2.13
webcolors                 24.11.1
webencodings              0.5.1
websocket-client          1.8.0
LaTeX details
  • LaTeX distribution: TeXShop 5.53
  • Installed LaTeX packages:

too long, not relevant

Additional comments

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status

    🆕 New

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions