From 81c3ae30372e288dc772633dbd17def6e603753e Mon Sep 17 00:00:00 2001 From: Grant Sanderson Date: Mon, 8 Nov 2021 21:43:57 -0800 Subject: [PATCH] Have separate notions of gloss and reflectiveness --- manimlib/mobject/mobject.py | 36 +++++++++---- .../inserts/camera_uniform_declarations.glsl | 2 +- manimlib/shaders/inserts/finalize_color.glsl | 51 ++++++++++++------- ...et_rotated_surface_unit_normal_vector.glsl | 2 +- .../inserts/position_point_into_frame.glsl | 4 +- manimlib/shaders/mandelbrot_fractal/frag.glsl | 4 ++ manimlib/shaders/newton_fractal/frag.glsl | 4 ++ .../shaders/quadratic_bezier_fill/geom.glsl | 4 ++ .../shaders/quadratic_bezier_stroke/geom.glsl | 4 ++ manimlib/shaders/surface/frag.glsl | 4 ++ manimlib/shaders/textured_surface/frag.glsl | 4 ++ manimlib/shaders/true_dot/frag.glsl | 30 +++++++---- 12 files changed, 108 insertions(+), 41 deletions(-) diff --git a/manimlib/mobject/mobject.py b/manimlib/mobject/mobject.py index b5e89fc0..35e3a0f5 100644 --- a/manimlib/mobject/mobject.py +++ b/manimlib/mobject/mobject.py @@ -43,10 +43,13 @@ class Mobject(object): "opacity": 1, "dim": 3, # TODO, get rid of this # Lighting parameters - # Positive gloss up to 1 makes it reflect the light. - "gloss": 0.0, - # Positive shadow up to 1 makes a side opposite the light darker + # ... + # Larger reflectiveness makes things brighter when facing the light + "reflectiveness": 0.0, + # Larger shadow makes faces opposite the light darker "shadow": 0.0, + # Makes parts bright where light gets reflected toward the camera + "gloss": 0.0, # For shaders "shader_folder": "", "render_primitive": moderngl.TRIANGLE_STRIP, @@ -82,11 +85,11 @@ class Mobject(object): def __str__(self): return self.__class__.__name__ - def __add__(self, other : 'Mobject') -> 'Mobject': + def __add__(self, other: 'Mobject') -> 'Mobject': assert(isinstance(other, Mobject)) return self.get_group_class()(self, other) - def __mul__(self, other : 'int') -> 'Mobject': + def __mul__(self, other: 'int') -> 'Mobject': assert(isinstance(other, int)) return self.replicate(other) @@ -102,6 +105,7 @@ class Mobject(object): "is_fixed_in_frame": float(self.is_fixed_in_frame), "gloss": self.gloss, "shadow": self.shadow, + "reflectiveness": self.reflectiveness, } def init_colors(self): @@ -394,6 +398,7 @@ class Mobject(object): self.submobjects.sort(key=submob_func) else: self.submobjects.sort(key=lambda m: point_to_num_func(m.get_center())) + self.assemble_family() return self def shuffle(self, recurse=False): @@ -401,6 +406,7 @@ class Mobject(object): for submob in self.submobjects: submob.shuffle(recurse=True) random.shuffle(self.submobjects) + self.assemble_family() return self # Copying @@ -974,12 +980,12 @@ class Mobject(object): def fade(self, darkness=0.5, recurse=True): self.set_opacity(1.0 - darkness, recurse=recurse) - def get_gloss(self): - return self.uniforms["gloss"] + def get_reflectiveness(self): + return self.uniforms["reflectiveness"] - def set_gloss(self, gloss, recurse=True): + def set_reflectiveness(self, reflectiveness, recurse=True): for mob in self.get_family(recurse): - mob.uniforms["gloss"] = gloss + mob.uniforms["reflectiveness"] = reflectiveness return self def get_shadow(self): @@ -990,6 +996,14 @@ class Mobject(object): mob.uniforms["shadow"] = shadow return self + def get_gloss(self): + return self.uniforms["gloss"] + + def set_gloss(self, gloss, recurse=True): + for mob in self.get_family(recurse): + mob.uniforms["gloss"] = gloss + return self + # Background rectangle def add_background_rectangle(self, color=None, opacity=0.75, **kwargs): @@ -1617,8 +1631,8 @@ class Group(Mobject): raise Exception("All submobjects must be of type Mobject") Mobject.__init__(self, **kwargs) self.add(*mobjects) - - def __add__(self, other : 'Mobject' or 'Group'): + + def __add__(self, other: 'Mobject' or 'Group'): assert(isinstance(other, Mobject)) return self.add(other) diff --git a/manimlib/shaders/inserts/camera_uniform_declarations.glsl b/manimlib/shaders/inserts/camera_uniform_declarations.glsl index b40b1b90..c67a01e1 100644 --- a/manimlib/shaders/inserts/camera_uniform_declarations.glsl +++ b/manimlib/shaders/inserts/camera_uniform_declarations.glsl @@ -1,6 +1,6 @@ uniform vec2 frame_shape; uniform float anti_alias_width; -uniform vec3 camera_center; +uniform vec3 camera_offset; uniform mat3 camera_rotation; uniform float is_fixed_in_frame; uniform float focal_distance; \ No newline at end of file diff --git a/manimlib/shaders/inserts/finalize_color.glsl b/manimlib/shaders/inserts/finalize_color.glsl index e7b64eee..de45e86c 100644 --- a/manimlib/shaders/inserts/finalize_color.glsl +++ b/manimlib/shaders/inserts/finalize_color.glsl @@ -13,39 +13,56 @@ vec4 add_light(vec4 color, vec3 point, vec3 unit_normal, vec3 light_coords, + vec3 cam_coords, + float reflectiveness, float gloss, float shadow){ - if(gloss == 0.0 && shadow == 0.0) return color; + if(reflectiveness == 0.0 && gloss == 0.0 && shadow == 0.0) return color; - float camera_distance = focal_distance; + vec4 result = color; // Assume everything has already been rotated such that camera is in the z-direction - vec3 to_camera = vec3(0, 0, camera_distance) - point; - vec3 to_light = light_coords - point; + // cam_coords = vec3(0, 0, focal_distance); + vec3 to_camera = normalize(cam_coords - point); + vec3 to_light = normalize(light_coords - point); - // TODO, do we actually want this? It effectively treats surfaces as two-sided - if(dot(to_camera,unit_normal) < 0){ - unit_normal *= -1; - } + // Note, this effectively treats surfaces as two-sided + // if(dot(to_camera, unit_normal) < 0) unit_normal *= -1; + float light_to_normal = dot(to_light, unit_normal); + // When unit normal points towards light, brighten + float bright_factor = max(light_to_normal, 0) * reflectiveness; + // For glossy surface, add extra shine if light beam go towards camera vec3 light_reflection = -to_light + 2 * unit_normal * dot(to_light, unit_normal); - float dot_prod = dot(normalize(light_reflection), normalize(to_camera)); - float shine = gloss * exp(-3 * pow(1 - dot_prod, 2)); - float dp2 = dot(normalize(to_light), unit_normal); - float darkening = mix(1, max(dp2, 0), shadow); - return vec4( - darkening * mix(color.rgb, vec3(1.0), shine), - color.a - ); + float light_to_cam = dot(light_reflection, to_camera); + float shine = gloss * exp(-3 * pow(1 - light_to_cam, 2)); + bright_factor += shine; + + 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); + } + // float darkening = mix(1, max(light_to_normal, 0), shadow); + // return vec4( + // darkening * mix(color.rgb, vec3(1.0), shine), + // color.a + // ); + return result; } vec4 finalize_color(vec4 color, vec3 point, vec3 unit_normal, vec3 light_coords, + vec3 cam_coords, + float reflectiveness, float gloss, float shadow){ ///// 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, gloss, shadow); + return add_light( + color, point, unit_normal, light_coords, cam_coords, + reflectiveness, gloss, shadow + ); } \ No newline at end of file diff --git a/manimlib/shaders/inserts/get_rotated_surface_unit_normal_vector.glsl b/manimlib/shaders/inserts/get_rotated_surface_unit_normal_vector.glsl index a9d637fe..012ec682 100644 --- a/manimlib/shaders/inserts/get_rotated_surface_unit_normal_vector.glsl +++ b/manimlib/shaders/inserts/get_rotated_surface_unit_normal_vector.glsl @@ -1,5 +1,5 @@ // Assumes the following uniforms exist in the surrounding context: -// uniform vec3 camera_center; +// uniform vec3 camera_offset; // uniform mat3 camera_rotation; vec3 get_rotated_surface_unit_normal_vector(vec3 point, vec3 du_point, vec3 dv_point){ diff --git a/manimlib/shaders/inserts/position_point_into_frame.glsl b/manimlib/shaders/inserts/position_point_into_frame.glsl index 4cef7e38..2e029579 100644 --- a/manimlib/shaders/inserts/position_point_into_frame.glsl +++ b/manimlib/shaders/inserts/position_point_into_frame.glsl @@ -1,6 +1,6 @@ // Assumes the following uniforms exist in the surrounding context: // uniform float is_fixed_in_frame; -// uniform vec3 camera_center; +// uniform vec3 camera_offset; // uniform mat3 camera_rotation; vec3 rotate_point_into_frame(vec3 point){ @@ -15,5 +15,5 @@ vec3 position_point_into_frame(vec3 point){ if(bool(is_fixed_in_frame)){ return point; } - return rotate_point_into_frame(point - camera_center); + return rotate_point_into_frame(point - camera_offset); } diff --git a/manimlib/shaders/mandelbrot_fractal/frag.glsl b/manimlib/shaders/mandelbrot_fractal/frag.glsl index 7d7e593f..0a2d40cc 100644 --- a/manimlib/shaders/mandelbrot_fractal/frag.glsl +++ b/manimlib/shaders/mandelbrot_fractal/frag.glsl @@ -1,6 +1,8 @@ #version 330 uniform vec3 light_source_position; +uniform vec3 camera_position; +uniform float reflectiveness; uniform float gloss; uniform float shadow; uniform float focal_distance; @@ -71,6 +73,8 @@ void main() { xyz_coords, vec3(0.0, 0.0, 1.0), light_source_position, + camera_position, + reflectiveness, gloss, shadow ); diff --git a/manimlib/shaders/newton_fractal/frag.glsl b/manimlib/shaders/newton_fractal/frag.glsl index 223f8556..74d4f4e9 100644 --- a/manimlib/shaders/newton_fractal/frag.glsl +++ b/manimlib/shaders/newton_fractal/frag.glsl @@ -1,6 +1,8 @@ #version 330 uniform vec3 light_source_position; +uniform vec3 camera_position; +uniform float reflectiveness; uniform float gloss; uniform float shadow; uniform float focal_distance; @@ -151,6 +153,8 @@ void main() { xyz_coords, vec3(0.0, 0.0, 1.0), light_source_position, + camera_position, + reflectiveness, gloss, shadow ); diff --git a/manimlib/shaders/quadratic_bezier_fill/geom.glsl b/manimlib/shaders/quadratic_bezier_fill/geom.glsl index 4fd9245f..7bc48d3e 100644 --- a/manimlib/shaders/quadratic_bezier_fill/geom.glsl +++ b/manimlib/shaders/quadratic_bezier_fill/geom.glsl @@ -11,6 +11,8 @@ uniform float focal_distance; uniform float is_fixed_in_frame; // Needed for finalize_color uniform vec3 light_source_position; +uniform vec3 camera_position; +uniform float reflectiveness; uniform float gloss; uniform float shadow; @@ -44,6 +46,8 @@ void emit_vertex_wrapper(vec3 point, int index){ point, v_global_unit_normal[index], light_source_position, + camera_position, + reflectiveness, gloss, shadow ); diff --git a/manimlib/shaders/quadratic_bezier_stroke/geom.glsl b/manimlib/shaders/quadratic_bezier_stroke/geom.glsl index 8baea0f9..08d35891 100644 --- a/manimlib/shaders/quadratic_bezier_stroke/geom.glsl +++ b/manimlib/shaders/quadratic_bezier_stroke/geom.glsl @@ -13,7 +13,9 @@ uniform float flat_stroke; //Needed for lighting uniform vec3 light_source_position; +uniform vec3 camera_position; uniform float joint_type; +uniform float reflectiveness; uniform float gloss; uniform float shadow; @@ -259,6 +261,8 @@ void main() { xyz_coords, v_global_unit_normal[index_map[i]], light_source_position, + camera_position, + reflectiveness, gloss, shadow ); diff --git a/manimlib/shaders/surface/frag.glsl b/manimlib/shaders/surface/frag.glsl index 707621a1..204a37dd 100644 --- a/manimlib/shaders/surface/frag.glsl +++ b/manimlib/shaders/surface/frag.glsl @@ -1,6 +1,8 @@ #version 330 uniform vec3 light_source_position; +uniform vec3 camera_position; +uniform float reflectiveness; uniform float gloss; uniform float shadow; uniform float focal_distance; @@ -19,6 +21,8 @@ void main() { xyz_coords, normalize(v_normal), light_source_position, + camera_position, + reflectiveness, gloss, shadow ); diff --git a/manimlib/shaders/textured_surface/frag.glsl b/manimlib/shaders/textured_surface/frag.glsl index 616b06e2..dc31ba36 100644 --- a/manimlib/shaders/textured_surface/frag.glsl +++ b/manimlib/shaders/textured_surface/frag.glsl @@ -4,6 +4,8 @@ uniform sampler2D LightTexture; uniform sampler2D DarkTexture; uniform float num_textures; uniform vec3 light_source_position; +uniform vec3 camera_position; +uniform float reflectiveness; uniform float gloss; uniform float shadow; uniform float focal_distance; @@ -36,6 +38,8 @@ void main() { xyz_coords, normalize(v_normal), light_source_position, + camera_position, + reflectiveness, gloss, shadow ); diff --git a/manimlib/shaders/true_dot/frag.glsl b/manimlib/shaders/true_dot/frag.glsl index 0be9a2ab..eca8b0b1 100644 --- a/manimlib/shaders/true_dot/frag.glsl +++ b/manimlib/shaders/true_dot/frag.glsl @@ -1,10 +1,13 @@ #version 330 uniform vec3 light_source_position; +uniform vec3 camera_position; +uniform float reflectiveness; uniform float gloss; uniform float shadow; uniform float anti_alias_width; uniform float focal_distance; +uniform float glow_factor; in vec4 color; in float radius; @@ -22,14 +25,23 @@ void main() { if (signed_dist > 0.5 * anti_alias_width){ discard; } - vec3 normal = vec3(diff / radius, sqrt(1 - (dist * dist) / (radius * radius))); - frag_color = finalize_color( - color, - vec3(point.xy, 0.0), - normal, - light_source_position, - gloss, - shadow - ); + frag_color = color; + if(gloss > 0 || shadow > 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 + ); + } + if(glow_factor > 0){ + frag_color.a *= pow(1 - dist / radius, glow_factor); + } + frag_color.a *= smoothstep(0.5, -0.5, signed_dist / anti_alias_width); } \ No newline at end of file