diff --git a/manimlib/camera/camera.py b/manimlib/camera/camera.py index fb6a84e9..9d2be342 100644 --- a/manimlib/camera/camera.py +++ b/manimlib/camera/camera.py @@ -250,6 +250,12 @@ class Camera(object): else: self.ctx.disable(moderngl.DEPTH_TEST) + def set_ctx_clip_distance(self, enable: bool = True) -> None: + if enable: + gl.glEnable(gl.GL_CLIP_DISTANCE0) + else: + gl.glDisable(gl.GL_CLIP_DISTANCE0) + def init_light_source(self) -> None: self.light_source = Point(self.light_source_position) @@ -377,6 +383,7 @@ class Camera(object): shader_program = render_group["prog"] self.set_shader_uniforms(shader_program, shader_wrapper) self.set_ctx_depth_test(shader_wrapper.depth_test) + self.set_ctx_clip_distance(shader_wrapper.use_clip_plane) render_group["vao"].render(int(shader_wrapper.render_primitive)) if render_group["single_use"]: self.release_render_group(render_group) diff --git a/manimlib/mobject/types/surface.py b/manimlib/mobject/types/surface.py index ea3dabec..08df19bd 100644 --- a/manimlib/mobject/types/surface.py +++ b/manimlib/mobject/types/surface.py @@ -66,6 +66,10 @@ class Surface(Mobject): ) self.compute_triangle_indices() + def init_uniforms(self): + super().init_uniforms() + self.uniforms["clip_plane"] = np.zeros(4) + def uv_func(self, u: float, v: float) -> tuple[float, float, float]: # To be implemented in subclasses return (u, v, 0.0) @@ -207,6 +211,23 @@ class Surface(Mobject): surface.sort_faces_back_to_front(vect) self.add_updater(updater) + def set_clip_plane( + self, + vect: Vect3 | None = None, + threshold: float | None = None + ): + if vect is not None: + self.uniforms["clip_plane"][:3] = vect + if threshold is not None: + self.uniforms["clip_plane"][3] = threshold + self.shader_wrapper.use_clip_plane = True + return self + + def deactivate_clip_plane(self): + self.uniforms["clip_plane"][:] = 0 + self.shader_wrapper.use_clip_plane = False + return self + # For shaders def get_shader_data(self) -> np.ndarray: s_points, du_points, dv_points = self.get_surface_points_and_nudged_points() diff --git a/manimlib/shader_wrapper.py b/manimlib/shader_wrapper.py index 8728833a..7353404b 100644 --- a/manimlib/shader_wrapper.py +++ b/manimlib/shader_wrapper.py @@ -35,6 +35,7 @@ class ShaderWrapper(object): uniforms: dict[str, float] | None = None, # A dictionary mapping names of uniform variables texture_paths: dict[str, str] | None = None, # A dictionary mapping names to filepaths for textures. depth_test: bool = False, + use_clip_plane: bool = False, render_primitive: int = moderngl.TRIANGLE_STRIP, ): self.vert_data = vert_data @@ -44,6 +45,7 @@ class ShaderWrapper(object): self.uniforms = uniforms or dict() self.texture_paths = texture_paths or dict() self.depth_test = depth_test + self.use_clip_plane = use_clip_plane self.render_primitive = str(render_primitive) self.init_program_code() self.refresh_id() diff --git a/manimlib/shaders/surface/vert.glsl b/manimlib/shaders/surface/vert.glsl index 9b61614e..9be9a92c 100644 --- a/manimlib/shaders/surface/vert.glsl +++ b/manimlib/shaders/surface/vert.glsl @@ -7,6 +7,7 @@ uniform vec3 camera_position; uniform float reflectiveness; uniform float gloss; uniform float shadow; +uniform vec4 clip_plane; in vec3 point; in vec3 du_point; @@ -28,6 +29,10 @@ void main(){ v_color = color; gl_Position = get_gl_Position(xyz_coords); + if(clip_plane.xyz != vec3(0.0, 0.0, 0.0)){ + gl_ClipDistance[0] = dot(vec4(point, 1.0), clip_plane); + } + v_color = finalize_color( color, xyz_coords,