diff --git a/manimlib/mobject/coordinate_systems.py b/manimlib/mobject/coordinate_systems.py index b670d8ee..e7bee7d8 100644 --- a/manimlib/mobject/coordinate_systems.py +++ b/manimlib/mobject/coordinate_systems.py @@ -504,7 +504,6 @@ class ThreeDAxes(Axes): z_normal: Vect3 = DOWN, depth: float = 6.0, num_axis_pieces: int = 20, - gloss: float = 0.5, **kwargs ): Axes.__init__(self, x_range, y_range, **kwargs) diff --git a/manimlib/mobject/mobject.py b/manimlib/mobject/mobject.py index d80713f4..9fbefb35 100644 --- a/manimlib/mobject/mobject.py +++ b/manimlib/mobject/mobject.py @@ -48,7 +48,7 @@ from manimlib.utils.space_ops import rotation_matrix_transpose from typing import TYPE_CHECKING if TYPE_CHECKING: - from typing import Callable, Iterable, Sequence, Union, Tuple + from typing import Callable, Iterable, Union, Tuple import numpy.typing as npt from manimlib.typing import ManimColor, Vect3, Vect4, Vect3Array @@ -76,12 +76,7 @@ class Mobject(object): self, color: ManimColor = WHITE, opacity: float = 1.0, - # Larger reflectiveness makes things brighter when facing the light - reflectiveness: float = 0.0, - # Larger shadow makes faces opposite the light darker - shadow: float = 0.0, - # Makes parts bright where light gets reflected toward the camera - gloss: float = 0.0, + shading: Tuple[float, float, float] = (0.0, 0.0, 0.0), # For shaders texture_paths: dict[str, str] | None = None, # If true, the mobject will not get rotated according to camera position @@ -90,9 +85,7 @@ class Mobject(object): ): self.color = color self.opacity = opacity - self.reflectiveness = reflectiveness - self.shadow = shadow - self.gloss = gloss + self.shading = shading self.texture_paths = texture_paths self.is_fixed_in_frame = is_fixed_in_frame self.depth_test = depth_test @@ -138,9 +131,7 @@ class Mobject(object): def init_uniforms(self): self.uniforms: dict[str, float | np.ndarray] = { "is_fixed_in_frame": float(self.is_fixed_in_frame), - "gloss": self.gloss, - "shadow": self.shadow, - "reflectiveness": self.reflectiveness, + "shading": np.array(self.shading, dtype=float), } def init_colors(self): @@ -1333,28 +1324,46 @@ class Mobject(object): def fade(self, darkness: float = 0.5, recurse: bool = True): self.set_opacity(1.0 - darkness, recurse=recurse) + def get_shading(self) -> np.ndarray: + return self.uniforms["shading"] + + def set_shading( + self, + reflectiveness: float | None = None, + gloss: float | None = None, + shadow: float | None = None, + recurse: bool = True + ): + """ + Larger reflectiveness makes things brighter when facing the light + Larger shadow makes faces opposite the light darker + Makes parts bright where light gets reflected toward the camera + """ + for mob in self.get_family(recurse): + for i, value in enumerate([reflectiveness, gloss, shadow]): + if value is not None: + mob.uniforms["shading"][i] = value + return self + def get_reflectiveness(self) -> float: - return self.uniforms["reflectiveness"] - - def set_reflectiveness(self, reflectiveness: float, recurse: bool = True): - for mob in self.get_family(recurse): - mob.uniforms["reflectiveness"] = reflectiveness - return self - - def get_shadow(self) -> float: - return self.uniforms["shadow"] - - def set_shadow(self, shadow: float, recurse: bool = True): - for mob in self.get_family(recurse): - mob.uniforms["shadow"] = shadow - return self + return self.get_shading()[0] def get_gloss(self) -> float: - return self.uniforms["gloss"] + return self.get_shading()[1] + + def get_shadow(self) -> float: + return self.get_shading()[2] + + def set_reflectiveness(self, reflectiveness: float, recurse: bool = True): + self.set_shading(reflectiveness=reflectiveness, recurse=recurse) + return self def set_gloss(self, gloss: float, recurse: bool = True): - for mob in self.get_family(recurse): - mob.uniforms["gloss"] = gloss + self.set_shading(gloss=gloss, recurse=recurse) + return self + + def set_shadow(self, shadow: float, recurse: bool = True): + self.set_shading(shadow=shadow, recurse=recurse) return self # Background rectangle diff --git a/manimlib/mobject/svg/drawings.py b/manimlib/mobject/svg/drawings.py index 2ae13e9a..ed7e7f9d 100644 --- a/manimlib/mobject/svg/drawings.py +++ b/manimlib/mobject/svg/drawings.py @@ -552,7 +552,7 @@ class Piano(VGroup): class Piano3D(VGroup): def __init__( self, - reflectiveness: float = 1.0, + shading: Tuple[float, float, float] = (1.0, 0.2, 0.2), stroke_width: float = 0.25, stroke_color: ManimColor = BLACK, key_depth: float = 0.1, @@ -569,6 +569,7 @@ class Piano3D(VGroup): for key in piano_2d )) self.set_stroke(stroke_color, stroke_width) + self.set_shading(*shading) self.apply_depth_test() # Elevate black keys diff --git a/manimlib/mobject/three_dimensions.py b/manimlib/mobject/three_dimensions.py index dc49f7ab..65f3a610 100644 --- a/manimlib/mobject/three_dimensions.py +++ b/manimlib/mobject/three_dimensions.py @@ -23,7 +23,7 @@ from manimlib.utils.space_ops import z_to_vector from typing import TYPE_CHECKING if TYPE_CHECKING: from typing import Tuple, TypeVar - from manimlib.typing import ManimColor, Vect3 + from manimlib.typing import ManimColor, Vect3, Sequence T = TypeVar("T", bound=Mobject) @@ -252,7 +252,7 @@ class Cube(SGroup): self, color: ManimColor = BLUE, opacity: float = 1, - gloss: float = 0.5, + shading: Tuple[float, float, float] = (0.1, 0.5, 0.1), square_resolution: Tuple[int, int] = (2, 2), side_length: float = 2, **kwargs, @@ -262,12 +262,9 @@ class Cube(SGroup): side_length=side_length, color=color, opacity=opacity, + shading=shading, ) - super().__init__( - *square_to_cube_faces(face), - gloss=gloss, - **kwargs - ) + super().__init__(*square_to_cube_faces(face), **kwargs) class Prism(Cube): @@ -288,16 +285,12 @@ class VGroup3D(VGroup): self, *vmobjects: VMobject, depth_test: bool = True, - gloss: float = 0.2, - shadow: float = 0.2, - reflectiveness: float = 0.2, + shading: Tuple[float, float, float] = (0.2, 0.2, 0.2), joint_type: str = "no_joint", **kwargs ): super().__init__(*vmobjects, **kwargs) - self.set_gloss(gloss) - self.set_shadow(shadow) - self.set_reflectiveness(reflectiveness) + self.set_shading(*shading) self.set_joint_type(joint_type) if depth_test: self.apply_depth_test() @@ -342,7 +335,7 @@ class Dodecahedron(VGroup3D): fill_opacity: float = 1, stroke_color: ManimColor = BLUE_E, stroke_width: float = 1, - reflectiveness: float = 0.2, + shading: Tuple[float, float, float] = (0.2, 0.2, 0.2), **kwargs, ): style = dict( @@ -350,7 +343,7 @@ class Dodecahedron(VGroup3D): fill_opacity=fill_opacity, stroke_color=stroke_color, stroke_width=stroke_width, - reflectiveness=reflectiveness, + shading=shading, **kwargs ) diff --git a/manimlib/mobject/types/dot_cloud.py b/manimlib/mobject/types/dot_cloud.py index ff68462f..8e8e0a0e 100644 --- a/manimlib/mobject/types/dot_cloud.py +++ b/manimlib/mobject/types/dot_cloud.py @@ -137,9 +137,13 @@ class DotCloud(PMobject): self.set_radii(scale_factor * self.get_radii()) return self - def make_3d(self, reflectiveness: float = 0.5, shadow: float = 0.2): - self.set_reflectiveness(reflectiveness) - self.set_shadow(shadow) + def make_3d( + self, + reflectiveness: float = 0.5, + gloss: float = 0.1, + shadow: float = 0.2 + ): + self.set_shading(reflectiveness, gloss, shadow) self.apply_depth_test() return self diff --git a/manimlib/mobject/types/surface.py b/manimlib/mobject/types/surface.py index d0315076..101822f7 100644 --- a/manimlib/mobject/types/surface.py +++ b/manimlib/mobject/types/surface.py @@ -36,9 +36,7 @@ class Surface(Mobject): def __init__( self, color: ManimColor = GREY, - reflectiveness: float = 0.3, - gloss: float = 0.1, - shadow: float = 0.4, + shading: Tuple[float, float, float] = (0.3, 0.2, 0.4), depth_test: bool = True, u_range: Tuple[float, float] = (0.0, 1.0), v_range: Tuple[float, float] = (0.0, 1.0), @@ -61,9 +59,7 @@ class Surface(Mobject): super().__init__( **kwargs, color=color, - reflectiveness=reflectiveness, - gloss=gloss, - shadow=shadow, + shading=shading, depth_test=depth_test, ) self.compute_triangle_indices() @@ -300,7 +296,7 @@ class TexturedSurface(Surface): self.resolution: Tuple[int, int] = uv_surface.resolution super().__init__( texture_paths=texture_paths, - gloss=uv_surface.gloss, + shading=tuple(uv_surface.shading), **kwargs ) diff --git a/manimlib/mobject/types/vectorized_mobject.py b/manimlib/mobject/types/vectorized_mobject.py index fb329352..584dd6a8 100644 --- a/manimlib/mobject/types/vectorized_mobject.py +++ b/manimlib/mobject/types/vectorized_mobject.py @@ -158,7 +158,7 @@ class VMobject(Mobject): opacity=self.stroke_opacity, background=self.stroke_behind, ) - self.set_gloss(self.gloss) + self.set_shading(*self.shading) self.set_flat_stroke(self.flat_stroke) self.color = self.get_color() return self @@ -229,9 +229,7 @@ class VMobject(Mobject): stroke_rgba: Vect4 | None = None, stroke_width: float | Iterable[float] | None = None, stroke_background: bool = True, - reflectiveness: float | None = None, - gloss: float | None = None, - shadow: float | None = None, + shading: Tuple[float, float, float] | None = None, recurse: bool = True ): for mob in self.get_family(recurse): @@ -260,12 +258,8 @@ class VMobject(Mobject): background=stroke_background, ) - if reflectiveness is not None: - mob.set_reflectiveness(reflectiveness, recurse=False) - if gloss is not None: - mob.set_gloss(gloss, recurse=False) - if shadow is not None: - mob.set_shadow(shadow, recurse=False) + if shading is not None: + mob.set_shading(*shading, recurse=False) return self def get_style(self): @@ -275,9 +269,7 @@ class VMobject(Mobject): "stroke_rgba": data['stroke_rgba'].copy(), "stroke_width": data['stroke_width'].copy(), "stroke_background": self.stroke_behind, - "reflectiveness": self.get_reflectiveness(), - "gloss": self.get_gloss(), - "shadow": self.get_shadow(), + "shading": self.get_shading(), } def match_style(self, vmobject: VMobject, recurse: bool = True): @@ -1160,7 +1152,7 @@ class VMobject(Mobject): self.make_approximately_smooth() return self - def apply_points_function(self, *args, **kwargs,): + def apply_points_function(self, *args, **kwargs): super().apply_points_function(*args, **kwargs) self.refresh_joint_angles() diff --git a/manimlib/shaders/inserts/finalize_color.glsl b/manimlib/shaders/inserts/finalize_color.glsl index f02705cd..72247062 100644 --- a/manimlib/shaders/inserts/finalize_color.glsl +++ b/manimlib/shaders/inserts/finalize_color.glsl @@ -1,8 +1,6 @@ uniform vec3 light_source_position; uniform vec3 camera_position; -uniform float reflectiveness; -uniform float gloss; -uniform float shadow; +uniform vec3 shading; vec3 float_to_color(float value, float min_val, float max_val, vec3[9] colormap_data){ float alpha = clamp((value - min_val) / (max_val - min_val), 0.0, 1.0); @@ -15,23 +13,16 @@ vec3 float_to_color(float value, float min_val, float max_val, vec3[9] colormap_ } -vec4 add_light( - vec4 color, - vec3 point, - vec3 unit_normal, - vec3 light_coords, - vec3 cam_coords, - float reflectiveness, - float gloss, - float shadow -){ - if(reflectiveness == 0.0 && gloss == 0.0 && shadow == 0.0) return color; +vec4 add_light(vec4 color, vec3 point, vec3 unit_normal){ + if(shading == vec3(0.0)) return color; + + float reflectiveness = shading.x; + float gloss = shading.y; + float shadow = shading.z; vec4 result = color; - // Assume everything has already been rotated such that camera is in the z-direction - // cam_coords = vec3(0, 0, focal_distance); - vec3 to_camera = normalize(cam_coords - point); - vec3 to_light = normalize(light_coords - point); + vec3 to_camera = normalize(camera_position - point); + vec3 to_light = normalize(light_position - point); // Note, this effectively treats surfaces as two-sided // if(dot(to_camera, unit_normal) < 0) unit_normal *= -1; @@ -48,26 +39,18 @@ vec4 add_light( result.rgb = mix(result.rgb, vec3(1.0), bright_factor); if (light_to_normal < 0){ // Darken - result.rgb = mix(result.rgb, vec3(0.0), -light_to_normal * shadow); + result.rgb = mix( + result.rgb, + vec3(0.0), + max(-light_to_normal, 0) * shadow + ); } return result; } -vec4 finalize_color( - vec4 color, - vec3 point, - vec3 unit_normal, - vec3 light_coords, - vec3 cam_coords, - float reflectiveness, - float gloss, - float shadow -){ +vec4 finalize_color(vec4 color, vec3 point, vec3 unit_normal){ ///// INSERT COLOR FUNCTION HERE ///// // The line above may be replaced by arbitrary code snippets, as per // the method Mobject.set_color_by_code - return add_light( - color, point, unit_normal, light_coords, cam_coords, - reflectiveness, gloss, shadow - ); + return add_light(color, point, unit_normal); } \ No newline at end of file diff --git a/manimlib/shaders/mandelbrot_fractal/frag.glsl b/manimlib/shaders/mandelbrot_fractal/frag.glsl index a75c838b..10e62f39 100644 --- a/manimlib/shaders/mandelbrot_fractal/frag.glsl +++ b/manimlib/shaders/mandelbrot_fractal/frag.glsl @@ -64,11 +64,6 @@ void main() { frag_color = finalize_color( vec4(color, opacity), xyz_coords, - vec3(0.0, 0.0, 1.0), - light_source_position, - camera_position, - reflectiveness, - gloss, - shadow + vec3(0.0, 0.0, 1.0) ); } \ No newline at end of file diff --git a/manimlib/shaders/newton_fractal/frag.glsl b/manimlib/shaders/newton_fractal/frag.glsl index c976038f..64d7d2fa 100644 --- a/manimlib/shaders/newton_fractal/frag.glsl +++ b/manimlib/shaders/newton_fractal/frag.glsl @@ -144,11 +144,6 @@ void main() { frag_color = finalize_color( color, xyz_coords, - vec3(0.0, 0.0, 1.0), - light_source_position, - camera_position, - reflectiveness, - gloss, - shadow + vec3(0.0, 0.0, 1.0) ); } \ No newline at end of file diff --git a/manimlib/shaders/quadratic_bezier_fill/geom.glsl b/manimlib/shaders/quadratic_bezier_fill/geom.glsl index 27d83835..b27b9359 100644 --- a/manimlib/shaders/quadratic_bezier_fill/geom.glsl +++ b/manimlib/shaders/quadratic_bezier_fill/geom.glsl @@ -33,14 +33,9 @@ void emit_vertex_wrapper(vec3 point, int index, vec3 unit_normal){ color = finalize_color( v_color[index], point, - unit_normal, - light_source_position, - camera_position, - reflectiveness, - gloss, - shadow + unit_normal ); - gl_Position = get_gl_Position(point); + gl_Position = get_gl_Position(position_point_into_frame(point)); EmitVertex(); } diff --git a/manimlib/shaders/quadratic_bezier_fill/vert.glsl b/manimlib/shaders/quadratic_bezier_fill/vert.glsl index 3b6976e8..3d2e2c9a 100644 --- a/manimlib/shaders/quadratic_bezier_fill/vert.glsl +++ b/manimlib/shaders/quadratic_bezier_fill/vert.glsl @@ -10,11 +10,8 @@ out float v_orientation; out vec4 v_color; out float v_vert_index; -// Analog of import for manim only -#INSERT get_gl_Position.glsl - void main(){ - verts = position_point_into_frame(point); + verts = point; v_orientation = orientation; v_color = fill_rgba; v_vert_index = vert_index; diff --git a/manimlib/shaders/quadratic_bezier_stroke/geom.glsl b/manimlib/shaders/quadratic_bezier_stroke/geom.glsl index a51ed2dd..f290710b 100644 --- a/manimlib/shaders/quadratic_bezier_stroke/geom.glsl +++ b/manimlib/shaders/quadratic_bezier_stroke/geom.glsl @@ -177,14 +177,9 @@ void main() { color = finalize_color( v_color[vert_index], corners[i], - unit_normal, - light_source_position, - camera_position, - reflectiveness, - gloss, - shadow + unit_normal ); - gl_Position = get_gl_Position(corners[i]); + gl_Position = get_gl_Position(position_point_into_frame(corners[i])); EmitVertex(); } EndPrimitive(); diff --git a/manimlib/shaders/quadratic_bezier_stroke/vert.glsl b/manimlib/shaders/quadratic_bezier_stroke/vert.glsl index f2de716a..613edb15 100644 --- a/manimlib/shaders/quadratic_bezier_stroke/vert.glsl +++ b/manimlib/shaders/quadratic_bezier_stroke/vert.glsl @@ -1,5 +1,7 @@ #version 330 +uniform vec2 frame_shape; + in vec3 point; in vec4 stroke_rgba; in float stroke_width; @@ -15,11 +17,8 @@ out float v_vert_index; const float STROKE_WIDTH_CONVERSION = 0.01; -#INSERT get_gl_Position.glsl - void main(){ - verts = position_point_into_frame(point); - + verts = point; v_stroke_width = STROKE_WIDTH_CONVERSION * stroke_width * frame_shape[1] / 8.0; v_joint_angle = joint_angle; v_color = stroke_rgba; diff --git a/manimlib/shaders/surface/vert.glsl b/manimlib/shaders/surface/vert.glsl index 9e9a722a..95b8e108 100644 --- a/manimlib/shaders/surface/vert.glsl +++ b/manimlib/shaders/surface/vert.glsl @@ -7,32 +7,18 @@ in vec3 du_point; in vec3 dv_point; in vec4 rgba; -out vec3 xyz_coords; -out vec3 v_normal; out vec4 v_color; #INSERT get_gl_Position.glsl -#INSERT get_rotated_surface_unit_normal_vector.glsl +#INSERT get_unit_normal.glsl #INSERT finalize_color.glsl void main(){ - xyz_coords = position_point_into_frame(point); - v_normal = get_rotated_surface_unit_normal_vector(point, du_point, dv_point); - v_color = rgba; - gl_Position = get_gl_Position(xyz_coords); + gl_Position = get_gl_Position(position_point_into_frame(point)); + vec3 normal = get_unit_normal(point, du_point, dv_point); + v_color = finalize_color(rgba, point, normal); 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( - rgba, - xyz_coords, - v_normal, - light_source_position, - camera_position, - reflectiveness, - gloss, - shadow - ); } \ No newline at end of file diff --git a/manimlib/shaders/textured_surface/frag.glsl b/manimlib/shaders/textured_surface/frag.glsl index 65d4aa8f..7d8010e6 100644 --- a/manimlib/shaders/textured_surface/frag.glsl +++ b/manimlib/shaders/textured_surface/frag.glsl @@ -4,7 +4,7 @@ uniform sampler2D LightTexture; uniform sampler2D DarkTexture; uniform float num_textures; -in vec3 xyz_coords; +in vec3 v_point; in vec3 v_normal; in vec2 v_im_coords; in float v_opacity; @@ -20,7 +20,7 @@ void main() { if(num_textures == 2.0){ vec4 dark_color = texture(DarkTexture, v_im_coords); float dp = dot( - normalize(light_source_position - xyz_coords), + normalize(light_source_position - v_point), normalize(v_normal) ); float alpha = smoothstep(-dark_shift, dark_shift, dp); @@ -29,13 +29,8 @@ void main() { frag_color = finalize_color( color, - xyz_coords, - normalize(v_normal), - light_source_position, - camera_position, - reflectiveness, - gloss, - shadow + v_point, + normalize(v_normal) ); frag_color.a = v_opacity; } \ No newline at end of file diff --git a/manimlib/shaders/textured_surface/vert.glsl b/manimlib/shaders/textured_surface/vert.glsl index 1127622d..02b9afce 100644 --- a/manimlib/shaders/textured_surface/vert.glsl +++ b/manimlib/shaders/textured_surface/vert.glsl @@ -6,18 +6,18 @@ in vec3 dv_point; in vec2 im_coords; in float opacity; -out vec3 xyz_coords; +out vec3 v_point; out vec3 v_normal; out vec2 v_im_coords; out float v_opacity; #INSERT get_gl_Position.glsl -#INSERT get_rotated_surface_unit_normal_vector.glsl +#INSERT get_unit_normal.glsl void main(){ - xyz_coords = position_point_into_frame(point); - v_normal = get_rotated_surface_unit_normal_vector(point, du_point, dv_point); + v_point = point; + v_normal = get_unit_normal(point, du_point, dv_point); v_im_coords = im_coords; v_opacity = opacity; - gl_Position = get_gl_Position(xyz_coords); + gl_Position = get_gl_Position(position_point_into_frame(point)); } \ No newline at end of file diff --git a/manimlib/shaders/true_dot/frag.glsl b/manimlib/shaders/true_dot/frag.glsl index caf221ba..a34d9ed0 100644 --- a/manimlib/shaders/true_dot/frag.glsl +++ b/manimlib/shaders/true_dot/frag.glsl @@ -11,6 +11,10 @@ in float scaled_aaw; out vec4 frag_color; +// This include a delaration of +// uniform vec3 shading +// uniform vec3 camera_position +// uniform vec3 light_position #INSERT finalize_color.glsl void main() { @@ -21,17 +25,12 @@ void main() { discard; } frag_color = color; - if(gloss > 0 || shadow > 0){ + if(shading != vec3(0.0)){ vec3 normal = vec3(diff / radius, sqrt(1 - (dist * dist) / (radius * radius))); frag_color = finalize_color( frag_color, vec3(point.xy, 0.0), - normal, - light_source_position, - camera_position, - reflectiveness, - gloss, - shadow + normal ); } if(glow_factor > 0){