Have mobjects keep track of a consistent shader data array to avoid unneeded numpy initializing

This commit is contained in:
Grant Sanderson 2020-02-13 15:41:57 -08:00
parent c654ca4506
commit 5df2d3db33
3 changed files with 52 additions and 36 deletions

View file

@ -41,6 +41,9 @@ class Mobject(Container):
"frag_shader_file": "",
"render_primative": moderngl.TRIANGLE_STRIP,
"texture_path": "",
"shader_dtype": [
('point', np.float32, (3,)),
]
}
def __init__(self, **kwargs):
@ -55,6 +58,7 @@ class Mobject(Container):
self.reset_points()
self.init_points()
self.init_colors()
self.init_shader_data()
def __str__(self):
return str(self.name)
@ -110,7 +114,7 @@ class Mobject(Container):
if camera is None:
from manimlib.camera.camera import Camera
camera = Camera()
camera.capture_mobject(self)
camera.capture(self)
return camera.get_image()
def show(self, camera=None):
@ -1125,6 +1129,18 @@ class Mobject(Container):
pass
# For shaders
def init_shader_data(self):
self.shader_data = np.zeros(len(self.points), dtype=self.shader_dtype)
def get_shader_data_array(self, size, name="shader_data"):
# If possible, try to populate an existing array, rather
# than recreating it each frame
arr = getattr(self, name)
if arr.size != size:
new_arr = np.resize(arr, size)
setattr(self, name, new_arr)
return new_arr
return arr
def get_shader_info_list(self):
return [self.get_shader_info()]

View file

@ -15,6 +15,11 @@ class ImageMobject(Mobject):
"opacity": 1,
"vert_shader_file": "image_vert.glsl",
"frag_shader_file": "image_frag.glsl",
"shader_dtype": [
('point', np.float32, (3,)),
('im_coords', np.float32, (2,)),
('opacity', np.float32, (1,)),
]
}
def __init__(self, filename, **kwargs):
@ -37,17 +42,10 @@ class ImageMobject(Mobject):
self.set_opacity(self.opacity)
def get_shader_data(self):
dtype = [
('point', np.float32, (3,)),
('im_coords', np.float32, (2,)),
('opacity', np.float32, (1,)),
]
data = np.zeros(len(self.points), dtype=dtype)
data = self.get_shader_data_array(len(self.points))
data["point"] = self.points
data["im_coords"] = self.im_coords
data["opacity"] = self.opacity
return data
def set_opacity(self, alpha, family=True):

View file

@ -57,11 +57,22 @@ class VMobject(Mobject):
"joint_type": "auto",
"render_primative": moderngl.TRIANGLES,
"triangulation_locked": False,
"fill_dtype": [
('point', np.float32, (3,)),
('color', np.float32, (4,)),
('fill_all', np.float32, (1,)),
('orientation', np.float32, (1,)),
],
"stroke_dtype": [
("point", np.float32, (3,)),
("prev_point", np.float32, (3,)),
("next_point", np.float32, (3,)),
("stroke_width", np.float32, (1,)),
("color", np.float32, (4,)),
("joint_type", np.float32, (1,)),
]
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def get_group_class(self):
return VGroup
@ -794,6 +805,10 @@ class VMobject(Mobject):
return vmob
# For shaders
def init_shader_data(self):
self.fill_data = np.zeros(len(self.points), dtype=self.fill_dtype)
self.stroke_data = np.zeros(len(self.points), dtype=self.stroke_dtype)
def get_shader_info_list(self):
result = []
if self.get_fill_opacity() > 0:
@ -819,21 +834,12 @@ class VMobject(Mobject):
return result
def get_stroke_shader_data(self):
dtype = [
("point", np.float32, (3,)),
("prev_point", np.float32, (3,)),
("next_point", np.float32, (3,)),
("stroke_width", np.float32, (1,)),
("color", np.float32, (4,)),
("joint_type", np.float32, (1,)),
]
joint_type_to_code = {
"auto": 0,
"round": 1,
"bevel": 2,
"miter": 3,
}
points = self.points
rgbas = self.get_stroke_rgbas()
if len(rgbas) > 1:
@ -843,12 +849,12 @@ class VMobject(Mobject):
if len(stroke_width) > 1:
stroke_width = self.stretched_style_array_matching_points(stroke_width)
data = np.zeros(len(points), dtype=dtype)
data['point'] = points
data['prev_point'][:3] = points[-3:]
data['prev_point'][3:] = points[:-3]
data['next_point'][:-3] = points[3:]
data['next_point'][-3:] = points[:3]
data = self.get_shader_data_array(len(self.points), "stroke_data")
data['point'] = self.points
data['prev_point'][:3] = self.points[-3:]
data['prev_point'][3:] = self.points[:-3]
data['next_point'][:-3] = self.points[3:]
data['next_point'][-3:] = self.points[:3]
data['stroke_width'][:, 0] = stroke_width
data['color'] = rgbas
data['joint_type'] = joint_type_to_code[self.joint_type]
@ -858,6 +864,7 @@ class VMobject(Mobject):
for sm in self.family_members_with_points():
sm.triangulation_locked = False
sm.saved_triangulation = sm.get_triangulation()
sm.saved_orientation = sm.get_orientation()
sm.triangulation_locked = True
return self
@ -873,6 +880,8 @@ class VMobject(Mobject):
return sum((p0[:, 0] + p1[:, 0]) * (p1[:, 1] - p0[:, 1]))
def get_orientation(self):
if self.triangulation_locked:
return self.saved_orientation
return np.sign(self.get_signed_polygonal_area())
def get_triangulation(self, orientation=None):
@ -928,22 +937,15 @@ class VMobject(Mobject):
return tri_indices
def get_fill_shader_data(self):
dtype = [
('point', np.float32, (3,)),
('color', np.float32, (4,)),
('fill_all', np.float32, (1,)),
('orientation', np.float32, (1,)),
]
points = self.points
orientation = self.get_orientation()
tri_indices = self.get_triangulation(orientation)
# TODO, best way to enable multiple colors?
rgbas = self.get_fill_rgbas()
rgbas = self.get_fill_rgbas()[:1]
data = np.zeros(len(tri_indices), dtype=dtype)
data = self.get_shader_data_array(len(tri_indices), "fill_data")
data["point"] = points[tri_indices]
data["color"] = rgbas
# Assume the triangulation is such that the first n_points points