mirror of
https://github.com/ManimCommunity/manim.git
synced 2026-06-22 10:01:47 +00:00
Working Shading in 3D many many tries
This commit is contained in:
parent
388604b3f7
commit
389c1a1587
4 changed files with 98 additions and 28 deletions
|
|
@ -67,6 +67,7 @@ bounding_box:
|
|||
"""
|
||||
|
||||
|
||||
# TODO: Move into GLVMobjectManager
|
||||
def get_triangulation(self, normal_vector=None):
|
||||
# Figure out how to triangulate the interior to know
|
||||
# how to send the points as to the vertex shader.
|
||||
|
|
@ -160,6 +161,7 @@ def prepare_array(values: np.ndarray, desired_length: int):
|
|||
return np.array(rgbas)
|
||||
|
||||
|
||||
# TODO: Move into GLVMobjectManager
|
||||
def compute_bounding_box(mob):
|
||||
all_points = np.vstack(
|
||||
[
|
||||
|
|
@ -221,12 +223,25 @@ class OpenGLRenderer(Renderer):
|
|||
logger.debug("Initializing OpenGL context and framebuffers")
|
||||
self.ctx = gl.create_context()
|
||||
|
||||
self.stencil_texture = self.ctx.texture((self.pixel_width, self.pixel_height), components=4,dtype='f1')
|
||||
self.target_fbo = self.ctx.framebuffer(
|
||||
color_attachments=[self.ctx.renderbuffer((self.pixel_width, self.pixel_height), components=4,samples=4,dtype='f1')]
|
||||
,depth_attachment=self.ctx.depth_texture((self.pixel_width, self.pixel_height), samples=4)
|
||||
# Those are the actual buffers that are used for rendering
|
||||
self.stencil_texture = self.ctx.texture((self.pixel_width, self.pixel_height), components=1, samples=0, dtype='f1')
|
||||
self.stencil_buffer = self.ctx.renderbuffer((self.pixel_width, self.pixel_height), components=1, samples=0, dtype='f1')
|
||||
self.color_buffer = self.ctx.renderbuffer((self.pixel_width, self.pixel_height), components=4,samples=0,dtype='f1')
|
||||
|
||||
# Here we create different fbos that can be reused which are basically just targets to use for rendering and copy
|
||||
# render_target_fbo is used for rendering it can write to color and stencil
|
||||
self.render_target_fbo = self.ctx.framebuffer(
|
||||
color_attachments=[ self.color_buffer,self.stencil_buffer]
|
||||
,depth_attachment=self.ctx.depth_renderbuffer((self.pixel_width, self.pixel_height), samples=0)
|
||||
)
|
||||
|
||||
# this is used as source for stencil copy
|
||||
self.stencil_buffer_fbo = self.ctx.framebuffer(color_attachments=[self.stencil_buffer])
|
||||
# this is used as destination for stencil copy
|
||||
self.stencil_texture_fbo = self.ctx.framebuffer(color_attachments=[self.stencil_texture])
|
||||
# this is used as source for copying color to the output
|
||||
self.color_buffer_fbo = self.ctx.framebuffer(color_attachments=[self.color_buffer])
|
||||
|
||||
self.output_fbo = self.ctx.framebuffer(
|
||||
color_attachments=[
|
||||
self.ctx.renderbuffer(
|
||||
|
|
@ -264,6 +279,7 @@ class OpenGLRenderer(Renderer):
|
|||
ProgramManager.write_uniforms(self.vmobject_fill_program, uniforms)
|
||||
ProgramManager.write_uniforms(self.vmobject_stroke_program, uniforms)
|
||||
|
||||
# TODO: Move into GLVMobjectManager
|
||||
def get_stroke_shader_data(self, mob: OpenGLVMobject) -> np.ndarray:
|
||||
if not isinstance(mob.renderer_data, GLRenderData):
|
||||
raise TypeError()
|
||||
|
|
@ -282,6 +298,7 @@ class OpenGLRenderer(Renderer):
|
|||
|
||||
return stroke_data
|
||||
|
||||
# TODO: Move into GLVMobjectManager
|
||||
def get_fill_shader_data(self, mob: OpenGLVMobject) -> np.ndarray:
|
||||
if not isinstance(mob.renderer_data, GLRenderData):
|
||||
raise TypeError()
|
||||
|
|
@ -294,17 +311,13 @@ class OpenGLRenderer(Renderer):
|
|||
fill_data["vert_index"] = np.reshape(range(len(mob.points)), (-1, 1))
|
||||
return fill_data
|
||||
|
||||
def copy_frame_to_stencil(self):
|
||||
self.stencil_texture = self.target_fbo.depth_attachment
|
||||
|
||||
def pre_render(self, camera):
|
||||
self.init_camera(camera=camera)
|
||||
self.target_fbo.use()
|
||||
self.target_fbo.clear(*self.background_color)
|
||||
self.copy_frame_to_stencil()
|
||||
self.render_target_fbo.use()
|
||||
self.render_target_fbo.clear(*self.background_color)
|
||||
|
||||
def post_render(self):
|
||||
self.ctx.copy_framebuffer(self.output_fbo, self.target_fbo)
|
||||
self.ctx.copy_framebuffer(self.output_fbo, self.color_buffer_fbo)
|
||||
|
||||
def render_program(self, prog, data, indices = None):
|
||||
vbo = self.ctx.buffer(data.tobytes())
|
||||
|
|
@ -325,9 +338,11 @@ class OpenGLRenderer(Renderer):
|
|||
vao.release()
|
||||
|
||||
def render_vmobject(self, mob: OpenGLVMobject) -> None: #type: ignore
|
||||
self.stencil_buffer_fbo.use()
|
||||
self.stencil_buffer_fbo.clear()
|
||||
self.render_target_fbo.use()
|
||||
# Setting camera uniforms
|
||||
counter = 0
|
||||
num_mobs = len(mob.family_members_with_points())
|
||||
|
||||
for sub in mob.family_members_with_points():
|
||||
if sub.renderer_data is None:
|
||||
# Initialize
|
||||
|
|
@ -357,18 +372,33 @@ class OpenGLRenderer(Renderer):
|
|||
self.ctx.enable(gl.DEPTH_TEST) #type: ignore
|
||||
else:
|
||||
self.ctx.disable(gl.DEPTH_TEST) #type: ignore
|
||||
|
||||
|
||||
num_mobs = len(mob.family_members_with_points())
|
||||
for counter,sub in enumerate(mob.family_members_with_points()):
|
||||
if not isinstance(sub.renderer_data, GLRenderData):
|
||||
return
|
||||
uniforms = GLVMobjectManager.read_uniforms(sub)
|
||||
uniforms['z_shift'] = counter/9
|
||||
# uniforms['z_shift'] = counter/9
|
||||
uniforms['index'] = (counter + 1)/num_mobs
|
||||
self.ctx.copy_framebuffer(self.stencil_texture_fbo,self.stencil_buffer_fbo)
|
||||
self.stencil_texture.use(0)
|
||||
self.vmobject_fill_program['stencil_texture'] = 0
|
||||
if sub.has_fill():
|
||||
ProgramManager.write_uniforms(self.vmobject_fill_program, uniforms)
|
||||
self.render_program(
|
||||
self.vmobject_fill_program, self.get_fill_shader_data(sub), sub.renderer_data.vert_indices
|
||||
)
|
||||
uniforms["z_shift"] -= 1/20
|
||||
|
||||
self.copy_frame_to_stencil()
|
||||
self.stencil_texture.use(1)
|
||||
self.vmobject_stroke_program['stencil_texture'] = 1
|
||||
for counter,sub in enumerate(mob.family_members_with_points()):
|
||||
if not isinstance(sub.renderer_data, GLRenderData):
|
||||
return
|
||||
uniforms = GLVMobjectManager.read_uniforms(sub)
|
||||
uniforms['index'] = (counter + 1)/num_mobs
|
||||
# uniforms['z_shift'] = counter/9 + 1/20
|
||||
self.ctx.copy_framebuffer(self.stencil_texture_fbo,self.stencil_buffer_fbo)
|
||||
self.stencil_texture.use(0)
|
||||
self.vmobject_stroke_program['stencil_texture'] = 0
|
||||
if sub.has_stroke():
|
||||
ProgramManager.write_uniforms(self.vmobject_stroke_program, uniforms)
|
||||
self.render_program(
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ vec4 get_gl_Position(vec3 point)
|
|||
// TODO, what's the better way to do this?
|
||||
// This is to keep vertices too far out of frame from getting cut.
|
||||
// TODO This will be done by the clipping plane in the future with the transformation matrix
|
||||
result.z -= z_shift;
|
||||
result.z += z_shift;
|
||||
result.z *= (1.0 / 100.0);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
#version 330
|
||||
|
||||
#include ../include/camera_uniform_declarations.glsl
|
||||
uniform vec2 pixel_shape;
|
||||
uniform float index;
|
||||
|
||||
in vec4 color;
|
||||
in float fill_all; // Either 0 or 1e
|
||||
|
|
@ -10,7 +12,10 @@ in float orientation;
|
|||
in vec2 uv_coords;
|
||||
in float bezier_degree;
|
||||
|
||||
out vec4 frag_color;
|
||||
uniform sampler2D stencil_texture;
|
||||
|
||||
layout(location = 0) out vec4 frag_color;
|
||||
layout(location = 1) out float stencil_value;
|
||||
|
||||
#define ANTI_ALIASING
|
||||
|
||||
|
|
@ -31,7 +36,23 @@ float sdf(){
|
|||
|
||||
|
||||
void main() {
|
||||
gl_FragDepth = gl_FragCoord.z;
|
||||
if (color.a == 0) discard;
|
||||
stencil_value = index;
|
||||
float previous_index =
|
||||
texture2D(stencil_texture, vec2(gl_FragCoord.x / pixel_shape.x, gl_FragCoord.y / pixel_shape.y)).r;
|
||||
|
||||
// Check if we are behind another fill and if yes discard the current fragment
|
||||
if (previous_index > index)
|
||||
{
|
||||
discard;
|
||||
}
|
||||
// If we are on top of a previously drawn fill we need to shift ourselves forward by the index amount to compensate
|
||||
// for different shifting and avoid z_fighting
|
||||
if (previous_index < index && previous_index != 0)
|
||||
{
|
||||
gl_FragDepth = gl_FragCoord.z - index / 1000.0;
|
||||
}
|
||||
frag_color = color;
|
||||
if (fill_all == 1.0) return;
|
||||
#ifdef ANTI_ALIASING
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include ../include/camera_uniform_declarations.glsl
|
||||
uniform vec2 pixel_shape;
|
||||
uniform float index;
|
||||
|
||||
in vec2 uv_coords;
|
||||
in vec2 uv_b2;
|
||||
|
|
@ -21,8 +22,8 @@ uniform sampler2D stencil_texture;
|
|||
|
||||
in float bezier_degree;
|
||||
|
||||
out vec4 frag_color;
|
||||
|
||||
layout(location = 0) out vec4 frag_color;
|
||||
layout(location = 1) out float stencil_value;
|
||||
|
||||
float cross2d(vec2 v, vec2 w){
|
||||
return v.x * w.y - w.x * v.y;
|
||||
|
|
@ -86,21 +87,39 @@ float modify_distance_for_endpoints(vec2 p, float dist, float t){
|
|||
|
||||
|
||||
void main() {
|
||||
// Use the default value as standard output
|
||||
gl_FragDepth = gl_FragCoord.z;
|
||||
// Get the previous index that was written to this fragment
|
||||
float previous_index =
|
||||
texture2D(stencil_texture, vec2(gl_FragCoord.x / pixel_shape.x, gl_FragCoord.y / pixel_shape.y)).r;
|
||||
// If the index is the same that means we are overlapping with the fill and crossing through so we push the stroke
|
||||
// forward a tiny bit
|
||||
if (previous_index < index && previous_index != 0)
|
||||
{
|
||||
gl_FragDepth = gl_FragCoord.z - 1.7 * index / 1000.0;
|
||||
}
|
||||
if (previous_index == index)
|
||||
{
|
||||
gl_FragDepth = gl_FragCoord.z - index / 1000.0;
|
||||
}
|
||||
// If the stroke is overlapping with a shape that is of higher index that means it is behind another mobject on the
|
||||
// same plane so we discard the fragment
|
||||
if (previous_index > index)
|
||||
{
|
||||
discard;
|
||||
}
|
||||
stencil_value = index;
|
||||
if (uv_stroke_width == 0)
|
||||
discard;
|
||||
float dist_to_curve = min_dist_to_curve(uv_coords, uv_b2, bezier_degree);
|
||||
// An sdf for the region around the curve we wish to color.
|
||||
float signed_dist = abs(dist_to_curve) - 0.5 * uv_stroke_width;
|
||||
|
||||
frag_color =
|
||||
// TODO: The incoming texture should be the depth buffer, discard the pixel on any value this needs to be
|
||||
// rewritten
|
||||
vec4(texture2D(stencil_texture, vec2(gl_FragCoord.x / pixel_shape.x, gl_FragCoord.y / pixel_shape.y)).a, 0, 0,
|
||||
1) +
|
||||
color / 1000;
|
||||
frag_color = color;
|
||||
frag_color.a *= smoothstep(0.5, -0.5, signed_dist / uv_anti_alias_width);
|
||||
if (frag_color.a <= 0.0)
|
||||
{
|
||||
discard;
|
||||
}
|
||||
// stencil_value = 1;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue