Working Shading in 3D many many tries

This commit is contained in:
Tristan Schulz 2023-09-12 18:21:24 +02:00
commit 389c1a1587
4 changed files with 98 additions and 28 deletions

View file

@ -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(

View file

@ -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);
}
}

View file

@ -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

View file

@ -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;
}