Better handling of textures, now letting multiple get passed in to a textured surface

This commit is contained in:
Grant Sanderson 2020-06-08 15:06:22 -07:00
parent 596b7c0112
commit 39230a805c
7 changed files with 52 additions and 40 deletions

View file

@ -367,11 +367,10 @@ class Camera(object):
geometry_shader=get_shader_code_from_file(info["geom"]), geometry_shader=get_shader_code_from_file(info["geom"]),
fragment_shader=get_shader_code_from_file(info["frag"]), fragment_shader=get_shader_code_from_file(info["frag"]),
) )
if info["texture_path"]: if info["texture_paths"]:
# TODO, this currently assumes that the uniform Sampler2D for name, path in info["texture_paths"].items():
# is named Texture, and that there's only one of them tid = self.get_texture_id(path)
tid = self.get_texture_id(info["texture_path"]) shader[name].value = tid
shader["Texture"].value = tid
self.set_shader_uniforms(shader) self.set_shader_uniforms(shader)
self.id_to_shader[sid] = shader self.id_to_shader[sid] = shader

View file

@ -50,7 +50,7 @@ class Mobject(Container):
"geom_shader_file": "", "geom_shader_file": "",
"frag_shader_file": "", "frag_shader_file": "",
"render_primative": moderngl.TRIANGLE_STRIP, "render_primative": moderngl.TRIANGLE_STRIP,
"texture_path": "", "texture_paths": None,
# Must match in attributes of vert shader # Must match in attributes of vert shader
"shader_dtype": [ "shader_dtype": [
('point', np.float32, (3,)), ('point', np.float32, (3,)),
@ -1215,8 +1215,8 @@ class Mobject(Container):
vert_file=self.vert_shader_file, vert_file=self.vert_shader_file,
geom_file=self.geom_shader_file, geom_file=self.geom_shader_file,
frag_file=self.frag_shader_file, frag_file=self.frag_shader_file,
texture_path=self.texture_path,
render_primative=self.render_primative, render_primative=self.render_primative,
texture_paths=self.texture_paths,
) )
def get_shader_data(self): def get_shader_data(self):

View file

@ -25,7 +25,7 @@ class ImageMobject(Mobject):
def __init__(self, filename, **kwargs): def __init__(self, filename, **kwargs):
path = get_full_raster_image_path(filename) path = get_full_raster_image_path(filename)
self.image = Image.open(path) self.image = Image.open(path)
self.texture_path = path self.texture_paths = {"Texture": path}
Mobject.__init__(self, **kwargs) Mobject.__init__(self, **kwargs)
def init_points(self): def init_points(self):

View file

@ -167,12 +167,15 @@ class TexturedSurface(ParametricSurface):
] ]
} }
def __init__(self, uv_surface, filename, **kwargs): def __init__(self, uv_surface, image_file, dark_image_file=None, **kwargs):
if not isinstance(uv_surface, ParametricSurface): if not isinstance(uv_surface, ParametricSurface):
raise Exception("uv_surface must be of type ParametricSurface") raise Exception("uv_surface must be of type ParametricSurface")
path = get_full_raster_image_path(filename) if dark_image_file is None:
self.image = Image.open(path) dark_image_file = image_file
self.texture_path = path self.texture_paths = {
"LightTexture": get_full_raster_image_path(image_file),
"DarkTexture": get_full_raster_image_path(dark_image_file),
}
self.uv_surface = uv_surface self.uv_surface = uv_surface
self.uv_func = uv_surface.uv_func self.uv_func = uv_surface.uv_func

View file

@ -827,14 +827,12 @@ class VMobject(Mobject):
vert_file=self.stroke_vert_shader_file, vert_file=self.stroke_vert_shader_file,
geom_file=self.stroke_geom_shader_file, geom_file=self.stroke_geom_shader_file,
frag_file=self.stroke_frag_shader_file, frag_file=self.stroke_frag_shader_file,
texture_path=self.texture_path,
render_primative=self.render_primative, render_primative=self.render_primative,
) )
fill_info = get_shader_info( fill_info = get_shader_info(
vert_file=self.fill_vert_shader_file, vert_file=self.fill_vert_shader_file,
geom_file=self.fill_geom_shader_file, geom_file=self.fill_geom_shader_file,
frag_file=self.fill_frag_shader_file, frag_file=self.fill_frag_shader_file,
texture_path=self.texture_path,
render_primative=self.render_primative, render_primative=self.render_primative,
) )

View file

@ -1,6 +1,7 @@
#version 330 #version 330
uniform sampler2D Texture; uniform sampler2D LightTexture;
uniform sampler2D DarkTexture;
uniform vec3 light_source_position; uniform vec3 light_source_position;
in vec3 xyz_coords; in vec3 xyz_coords;
@ -15,9 +16,17 @@ out vec4 frag_color;
#INSERT add_light.glsl #INSERT add_light.glsl
void main() { void main() {
vec4 im_color = texture(Texture, v_im_coords); vec4 light_color = texture(LightTexture, v_im_coords);
vec4 dark_color = texture(DarkTexture, v_im_coords);
float dp = dot(
normalize(light_source_position - xyz_coords),
normalize(v_normal)
);
float alpha = smoothstep(-0.1, 0.1, dp);
vec4 color = mix(dark_color, light_color, alpha);
frag_color = add_light( frag_color = add_light(
im_color, color,
xyz_coords, xyz_coords,
normalize(v_normal), normalize(v_normal),
light_source_position, light_source_position,

View file

@ -2,6 +2,7 @@ import os
import warnings import warnings
import re import re
import moderngl import moderngl
import json
from manimlib.constants import SHADER_DIR from manimlib.constants import SHADER_DIR
@ -13,11 +14,19 @@ from manimlib.constants import SHADER_DIR
SHADER_INFO_KEYS = [ SHADER_INFO_KEYS = [
# A structred array caring all of the points/color/lighting/etc. information
# needed for the shader.
"data", "data",
# Filename of vetex shader
"vert", "vert",
# Filename of geometry shader, if there is one
"geom", "geom",
# Filename of fragment shader
"frag", "frag",
"texture_path", # A dictionary mapping names (as they show up in)
# the shader to filepaths for textures.
"texture_paths",
# E.g. moderngl.TRIANGLE_STRIP
"render_primative", "render_primative",
] ]
@ -26,15 +35,18 @@ def get_shader_info(data=None,
vert_file=None, vert_file=None,
geom_file=None, geom_file=None,
frag_file=None, frag_file=None,
texture_path=None, render_primative=moderngl.TRIANGLE_STRIP,
render_primative=moderngl.TRIANGLE_STRIP): texture_paths=None,
):
return { return {
key: value key: value
for key, value in zip( for key, value in zip(
SHADER_INFO_KEYS, SHADER_INFO_KEYS,
[ [
data, vert_file, geom_file, frag_file, data,
texture_path, str(render_primative) vert_file, geom_file, frag_file,
texture_paths or {},
str(render_primative)
] ]
) )
} }
@ -52,32 +64,23 @@ def is_valid_shader_info(shader_info):
def shader_info_to_id(shader_info): def shader_info_to_id(shader_info):
# A unique id for a shader based on the # A unique id for a shader based on the
# files holding its code and texture # files holding its code and texture
return "|".join([ tuples = [
shader_info.get(key, "") or "" (key, shader_info[key])
for key in SHADER_INFO_KEYS[1:] for key in SHADER_INFO_KEYS[1:] # Skip data
]) ]
return json.dumps(tuples)
def shader_id_to_info(sid): def shader_id_to_info(sid):
return { result = dict(json.loads(sid))
key: (value or None) result["data"] = None
for key, value in zip( return result
SHADER_INFO_KEYS,
[None, *sid.split("|")]
)
}
def same_shader_type(info1, info2): def same_shader_type(info1, info2):
return all([ return all([
info1[key] == info2[key] info1[key] == info2[key]
for key in [ for key in SHADER_INFO_KEYS[1:] # Skip data
"vert",
"geom",
"frag",
"texture_path",
"render_primative",
]
]) ])