mirror of
https://github.com/3b1b/manim.git
synced 2025-07-30 21:44:19 +08:00
Update fill shader alpha blending, and simplify the fill canvas
This commit is contained in:
@ -287,24 +287,22 @@ class FillShaderWrapper(ShaderWrapper):
|
|||||||
return
|
return
|
||||||
|
|
||||||
original_fbo = self.ctx.fbo
|
original_fbo = self.ctx.fbo
|
||||||
texture_fbo, texture_vao, null_rgb = self.fill_canvas
|
texture_fbo, texture_vao = self.fill_canvas
|
||||||
|
|
||||||
texture_fbo.clear(*null_rgb, 0.0)
|
texture_fbo.clear()
|
||||||
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,
|
||||||
# Just take the max of the alphas, given the shenanigans
|
# The effect of blending with -a / (1 - a)
|
||||||
# with how alphas are being used to compute winding numbers
|
# should be to cancel out
|
||||||
gl.GL_ONE, gl.GL_ONE,
|
gl.GL_ONE_MINUS_DST_ALPHA, gl.GL_ONE,
|
||||||
)
|
)
|
||||||
gl.glBlendEquationSeparate(gl.GL_FUNC_ADD, gl.GL_MAX)
|
|
||||||
|
|
||||||
super().render()
|
super().render()
|
||||||
|
|
||||||
original_fbo.use()
|
original_fbo.use()
|
||||||
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)
|
|
||||||
|
|
||||||
texture_vao.render()
|
texture_vao.render()
|
||||||
|
|
||||||
|
@ -33,7 +33,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.99 * frag_color.a;
|
float a = 0.95 * 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;
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ def get_colormap_code(rgb_list: Sequence[float]) -> str:
|
|||||||
|
|
||||||
|
|
||||||
@lru_cache()
|
@lru_cache()
|
||||||
def get_fill_canvas(ctx: moderngl.Context) -> Tuple[Framebuffer, VertexArray, Tuple[float, float, float]]:
|
def get_fill_canvas(ctx: moderngl.Context) -> Tuple[Framebuffer, VertexArray]:
|
||||||
"""
|
"""
|
||||||
Because VMobjects with fill are rendered in a funny way, using
|
Because VMobjects with fill are rendered in a funny way, using
|
||||||
alpha blending to effectively compute the winding number around
|
alpha blending to effectively compute the winding number around
|
||||||
@ -123,26 +123,16 @@ def get_fill_canvas(ctx: moderngl.Context) -> Tuple[Framebuffer, VertexArray, Tu
|
|||||||
depth_texture = ctx.depth_texture(size=size)
|
depth_texture = ctx.depth_texture(size=size)
|
||||||
texture_fbo = ctx.framebuffer(texture, depth_texture)
|
texture_fbo = ctx.framebuffer(texture, depth_texture)
|
||||||
|
|
||||||
# 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 we don't want to overlap with any colors one might actually
|
|
||||||
# use. It should be negative enough to be distinguishable from
|
|
||||||
# ordinary colors with some margin, but the farther it's pulled back
|
|
||||||
# from zero the more it will be true that overlapping filled objects
|
|
||||||
# with transparency have an unnaturally bright composition.
|
|
||||||
null_rgb = (-0.25, -0.25, -0.25)
|
|
||||||
|
|
||||||
simple_program = ctx.program(
|
simple_program = ctx.program(
|
||||||
vertex_shader='''
|
vertex_shader='''
|
||||||
#version 330
|
#version 330
|
||||||
|
|
||||||
in vec2 texcoord;
|
in vec2 texcoord;
|
||||||
out vec2 v_textcoord;
|
out vec2 uv;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
gl_Position = vec4((2.0 * texcoord - 1.0), 0.0, 1.0);
|
gl_Position = vec4((2.0 * texcoord - 1.0), 0.0, 1.0);
|
||||||
v_textcoord = texcoord;
|
uv = texcoord;
|
||||||
}
|
}
|
||||||
''',
|
''',
|
||||||
fragment_shader='''
|
fragment_shader='''
|
||||||
@ -150,31 +140,24 @@ def get_fill_canvas(ctx: moderngl.Context) -> Tuple[Framebuffer, VertexArray, Tu
|
|||||||
|
|
||||||
uniform sampler2D Texture;
|
uniform sampler2D Texture;
|
||||||
uniform sampler2D DepthTexture;
|
uniform sampler2D DepthTexture;
|
||||||
uniform vec3 null_rgb;
|
|
||||||
|
|
||||||
in vec2 v_textcoord;
|
in vec2 uv;
|
||||||
out vec4 color;
|
out vec4 color;
|
||||||
|
|
||||||
const float MIN_DIST_TO_NULL = 0.2;
|
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
color = texture(Texture, v_textcoord);
|
color = texture(Texture, uv);
|
||||||
if(color.a == 0) discard;
|
if(color.a == 0) discard;
|
||||||
if(distance(color.rgb, null_rgb) < MIN_DIST_TO_NULL) discard;
|
|
||||||
|
|
||||||
// Un-blend from the null value
|
|
||||||
color.rgb -= (1 - color.a) * null_rgb;
|
|
||||||
// Counteract scaling in fill frag
|
// Counteract scaling in fill frag
|
||||||
color.a *= 1.01;
|
color.a *= 1.06;
|
||||||
|
|
||||||
gl_FragDepth = texture(DepthTexture, v_textcoord)[0];
|
gl_FragDepth = texture(DepthTexture, uv)[0];
|
||||||
}
|
}
|
||||||
''',
|
''',
|
||||||
)
|
)
|
||||||
|
|
||||||
simple_program['Texture'].value = get_texture_id(texture)
|
simple_program['Texture'].value = get_texture_id(texture)
|
||||||
simple_program['DepthTexture'].value = get_texture_id(depth_texture)
|
simple_program['DepthTexture'].value = get_texture_id(depth_texture)
|
||||||
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(
|
||||||
@ -183,4 +166,4 @@ def get_fill_canvas(ctx: moderngl.Context) -> Tuple[Framebuffer, VertexArray, Tu
|
|||||||
'texcoord',
|
'texcoord',
|
||||||
mode=moderngl.TRIANGLE_STRIP
|
mode=moderngl.TRIANGLE_STRIP
|
||||||
)
|
)
|
||||||
return (texture_fbo, fill_texture_vao, null_rgb)
|
return (texture_fbo, fill_texture_vao)
|
||||||
|
Reference in New Issue
Block a user