Add is_fixed_in_frame uniform which allows mobjects to not get rotated by the camera

This commit is contained in:
Grant Sanderson 2020-06-08 20:27:07 -07:00
parent 5d34cee014
commit ccefbc0dea
16 changed files with 73 additions and 33 deletions

View file

@ -148,7 +148,7 @@ class Camera(object):
"light_source_position": [-10, 10, 10],
"apply_depth_test": False,
# Measured in pixel widths, used for vector graphics
"anti_alias_width": 1.5,
"anti_alias_width": 3,
# Although vector graphics handle antialiasing fine
# without multisampling, for 3d scenes one might want
# to set samples to be greater than 0.
@ -362,14 +362,11 @@ class Camera(object):
for name, path in info["texture_paths"].items():
tid = self.get_texture_id(path)
shader[name].value = tid
for name, value in info["uniforms"].items():
shader[name].value = value
self.set_shader_uniforms(shader)
self.set_shader_uniforms(shader, sid)
self.id_to_shader[sid] = shader
return self.id_to_shader[sid]
def set_shader_uniforms(self, shader):
def set_shader_uniforms(self, shader, sid):
if shader is None:
return
@ -378,13 +375,15 @@ class Camera(object):
transform = self.frame.get_inverse_camera_position_matrix()
light = self.light_source.get_location()
transformed_light = np.dot(transform, [*light, 1])[:3]
mapping = {
'to_screen_space': tuple(transform.T.flatten()),
'frame_shape': self.frame.get_shape(),
'focal_distance': self.frame.get_focal_distance(),
'anti_alias_width': anti_alias_width,
'light_source_position': tuple(transformed_light),
}
mapping = dict()
mapping['to_screen_space'] = tuple(transform.T.flatten())
mapping['frame_shape'] = self.frame.get_shape()
mapping['focal_distance'] = self.frame.get_focal_distance()
mapping['anti_alias_width'] = anti_alias_width
mapping['light_source_position'] = tuple(transformed_light)
# Potentially overwrite with whatever came from the mobject
mapping.update(shader_id_to_info(sid)["uniforms"])
for key, value in mapping.items():
try:
shader[key].value = value
@ -393,7 +392,7 @@ class Camera(object):
def refresh_shader_uniforms(self):
for sid, shader in self.id_to_shader.items():
self.set_shader_uniforms(shader)
self.set_shader_uniforms(shader, sid)
def init_textures(self):
self.path_to_texture_id = {}

View file

@ -51,6 +51,8 @@ class Mobject(Container):
"frag_shader_file": "",
"render_primative": moderngl.TRIANGLE_STRIP,
"texture_paths": None,
# If true, the mobject will not get rotated according to camera position
"is_fixed_in_frame": False,
# Must match in attributes of vert shader
"shader_dtype": [
('point', np.float32, (3,)),
@ -455,8 +457,19 @@ class Mobject(Container):
# Redundant with default behavior of scale now.
return self.scale(scale_factor, about_point=point)
def pose_at_angle(self, angle=TAU / 14, axis=UR, **kwargs):
return self.rotate(angle, axis, **kwargs)
def fix_in_frame(self, family=True):
self.is_fixed_in_frame = True
if family:
for submob in self.submobjects:
submob.fix_in_frame(family)
return self
def unfix_from_frame(self, family=True):
self.is_fixed_in_frame = False
if family:
for submob in self.submobjects:
submob.unfix_from_frame(family)
return self
# Positioning methods
@ -1221,7 +1234,9 @@ class Mobject(Container):
)
def get_shader_uniforms(self):
return {}
return {
"is_fixed_in_frame": float(self.is_fixed_in_frame),
}
def get_shader_data(self):
# Typically to be implemented by subclasses

View file

@ -214,7 +214,9 @@ class TexturedSurface(ParametricSurface):
return self
def get_shader_uniforms(self):
return {"num_textures": self.num_textures}
result = super().get_shader_uniforms()
result["num_textures"] = self.num_textures
return result
def fill_in_shader_color_info(self, data):
data["im_coords"] = self.get_triangle_ready_array(self.im_coords)

View file

@ -830,7 +830,7 @@ class VMobject(Mobject):
render_primative=self.render_primative,
)
fill_info = get_shader_info(
uniforms={},
uniforms=self.get_shader_uniforms(),
vert_file=self.fill_vert_shader_file,
geom_file=self.fill_geom_shader_file,
frag_file=self.fill_frag_shader_file,
@ -870,13 +870,15 @@ class VMobject(Mobject):
return result
def get_stroke_uniforms(self):
joint_type_to_code = {
j_map = {
"auto": 0,
"round": 1,
"bevel": 2,
"miter": 3,
}
return {"joint_type": joint_type_to_code[self.joint_type]}
result = super().get_shader_uniforms()
result["join_type"] = j_map[self.joint_type]
return result
def get_stroke_shader_data(self):
rgbas = self.get_stroke_rgbas()

View file

@ -1,15 +1,24 @@
// Assumes the following uniforms exist in the surrounding context:
// uniform vec2 frame_shape;
// uniform float focal_distance;
// uniform float is_fixed_in_frame;
const vec2 DEFAULT_FRAME_SHAPE = vec2(8 * 16 / 9, 8);
vec4 get_gl_Position(vec3 point){
point.x *= 2 / frame_shape.x;
point.y *= 2 / frame_shape.y;
point.z /= focal_distance;
point.xy /= max(1 - point.z, 0);
// Todo, does this discontinuity add weirdness? Theoretically, by this point,
// the z-coordiante of gl_Position only matter for z-indexing. The reason
// for thie line is to avoid agressive clipping of distant points.
if(point.z < 0) point.z *= 0.1;
if(!bool(is_fixed_in_frame)){
point.x *= 2 / frame_shape.x;
point.y *= 2 / frame_shape.y;
point.z /= focal_distance;
point.xy /= max(1 - point.z, 0);
// Todo, does this discontinuity add weirdness? Theoretically, by this point,
// the z-coordiante of gl_Position only matter for z-indexing. The reason
// for thie line is to avoid agressive clipping of distant points.
if(point.z < 0) point.z *= 0.1;
} else{
point.x *= 2 / DEFAULT_FRAME_SHAPE.x;
point.y *= 2 / DEFAULT_FRAME_SHAPE.y;
}
return vec4(point.xy, -point.z, 1);
}

View file

@ -3,6 +3,7 @@
uniform vec2 frame_shape;
uniform float anti_alias_width;
uniform mat4 to_screen_space;
uniform float is_fixed_in_frame;
uniform float focal_distance;
uniform sampler2D Texture;

View file

@ -1,7 +1,12 @@
// Must be used in an environment with the following uniforms:
// uniform mat4 to_screen_space;
// uniform float is_fixed_in_frame;
vec3 position_point_into_frame(vec3 point){
// Simply apply the pre-computed to_screen_space matrix.
return (to_screen_space * vec4(point, 1)).xyz;
if(bool(is_fixed_in_frame)){
return point;
}else{
// Simply apply the pre-computed to_screen_space matrix.
return (to_screen_space * vec4(point, 1)).xyz;
}
}

View file

@ -1,6 +1,7 @@
#version 330
uniform mat4 to_screen_space;
uniform float is_fixed_in_frame;
in vec4 color;
in float fill_all; // Either 0 or 1e

View file

@ -7,6 +7,7 @@ uniform float anti_alias_width;
// Needed for get_gl_Position
uniform vec2 frame_shape;
uniform float focal_distance;
uniform float is_fixed_in_frame;
uniform vec3 light_source_position;
in vec3 bp[3];

View file

@ -1,6 +1,7 @@
#version 330
uniform mat4 to_screen_space;
uniform float is_fixed_in_frame;
in vec3 point;
in vec3 unit_normal;

View file

@ -1,6 +1,7 @@
#version 330
uniform mat4 to_screen_space;
uniform float is_fixed_in_frame;
uniform vec3 light_source_position;
in vec2 uv_coords;

View file

@ -6,6 +6,7 @@ layout (triangle_strip, max_vertices = 5) out;
// Needed for get_gl_Position
uniform vec2 frame_shape;
uniform float focal_distance;
uniform float is_fixed_in_frame;
uniform float anti_alias_width;
uniform vec3 light_source_position;
uniform float joint_type;

View file

@ -1,6 +1,7 @@
#version 330
uniform mat4 to_screen_space;
uniform float is_fixed_in_frame;
uniform float focal_distance;
in vec3 point;

View file

@ -3,6 +3,7 @@
uniform vec2 frame_shape;
uniform float anti_alias_width;
uniform mat4 to_screen_space;
uniform float is_fixed_in_frame;
uniform float focal_distance;
in vec3 point;

View file

@ -1,8 +1,8 @@
#version 330
uniform vec2 frame_shape;
uniform float anti_alias_width;
uniform mat4 to_screen_space;
uniform float is_fixed_in_frame;
uniform float focal_distance;
uniform vec3 light_source_position;

View file

@ -1,8 +1,8 @@
#version 330
uniform vec2 frame_shape;
uniform float anti_alias_width;
uniform mat4 to_screen_space;
uniform float is_fixed_in_frame;
uniform float focal_distance;
uniform vec3 light_source_position;