From f3ebbceb3a82e9c9d5dbc809496f9381e4941a64 Mon Sep 17 00:00:00 2001 From: Colin Rubow Date: Sat, 20 Jun 2026 18:34:38 -0600 Subject: [PATCH 1/3] transparent mobjects with depth testing should not write to the depth mask --- manim/renderer/opengl_renderer.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/manim/renderer/opengl_renderer.py b/manim/renderer/opengl_renderer.py index 2dbde6f948..863f052624 100644 --- a/manim/renderer/opengl_renderer.py +++ b/manim/renderer/opengl_renderer.py @@ -352,11 +352,17 @@ def render_vmobject(self, mob: OpenGLVMobject) -> None: gl.ONE, ) - def enable_depth(sub): + def enable_depth(sub) -> bool: if sub.depth_test: self.ctx.enable(gl.DEPTH_TEST) + if (sub.has_fill() and sub.get_fill_opacity() != 1.0) or ( + sub.has_stroke() and sub.get_stroke_opacity() != 1.0 + ): + self.render_target_fbo.depth_mask = False + return True else: self.ctx.disable(gl.DEPTH_TEST) + return False for sub in mob.family_members_with_points(): # TODO: review this renderer data optimization attempt @@ -382,7 +388,7 @@ def enable_depth(sub): for counter, sub in enumerate(family): if not isinstance(sub.renderer_data, GLRenderData): return - enable_depth(sub) + reenable_depth_mask = enable_depth(sub) uniforms = {} uniforms["index"] = (counter + 1) / num_mobs / 2 uniforms["disable_stencil"] = float(True) @@ -399,11 +405,13 @@ def enable_depth(sub): GLVMobjectManager.get_stroke_shader_data(sub), np.array(range(len(sub.points))), ) + if reenable_depth_mask: + self.render_target_fbo.depth_mask = True for counter, sub in enumerate(family): if not isinstance(sub.renderer_data, GLRenderData): return - enable_depth(sub) + reenable_depth_mask = enable_depth(sub) uniforms = {} # uniforms['z_shift'] = counter/9 uniforms["index"] = (counter + 1) / num_mobs @@ -420,11 +428,13 @@ def enable_depth(sub): GLVMobjectManager.get_fill_shader_data(sub), sub.renderer_data.vert_indices, ) + if reenable_depth_mask: + self.render_target_fbo.depth_mask = True for counter, sub in enumerate(family): if not isinstance(sub.renderer_data, GLRenderData): return - enable_depth(sub) + reenable_depth_mask = enable_depth(sub) uniforms = {} uniforms["index"] = (counter + 1) / num_mobs uniforms["disable_stencil"] = float(False) @@ -441,6 +451,8 @@ def enable_depth(sub): GLVMobjectManager.get_stroke_shader_data(sub), np.array(range(len(sub.points))), ) + if reenable_depth_mask: + self.render_target_fbo.depth_mask = True def get_pixels(self) -> PixelArray: raw = self.output_fbo.read(components=4, dtype="f1", clamp=True) # RGBA, floats From 0be4e534a7b95ad4e926483d540c9ceba6246703 Mon Sep 17 00:00:00 2001 From: Colin Rubow Date: Sat, 20 Jun 2026 19:32:51 -0600 Subject: [PATCH 2/3] sorting mobjects --- manim/renderer/renderer.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/manim/renderer/renderer.py b/manim/renderer/renderer.py index e8e30f14af..445170ea14 100644 --- a/manim/renderer/renderer.py +++ b/manim/renderer/renderer.py @@ -2,6 +2,7 @@ from abc import ABC, abstractmethod from typing import TYPE_CHECKING, Protocol, runtime_checkable +import numpy as np from manim._config import logger from manim.mobject.mobject import InvisibleMobject @@ -35,8 +36,23 @@ def __init__(self) -> None: def render(self, state: SceneState) -> None: self.pre_render(state.camera) + + # seperate depth testing mobjects and otherwise + depth_testing: list[OpenGLVMobject] = [] + non_depth_testing: list[OpenGLVMobject] = [] for mob in state.mobjects: + if mob.depth_test: + depth_testing.append(mob) + else: + non_depth_testing.append(mob) + # sort depth testing mobjects according to center distance from camera + depth_testing.sort(key=lambda m: np.linalg.norm(m.get_center() - state.camera.get_implied_camera_location()), reverse=True) + # render depth testing mobs followed by otherwise + for mob in depth_testing: + self.render_mobject(mob) + for mob in non_depth_testing: self.render_mobject(mob) + self.post_render() def render_mobject(self, mob: OpenGLMobject) -> None: From 9774c4a702231e62fba00dfbf61980f579580707 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 21 Jun 2026 02:04:35 +0000 Subject: [PATCH 3/3] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- manim/renderer/renderer.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/manim/renderer/renderer.py b/manim/renderer/renderer.py index 445170ea14..8580418c0e 100644 --- a/manim/renderer/renderer.py +++ b/manim/renderer/renderer.py @@ -2,6 +2,7 @@ from abc import ABC, abstractmethod from typing import TYPE_CHECKING, Protocol, runtime_checkable + import numpy as np from manim._config import logger @@ -46,7 +47,12 @@ def render(self, state: SceneState) -> None: else: non_depth_testing.append(mob) # sort depth testing mobjects according to center distance from camera - depth_testing.sort(key=lambda m: np.linalg.norm(m.get_center() - state.camera.get_implied_camera_location()), reverse=True) + depth_testing.sort( + key=lambda m: np.linalg.norm( + m.get_center() - state.camera.get_implied_camera_location() + ), + reverse=True, + ) # render depth testing mobs followed by otherwise for mob in depth_testing: self.render_mobject(mob)