2020-02-17 12:14:40 -08:00
|
|
|
import os
|
|
|
|
import warnings
|
|
|
|
import re
|
|
|
|
import moderngl
|
|
|
|
|
|
|
|
from manimlib.constants import SHADER_DIR
|
|
|
|
|
|
|
|
# Mobjects that should be rendered with
|
|
|
|
# the same shader will be organized and
|
|
|
|
# clumped together based on keeping track
|
|
|
|
# of a dict holding all the relevant information
|
|
|
|
# to that shader
|
|
|
|
|
|
|
|
|
2020-06-26 23:05:25 -07:00
|
|
|
# TODO, this should all be treated as an object
|
|
|
|
# This object a shader program instead of the vert,
|
|
|
|
# geom and frag file names, and it should cache those
|
|
|
|
# programs in the way currently handled by Camera
|
|
|
|
# It should replace the Camera.get_shader method with
|
|
|
|
# its own get_shader_program method, which will take
|
|
|
|
# in the camera's perspective_uniforms.
|
|
|
|
|
|
|
|
|
2020-02-17 12:14:40 -08:00
|
|
|
SHADER_INFO_KEYS = [
|
2020-06-29 11:05:09 -07:00
|
|
|
# Vertex data for the shader (as structured array)
|
|
|
|
"vert_data",
|
|
|
|
# Index data (if applicable) for the shader
|
|
|
|
"index_data",
|
2020-06-26 19:29:34 -07:00
|
|
|
# List of variable names corresponding to inputs of vertex shader
|
|
|
|
"attributes",
|
2020-06-08 15:06:22 -07:00
|
|
|
# Filename of vetex shader
|
2020-02-17 12:14:40 -08:00
|
|
|
"vert",
|
2020-06-08 15:06:22 -07:00
|
|
|
# Filename of geometry shader, if there is one
|
2020-02-17 12:14:40 -08:00
|
|
|
"geom",
|
2020-06-08 15:06:22 -07:00
|
|
|
# Filename of fragment shader
|
2020-02-17 12:14:40 -08:00
|
|
|
"frag",
|
2020-06-14 19:01:04 -07:00
|
|
|
# A dictionary mapping names of uniform variables
|
|
|
|
"uniforms",
|
2020-06-08 15:06:22 -07:00
|
|
|
# A dictionary mapping names (as they show up in)
|
|
|
|
# the shader to filepaths for textures.
|
|
|
|
"texture_paths",
|
2020-06-14 17:41:47 -07:00
|
|
|
# Whether or not to apply depth test
|
|
|
|
"depth_test",
|
2020-06-08 15:06:22 -07:00
|
|
|
# E.g. moderngl.TRIANGLE_STRIP
|
2020-02-17 12:14:40 -08:00
|
|
|
"render_primative",
|
|
|
|
]
|
|
|
|
|
2020-06-29 11:05:09 -07:00
|
|
|
# Exclude data
|
|
|
|
SHADER_KEYS_FOR_ID = SHADER_INFO_KEYS[3:]
|
2020-06-08 15:57:12 -07:00
|
|
|
|
2020-02-17 12:14:40 -08:00
|
|
|
|
2020-06-29 11:05:09 -07:00
|
|
|
def get_shader_info(vert_data=None,
|
|
|
|
vert_indices=None,
|
2020-06-26 19:29:34 -07:00
|
|
|
attributes=None,
|
2020-02-17 12:14:40 -08:00
|
|
|
vert_file=None,
|
|
|
|
geom_file=None,
|
|
|
|
frag_file=None,
|
2020-06-14 19:01:04 -07:00
|
|
|
uniforms=None,
|
2020-06-08 15:06:22 -07:00
|
|
|
texture_paths=None,
|
2020-06-14 17:41:47 -07:00
|
|
|
depth_test=False,
|
|
|
|
render_primative=moderngl.TRIANGLE_STRIP,
|
2020-06-08 15:06:22 -07:00
|
|
|
):
|
2020-06-15 11:59:24 -07:00
|
|
|
result = {
|
2020-06-29 11:05:09 -07:00
|
|
|
"vert_data": vert_data,
|
|
|
|
"vert_indices": vert_indices,
|
2020-06-26 19:29:34 -07:00
|
|
|
"attributes": attributes,
|
2020-06-15 11:59:24 -07:00
|
|
|
"vert": vert_file,
|
|
|
|
"geom": geom_file,
|
|
|
|
"frag": frag_file,
|
|
|
|
"uniforms": uniforms or dict(),
|
|
|
|
"texture_paths": texture_paths or dict(),
|
|
|
|
"depth_test": depth_test,
|
|
|
|
"render_primative": str(render_primative),
|
2020-02-17 12:14:40 -08:00
|
|
|
}
|
2020-06-26 23:05:25 -07:00
|
|
|
result["id"] = create_shader_info_id(result)
|
2020-06-28 12:14:46 -07:00
|
|
|
result["prog_id"] = create_shader_info_program_id(result)
|
2020-06-15 11:59:24 -07:00
|
|
|
return result
|
2020-02-17 12:14:40 -08:00
|
|
|
|
|
|
|
|
|
|
|
def is_valid_shader_info(shader_info):
|
2020-06-29 11:05:09 -07:00
|
|
|
vert_data = shader_info["vert_data"]
|
2020-02-17 12:14:40 -08:00
|
|
|
return all([
|
2020-06-29 11:05:09 -07:00
|
|
|
vert_data is not None,
|
2020-02-17 12:14:40 -08:00
|
|
|
shader_info["vert"],
|
|
|
|
shader_info["frag"],
|
|
|
|
])
|
|
|
|
|
|
|
|
|
|
|
|
def shader_info_to_id(shader_info):
|
2020-06-26 23:05:25 -07:00
|
|
|
return shader_info["id"]
|
|
|
|
|
|
|
|
|
2020-06-28 12:14:46 -07:00
|
|
|
def shader_info_program_id(shader_info):
|
|
|
|
return shader_info["prog_id"]
|
|
|
|
|
|
|
|
|
2020-06-26 23:05:25 -07:00
|
|
|
def create_shader_info_id(shader_info):
|
2020-06-14 19:01:04 -07:00
|
|
|
# A unique id for a shader
|
2020-06-17 17:10:35 -07:00
|
|
|
return "|".join([str(shader_info[key]) for key in SHADER_KEYS_FOR_ID])
|
2020-02-17 12:14:40 -08:00
|
|
|
|
|
|
|
|
2020-06-27 00:01:45 -07:00
|
|
|
def refresh_shader_info_id(shader_info):
|
|
|
|
shader_info["id"] = create_shader_info_id(shader_info)
|
|
|
|
|
|
|
|
|
2020-06-28 12:14:46 -07:00
|
|
|
def create_shader_info_program_id(shader_info):
|
2020-06-26 23:05:25 -07:00
|
|
|
return "|".join([str(shader_info[key]) for key in ["vert", "geom", "frag"]])
|
|
|
|
|
|
|
|
|
2020-02-17 12:14:40 -08:00
|
|
|
def same_shader_type(info1, info2):
|
2020-06-26 23:05:25 -07:00
|
|
|
return info1["id"] == info2["id"]
|
2020-02-17 12:14:40 -08:00
|
|
|
|
|
|
|
|
2020-06-14 19:01:04 -07:00
|
|
|
def shader_info_to_program_code(shader_info):
|
|
|
|
return {
|
|
|
|
"vertex_shader": get_shader_code_from_file(shader_info["vert"]),
|
|
|
|
"geometry_shader": get_shader_code_from_file(shader_info["geom"]),
|
|
|
|
"fragment_shader": get_shader_code_from_file(shader_info["frag"]),
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-02-17 12:14:40 -08:00
|
|
|
def get_shader_code_from_file(filename):
|
|
|
|
if not filename:
|
|
|
|
return None
|
|
|
|
|
|
|
|
filepath = os.path.join(SHADER_DIR, filename)
|
|
|
|
if not os.path.exists(filepath):
|
|
|
|
warnings.warn(f"No file at {filepath}")
|
|
|
|
return
|
|
|
|
|
|
|
|
with open(filepath, "r") as f:
|
|
|
|
result = f.read()
|
|
|
|
|
|
|
|
# To share functionality between shaders, some functions are read in
|
|
|
|
# from other files an inserted into the relevant strings before
|
|
|
|
# passing to ctx.program for compiling
|
|
|
|
# Replace "#INSERT " lines with relevant code
|
|
|
|
insertions = re.findall(r"^#INSERT .*\.glsl$", result, flags=re.MULTILINE)
|
|
|
|
for line in insertions:
|
|
|
|
inserted_code = get_shader_code_from_file(line.replace("#INSERT ", ""))
|
|
|
|
result = result.replace(line, inserted_code)
|
|
|
|
return result
|