diff --git a/manimlib/camera/camera.py b/manimlib/camera/camera.py index 64d7843d..191341af 100644 --- a/manimlib/camera/camera.py +++ b/manimlib/camera/camera.py @@ -297,7 +297,7 @@ class Camera(object): self.fill_prog['Texture'].value = tid self.n_textures += 1 verts = np.array([[0, 0], [0, 1], [1, 0], [1, 1]]) - self.fill_vao = self.ctx.simple_vertex_array( + self.fill_texture_vao = self.ctx.simple_vertex_array( self.fill_prog, self.ctx.buffer(verts.astype('f4').tobytes()), 'texcoord', @@ -446,33 +446,39 @@ class Camera(object): def render(self, render_group: dict[str, Any]) -> None: shader_wrapper = render_group["shader_wrapper"] shader_program = render_group["prog"] + primitive = int(shader_wrapper.render_primitive) self.set_shader_uniforms(shader_program, shader_wrapper) self.set_ctx_depth_test(shader_wrapper.depth_test) self.set_ctx_clip_plane(shader_wrapper.use_clip_plane) - # TODO - if shader_wrapper.render_to_texture: - self.fill_fbo.clear(0.0, 0.0, 0.0, 0.0) - self.fill_fbo.use() - self.ctx.enable(moderngl.BLEND) - self.ctx.blend_func = moderngl.ONE, moderngl.ONE - self.ctx.blend_equation = moderngl.FUNC_SUBTRACT - render_group["vao"].render( - int(shader_wrapper.render_primitive), - instances=2, - ) - self.ctx.blend_func = moderngl.DEFAULT_BLENDING - self.ctx.blend_equation = moderngl.FUNC_ADD - self.fbo.use() - self.fill_texture.use(0) - self.fill_prog['Texture'].value = 0 - self.fill_vao.render(moderngl.TRIANGLE_STRIP) + if shader_wrapper.is_fill: + self.render_fill(render_group["vao"], primitive) else: - render_group["vao"].render(int(shader_wrapper.render_primitive)) + render_group["vao"].render(primitive) if render_group["single_use"]: self.release_render_group(render_group) + def render_fill(self, vao, render_primitive: int): + """ + VMobject fill is handled in a special way, where emited triangles + must be blended with moderngl.FUNC_SUBTRACT so as to effectively compute + a winding number around each pixel. This is rendered to a separate texture, + then that texture is overlayed onto the current fbo + """ + self.fill_fbo.clear(0.0, 0.0, 0.0, 0.0) + self.fill_fbo.use() + self.ctx.enable(moderngl.BLEND) + self.ctx.blend_func = moderngl.ONE, moderngl.ONE + self.ctx.blend_equation = moderngl.FUNC_SUBTRACT + vao.render(render_primitive, instances=2) + self.ctx.blend_func = moderngl.DEFAULT_BLENDING + self.ctx.blend_equation = moderngl.FUNC_ADD + self.fbo.use() + self.fill_texture.use(0) + self.fill_prog['Texture'].value = 0 + self.fill_texture_vao.render(moderngl.TRIANGLE_STRIP) + def get_render_group_list(self, mobject: Mobject) -> Iterable[dict[str, Any]]: if mobject.is_changing(): return self.generate_render_group_list(mobject) diff --git a/manimlib/mobject/types/vectorized_mobject.py b/manimlib/mobject/types/vectorized_mobject.py index d2f31ed8..7ad8cd26 100644 --- a/manimlib/mobject/types/vectorized_mobject.py +++ b/manimlib/mobject/types/vectorized_mobject.py @@ -1154,7 +1154,7 @@ class VMobject(Mobject): uniforms=self.uniforms, shader_folder=self.fill_shader_folder, render_primitive=self.fill_render_primitive, - render_to_texture=True, + is_fill=True, ) self.stroke_shader_wrapper = ShaderWrapper( vert_data=stroke_data, diff --git a/manimlib/shader_wrapper.py b/manimlib/shader_wrapper.py index da11836b..8401349d 100644 --- a/manimlib/shader_wrapper.py +++ b/manimlib/shader_wrapper.py @@ -34,7 +34,7 @@ class ShaderWrapper(object): depth_test: bool = False, use_clip_plane: bool = False, render_primitive: int = moderngl.TRIANGLE_STRIP, - render_to_texture: bool = False, + is_fill: bool = False, ): self.vert_data = vert_data self.vert_indices = vert_indices @@ -45,7 +45,7 @@ class ShaderWrapper(object): self.depth_test = depth_test self.use_clip_plane = use_clip_plane self.render_primitive = str(render_primitive) - self.render_to_texture = render_to_texture + self.is_fill = is_fill self.init_program_code() self.refresh_id() diff --git a/manimlib/shaders/quadratic_bezier_fill/geom.glsl b/manimlib/shaders/quadratic_bezier_fill/geom.glsl index 25516623..bb808136 100644 --- a/manimlib/shaders/quadratic_bezier_fill/geom.glsl +++ b/manimlib/shaders/quadratic_bezier_fill/geom.glsl @@ -47,19 +47,22 @@ void main(){ // Emit main triangle fill_all = float(true); uv_coords = vec2(0.0); - emit_vertex_wrapper(verts[0], v_color[0], unit_normal); emit_vertex_wrapper(v_base_point[0], v_color[0], unit_normal); + emit_vertex_wrapper(verts[0], v_color[0], unit_normal); emit_vertex_wrapper(verts[2], v_color[2], unit_normal); }else{ // Emit edge triangle fill_all = float(false); - uv_coords = vec2(0.0, 0.0); - emit_vertex_wrapper(verts[0], v_color[0], unit_normal); - uv_coords = vec2(0.5, 0); - emit_vertex_wrapper(verts[1], v_color[1], unit_normal); - uv_coords = vec2(1.0, 1.0); - emit_vertex_wrapper(verts[2], v_color[2], unit_normal); - EndPrimitive(); + vec2 uv_coords_arr[3] = vec2[3]( + vec2(0.0, 0.0), + vec2(0.5, 0), + vec2(1.0, 1.0) + ); + for(int i = 0; i < 3; i ++){ + uv_coords = uv_coords_arr[i]; + emit_vertex_wrapper(verts[i], v_color[i], unit_normal); + } } + EndPrimitive(); }