Skip to content

Add :class:~.OpenGLImageMobject #1837

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions manim/mobject/types/opengl_image_mobject.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import numpy as np
from PIL import Image

from ...constants import *
from ...utils.bezier import inverse_interpolate
from ...utils.images import get_full_raster_image_path
from ...utils.iterables import listify
from ..opengl_mobject import OpenGLMobject


class OpenGLImageMobject(OpenGLMobject):
shader_dtype = [
("point", np.float32, (3,)),
("im_coords", np.float32, (2,)),
("opacity", np.float32, (1,)),
]
shader_folder = "image"

def __init__(self, filename, width=None, height=None, opacity=1, **kwargs):
path = get_full_raster_image_path(filename)
self.image = Image.open(path)
self.size = self.image.size
if width is None and height is None:
width = self.size[0] / self.size[1]
height = 1
if height is None:
height = width * self.size[1] / self.size[0]
if width is None:
width = height * self.size[0] / self.size[1]

self.tmp_width = width
self.tmp_height = height
super().__init__(
opacity=opacity,
texture_paths={"Texture": path},
width=width,
height=height,
**kwargs
)

def init_data(self):
w = self.tmp_width / 2
h = self.tmp_height / 2
self.data = {
"points": np.array(
[
UP * h + LEFT * w,
DOWN * h + LEFT * w,
UP * h + RIGHT * w,
UP * h + RIGHT * w,
DOWN * h + RIGHT * w,
DOWN * h + LEFT * w,
]
),
"im_coords": np.array([(0, 0), (0, 1), (1, 0), (1, 0), (1, 1), (0, 1)]),
"opacity": np.array([[self.opacity]], dtype=np.float32),
}

def set_opacity(self, opacity, recurse=True):
for mob in self.get_family(recurse):
mob.data["opacity"] = np.array([[o] for o in listify(opacity)])
return self

def point_to_rgb(self, point):
x0, y0 = self.get_corner(UL)[:2]
x1, y1 = self.get_corner(DR)[:2]
x_alpha = inverse_interpolate(x0, x1, point[0])
y_alpha = inverse_interpolate(y0, y1, point[1])
if not (0 <= x_alpha <= 1) and (0 <= y_alpha <= 1):
# TODO, raise smarter exception
raise Exception("Cannot sample color from outside an image")

pw, ph = self.image.size
rgb = self.image.getpixel(
(
int((pw - 1) * x_alpha),
int((ph - 1) * y_alpha),
)
)
return np.array(rgb) / 255

def get_shader_data(self):
shader_data = super().get_shader_data()
self.read_data_to_shader(shader_data, "im_coords", "im_coords")
self.read_data_to_shader(shader_data, "opacity", "opacity")
return shader_data
1 change: 1 addition & 0 deletions manim/opengl/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from ..mobject.svg.opengl_svg_mobject import *
from ..mobject.svg.opengl_tex_mobject import *
from ..mobject.svg.opengl_text_mobject import *
from ..mobject.types.opengl_image_mobject import *
from ..mobject.types.opengl_surface import *
from ..mobject.types.opengl_vectorized_mobject import *
from ..renderer.shader import *
Expand Down
2 changes: 1 addition & 1 deletion manim/renderer/shaders/image/frag.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ out vec4 frag_color;

void main() {
frag_color = texture(Texture, v_im_coords);
frag_color.a = v_opacity;
frag_color.a *= v_opacity;
}
3 changes: 3 additions & 0 deletions manim/renderer/shaders/image/vert.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
#include ../include/camera_uniform_declarations.glsl

uniform sampler2D Texture;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

in vec3 point;
in vec2 im_coords;
Expand Down
7 changes: 0 additions & 7 deletions manim/renderer/shaders/include/get_gl_Position.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,6 @@ vec4 get_gl_Position(vec3 point){
if(!bool(is_fixed_in_frame)){
result.x *= 2.0 / frame_shape.x;
result.y *= 2.0 / frame_shape.y;
float psf = perspective_scale_factor(result.z, focal_distance);
if (psf > 0){
result.xy *= psf;
// TODO, what's the better way to do this?
// This is to keep vertices too far out of frame from getting cut.
result.z *= 0.01;
}
} else{
result.x *= 2.0 / DEFAULT_FRAME_SHAPE.x;
result.y *= 2.0 / DEFAULT_FRAME_SHAPE.y;
Expand Down