Clean up fill shader a bit

This commit is contained in:
Grant Sanderson 2023-01-27 08:26:54 -08:00
parent 746b52cda5
commit 1707958e0f
4 changed files with 41 additions and 26 deletions

View file

@ -13,7 +13,7 @@ from manimlib.utils.shaders import get_shader_code_from_file
from manimlib.utils.shaders import get_shader_program from manimlib.utils.shaders import get_shader_program
from manimlib.utils.shaders import image_path_to_texture from manimlib.utils.shaders import image_path_to_texture
from manimlib.utils.shaders import get_texture_id from manimlib.utils.shaders import get_texture_id
from manimlib.utils.shaders import get_fill_palette from manimlib.utils.shaders import get_fill_canvas
from manimlib.utils.shaders import release_texture from manimlib.utils.shaders import release_texture
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
@ -275,7 +275,7 @@ class FillShaderWrapper(ShaderWrapper):
**kwargs **kwargs
): ):
super().__init__(ctx, *args, **kwargs) super().__init__(ctx, *args, **kwargs)
self.texture_fbo, self.texture_vao = get_fill_palette(self.ctx) self.fill_canvas = get_fill_canvas(self.ctx)
def render(self): def render(self):
vao = self.vao vao = self.vao
@ -287,9 +287,10 @@ class FillShaderWrapper(ShaderWrapper):
return return
original_fbo = self.ctx.fbo original_fbo = self.ctx.fbo
texture_fbo, texture_vao, null_rgb = self.fill_canvas
self.texture_fbo.clear() texture_fbo.clear(*null_rgb, 0.0)
self.texture_fbo.use() texture_fbo.use()
gl.glBlendFuncSeparate( gl.glBlendFuncSeparate(
# Ordinary blending for colors # Ordinary blending for colors
gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA, gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA,
@ -306,6 +307,6 @@ class FillShaderWrapper(ShaderWrapper):
gl.glBlendFunc(gl.GL_ONE, gl.GL_ONE_MINUS_SRC_ALPHA) gl.glBlendFunc(gl.GL_ONE, gl.GL_ONE_MINUS_SRC_ALPHA)
gl.glBlendEquation(gl.GL_FUNC_ADD) gl.glBlendEquation(gl.GL_FUNC_ADD)
self.texture_vao.render(moderngl.TRIANGLE_STRIP) texture_vao.render(moderngl.TRIANGLE_STRIP)
gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA) gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)

View file

@ -32,7 +32,7 @@ void main() {
cap is to make sure the original fragment color can be recovered even after cap is to make sure the original fragment color can be recovered even after
blending with an (alpha = 1) color. blending with an (alpha = 1) color.
*/ */
float a = 0.98 * frag_color.a; float a = 0.99 * frag_color.a;
if(winding && orientation < 0) a = -a / (1 - a); if(winding && orientation < 0) a = -a / (1 - a);
frag_color.a = a; frag_color.a = a;

View file

@ -37,8 +37,6 @@ void emit_triangle(vec3 points[3], vec4 v_color[3]){
uv_coords = SIMPLE_QUADRATIC[i]; uv_coords = SIMPLE_QUADRATIC[i];
color = v_color[i]; color = v_color[i];
point = points[i]; point = points[i];
// Pure black will be used to discard fragments later
if(winding && color.rgb == vec3(0.0)) color.rgb += vec3(3.0 / 256);
gl_Position = get_gl_Position(points[i]); gl_Position = get_gl_Position(points[i]);
EmitVertex(); EmitVertex();
} }

View file

@ -103,10 +103,16 @@ def get_colormap_code(rgb_list: Sequence[float]) -> str:
@lru_cache() @lru_cache()
def get_fill_palette(ctx) -> Tuple[Framebuffer, VertexArray]: def get_fill_canvas(ctx) -> Tuple[Framebuffer, VertexArray, Tuple[float, float, float]]:
""" """
Creates a texture, loaded into a frame buffer, and a vao Because VMobjects with fill are rendered in a funny way, using
which can display that texture as a simple quad onto a screen. alpha blending to effectively compute the winding number around
each pixel, they need to be rendered to a separate texture, which
is then composited onto the ordinary frame buffer.
This returns a texture, loaded into a frame buffer, and a vao
which can display that texture as a simple quad onto a screen,
along with the rgb value which is meant to be discarded.
""" """
cam_config = get_customization()['camera_resolutions'] cam_config = get_customization()['camera_resolutions']
res_name = cam_config['default_resolution'] res_name = cam_config['default_resolution']
@ -118,6 +124,12 @@ def get_fill_palette(ctx) -> Tuple[Framebuffer, VertexArray]:
depth_buffer = ctx.depth_renderbuffer(size) # TODO, currently not used depth_buffer = ctx.depth_renderbuffer(size) # TODO, currently not used
texture_fbo = ctx.framebuffer(texture, depth_buffer) texture_fbo = ctx.framebuffer(texture, depth_buffer)
# We'll paint onto a canvas with initially negative rgbs, and
# discard any pixels remaining close to this value. This is
# because alphas are effectively being used for another purpose,
# and
null_rgb = (-0.25, -0.25, -0.25)
simple_program = ctx.program( simple_program = ctx.program(
vertex_shader=''' vertex_shader='''
#version 330 #version 330
@ -136,27 +148,30 @@ def get_fill_palette(ctx) -> Tuple[Framebuffer, VertexArray]:
uniform sampler2D Texture; uniform sampler2D Texture;
uniform float v_nudge; uniform float v_nudge;
uniform float h_nudge; uniform float h_nudge;
uniform vec3 null_rgb;
in vec2 v_textcoord; in vec2 v_textcoord;
out vec4 color; out vec4 color;
const float MIN_RGB = 3.0 / 256; const float MIN_DIST_TO_NULL = 0.2;
void main() { void main() {
// Apply poor man's anti-aliasing // Apply poor man's anti-aliasing
vec2 tc0 = v_textcoord + vec2(0, 0); vec2 nudges[4] = vec2[4](
vec2 tc1 = v_textcoord + vec2(0, h_nudge); vec2(0, 0),
vec2 tc2 = v_textcoord + vec2(v_nudge, 0); vec2(0, h_nudge),
vec2 tc3 = v_textcoord + vec2(v_nudge, h_nudge); vec2(v_nudge, 0),
color = vec2(v_nudge, h_nudge)
0.25 * texture(Texture, tc0) + );
0.25 * texture(Texture, tc1) + color = vec4(0.0);
0.25 * texture(Texture, tc2) + for(int i = 0; i < 4; i++){
0.25 * texture(Texture, tc3); color += 0.25 * texture(Texture, v_textcoord + nudges[i]);
if(abs(color.r) < MIN_RGB && abs(color.g) < MIN_RGB && abs(color.b) < MIN_RGB) }
discard; if(distance(color.rgb, null_rgb) < MIN_DIST_TO_NULL) discard;
// Counteract scaling in quadratic_bezier_frag
color = color / 0.98; // Un-blend from the null value
color.rgb -= (1 - color.a) * null_rgb;
//TODO, set gl_FragDepth; //TODO, set gl_FragDepth;
} }
''', ''',
@ -166,6 +181,7 @@ def get_fill_palette(ctx) -> Tuple[Framebuffer, VertexArray]:
# Half pixel width/height # Half pixel width/height
simple_program['h_nudge'].value = 0.5 / size[0] simple_program['h_nudge'].value = 0.5 / size[0]
simple_program['v_nudge'].value = 0.5 / size[1] simple_program['v_nudge'].value = 0.5 / size[1]
simple_program['null_rgb'].value = null_rgb
verts = np.array([[0, 0], [0, 1], [1, 0], [1, 1]]) verts = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
fill_texture_vao = ctx.simple_vertex_array( fill_texture_vao = ctx.simple_vertex_array(
@ -173,4 +189,4 @@ def get_fill_palette(ctx) -> Tuple[Framebuffer, VertexArray]:
ctx.buffer(verts.astype('f4').tobytes()), ctx.buffer(verts.astype('f4').tobytes()),
'texcoord', 'texcoord',
) )
return (texture_fbo, fill_texture_vao) return (texture_fbo, fill_texture_vao, null_rgb)