diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2019-12-05 18:08:52 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2019-12-05 18:36:06 +0300 |
commit | d40579c62b40e2ad7d30ae4196169c3328610d41 (patch) | |
tree | 1aeeb85fa19408d6836ecd8f03e1d91eefd39ad5 /source/blender/draw/engines | |
parent | 95ca3f6536f1b756a0c87578f8d9d757ba9cd3a4 (diff) |
Overlay Engine: Fix bone outline antialiasing
Diffstat (limited to 'source/blender/draw/engines')
8 files changed, 103 insertions, 120 deletions
diff --git a/source/blender/draw/engines/overlay/overlay_armature.c b/source/blender/draw/engines/overlay/overlay_armature.c index 556cab39b30..4749901470f 100644 --- a/source/blender/draw/engines/overlay/overlay_armature.c +++ b/source/blender/draw/engines/overlay/overlay_armature.c @@ -204,12 +204,6 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata) DRW_shgroup_uniform_float_copy(grp, "alpha", pd->armature.transparent ? 0.4f : 1.0f); cb->point_solid = BUF_INSTANCE(grp, format, DRW_cache_bone_point_get()); - sh = OVERLAY_shader_armature_sphere(true); - grp = DRW_shgroup_create(sh, armature_ps); - DRW_shgroup_state_disable(grp, DRW_STATE_CULL_BACK); - DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo); - cb->point_outline = BUF_INSTANCE(grp, format, DRW_cache_bone_point_wire_outline_get()); - sh = OVERLAY_shader_armature_shape(false); cb->custom_solid = grp = DRW_shgroup_create(sh, armature_ps); DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo); @@ -217,9 +211,15 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata) cb->box_solid = BUF_INSTANCE(grp, format, DRW_cache_bone_box_get()); cb->octa_solid = BUF_INSTANCE(grp, format, DRW_cache_bone_octahedral_get()); + sh = OVERLAY_shader_armature_sphere(true); + grp = DRW_shgroup_create(sh, armature_ps); + DRW_shgroup_state_disable(grp, DRW_STATE_BLEND_ALPHA); + DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo); + cb->point_outline = BUF_INSTANCE(grp, format, DRW_cache_bone_point_wire_outline_get()); + sh = OVERLAY_shader_armature_shape(true); cb->custom_outline = grp = DRW_shgroup_create(sh, armature_ps); - DRW_shgroup_state_disable(grp, DRW_STATE_CULL_BACK); + DRW_shgroup_state_disable(grp, DRW_STATE_BLEND_ALPHA); DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo); cb->box_outline = BUF_INSTANCE(grp, format, DRW_cache_bone_box_wire_get()); cb->octa_outline = BUF_INSTANCE(grp, format, DRW_cache_bone_octahedral_wire_get()); @@ -230,6 +230,7 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata) sh = OVERLAY_shader_armature_degrees_of_freedom(); grp = DRW_shgroup_create(sh, armature_ps); DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_state_disable(grp, DRW_STATE_BLEND_ALPHA); cb->dof_lines = BUF_INSTANCE(grp, format, DRW_cache_bone_dof_lines_get()); grp = DRW_shgroup_create(sh, psl->armature_transp_ps); @@ -258,7 +259,7 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata) sh = OVERLAY_shader_armature_envelope(true); grp = DRW_shgroup_create(sh, armature_ps); - DRW_shgroup_state_disable(grp, DRW_STATE_CULL_BACK); + DRW_shgroup_state_disable(grp, DRW_STATE_BLEND_ALPHA); DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo); cb->envelope_outline = BUF_INSTANCE(grp, format, DRW_cache_bone_envelope_outline_get()); @@ -276,6 +277,8 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata) sh = OVERLAY_shader_armature_wire(); grp = DRW_shgroup_create(sh, armature_ps); + DRW_shgroup_state_disable(grp, DRW_STATE_BLEND_ALPHA); + DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo); cb->wire = BUF_LINE(grp, format); } } @@ -2341,12 +2344,9 @@ void OVERLAY_pose_draw(OVERLAY_Data *vedata) DRW_draw_pass(psl->armature_bone_select_ps); if (DRW_state_is_fbo()) { - GPU_framebuffer_bind(fbl->overlay_line_in_front_fb); - GPU_framebuffer_clear_depth(fbl->overlay_line_in_front_fb, 1.0f); + GPU_framebuffer_bind(fbl->overlay_line_fb); } - /* Selection still works because we are drawing only the pose bones in this case. */ - DRW_draw_pass(psl->armature_ps[1]); } }
\ No newline at end of file diff --git a/source/blender/draw/engines/overlay/overlay_shader.c b/source/blender/draw/engines/overlay/overlay_shader.c index be55d6c07c7..7ef8ca88e19 100644 --- a/source/blender/draw/engines/overlay/overlay_shader.c +++ b/source/blender/draw/engines/overlay/overlay_shader.c @@ -44,6 +44,7 @@ extern char datatoc_armature_sphere_solid_frag_glsl[]; extern char datatoc_armature_sphere_solid_vert_glsl[]; extern char datatoc_armature_stick_frag_glsl[]; extern char datatoc_armature_stick_vert_glsl[]; +extern char datatoc_armature_wire_frag_glsl[]; extern char datatoc_armature_wire_vert_glsl[]; extern char datatoc_depth_only_vert_glsl[]; extern char datatoc_edit_curve_handle_geom_glsl[]; @@ -296,7 +297,7 @@ GPUShader *OVERLAY_shader_armature_sphere(bool use_outline) NULL}, .frag = (const char *[]){extensions, datatoc_common_view_lib_glsl, - datatoc_gpu_shader_flat_color_frag_glsl, + datatoc_armature_wire_frag_glsl, NULL}, .defs = (const char *[]){sh_cfg->def, NULL}, }); @@ -334,7 +335,8 @@ GPUShader *OVERLAY_shader_armature_shape(bool use_outline) datatoc_common_view_lib_glsl, datatoc_armature_shape_outline_geom_glsl, NULL}, - .frag = (const char *[]){datatoc_gpu_shader_flat_color_frag_glsl, NULL}, + .frag = + (const char *[]){datatoc_common_view_lib_glsl, datatoc_armature_wire_frag_glsl, NULL}, .defs = (const char *[]){sh_cfg->def, NULL}, }); } @@ -363,7 +365,8 @@ GPUShader *OVERLAY_shader_armature_envelope(bool use_outline) datatoc_common_view_lib_glsl, datatoc_armature_envelope_outline_vert_glsl, NULL}, - .frag = (const char *[]){datatoc_gpu_shader_flat_color_frag_glsl, NULL}, + .frag = + (const char *[]){datatoc_common_view_lib_glsl, datatoc_armature_wire_frag_glsl, NULL}, .defs = (const char *[]){sh_cfg->def, NULL}, }); } @@ -407,10 +410,12 @@ GPUShader *OVERLAY_shader_armature_degrees_of_freedom(void) if (!sh_data->armature_dof) { sh_data->armature_dof = GPU_shader_create_from_arrays({ .vert = (const char *[]){sh_cfg->lib, + datatoc_common_globals_lib_glsl, datatoc_common_view_lib_glsl, datatoc_armature_dof_vert_glsl, NULL}, - .frag = (const char *[]){datatoc_gpu_shader_flat_color_frag_glsl, NULL}, + .frag = + (const char *[]){datatoc_common_view_lib_glsl, datatoc_armature_wire_frag_glsl, NULL}, .defs = (const char *[]){sh_cfg->def, NULL}, }); } @@ -425,10 +430,12 @@ GPUShader *OVERLAY_shader_armature_wire(void) if (!sh_data->armature_wire) { sh_data->armature_wire = GPU_shader_create_from_arrays({ .vert = (const char *[]){sh_cfg->lib, + datatoc_common_globals_lib_glsl, datatoc_common_view_lib_glsl, datatoc_armature_wire_vert_glsl, NULL}, - .frag = (const char *[]){datatoc_gpu_shader_flat_color_frag_glsl, NULL}, + .frag = + (const char *[]){datatoc_common_view_lib_glsl, datatoc_armature_wire_frag_glsl, NULL}, .defs = (const char *[]){sh_cfg->def, NULL}, }); } diff --git a/source/blender/draw/engines/overlay/shaders/armature_dof_vert.glsl b/source/blender/draw/engines/overlay/shaders/armature_dof_vert.glsl index 371229f23ab..b15554bbb6a 100644 --- a/source/blender/draw/engines/overlay/shaders/armature_dof_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/armature_dof_vert.glsl @@ -8,6 +8,8 @@ in vec4 color; in mat4 inst_obmat; flat out vec4 finalColor; +flat out vec2 edgeStart; +noperspective out vec2 edgePos; vec3 sphere_project(float ax, float az) { @@ -28,6 +30,14 @@ void main() vec3 final_pos = sphere_project(pos.x * abs((pos.x > 0.0) ? amax.x : amin.x), pos.y * abs((pos.y > 0.0) ? amax.y : amin.y)); - gl_Position = ViewProjectionMatrix * (model_mat * vec4(final_pos, 1.0)); + + vec3 world_pos = (model_mat * vec4(final_pos, 1.0)).xyz; + gl_Position = point_world_to_ndc(world_pos); finalColor = color; + + edgeStart = edgePos = ((gl_Position.xy / gl_Position.w) * 0.5 + 0.5) * sizeViewport.xy; + +#ifdef USE_WORLD_CLIP_PLANES + world_clip_planes_calc_clip_distance(world_pos); +#endif } diff --git a/source/blender/draw/engines/overlay/shaders/armature_envelope_outline_vert.glsl b/source/blender/draw/engines/overlay/shaders/armature_envelope_outline_vert.glsl index e3cc8d582d8..2260b2d3fa6 100644 --- a/source/blender/draw/engines/overlay/shaders/armature_envelope_outline_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/armature_envelope_outline_vert.glsl @@ -12,6 +12,8 @@ in vec4 outlineColorSize; in vec3 xAxis; flat out vec4 finalColor; +flat out vec2 edgeStart; +noperspective out vec2 edgePos; /* project to screen space */ vec2 proj(vec4 pos) @@ -132,33 +134,27 @@ void main() vec3 wpos2 = get_outline_point( pos2, sph_near, sph_far, mat_near, mat_far, z_ofs_near, z_ofs_far, b); - vec4 pos_4d = vec4(wpos1, 1.0); #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance(pos_4d.xyz); + world_clip_planes_calc_clip_distance(wpos1); #endif - vec4 V = ViewMatrix * pos_4d; - float pres_fac = (ProjectionMatrix[3][3] == 0.0) ? abs(V.z) : 1.0; + vec4 p0 = point_world_to_ndc(wpos0); + vec4 p1 = point_world_to_ndc(wpos1); + vec4 p2 = point_world_to_ndc(wpos2); - vec4 p0 = ViewProjectionMatrix * vec4(wpos0, 1.0); - vec4 p1 = ProjectionMatrix * V; - vec4 p2 = ViewProjectionMatrix * vec4(wpos2, 1.0); + gl_Position = p1; /* compute position from 3 vertex because the change in direction * can happen very quicky and lead to very thin edges. */ vec2 ss0 = proj(p0); vec2 ss1 = proj(p1); vec2 ss2 = proj(p2); - vec2 edge_dir = compute_dir(ss0, ss1, ss2); + vec2 ofs_dir = compute_dir(ss0, ss1, ss2); - float line_thickness = 2.0 * sizePixel; - bool outer = ((gl_VertexID & 1) == 1); - vec2 t = outlineColorSize.w * line_thickness * sizeViewportInv.xy; - t *= pres_fac; - t = (outer) ? t : vec2(0.0); + /* Offset away from the center to avoid overlap with solid shape. */ + gl_Position.xy += ofs_dir * sizeViewportInv.xy * gl_Position.w; - gl_Position = p1; - gl_Position.xy += t * edge_dir; + edgeStart = edgePos = proj(gl_Position); finalColor = vec4(outlineColorSize.rgb, 1.0); } diff --git a/source/blender/draw/engines/overlay/shaders/armature_shape_outline_geom.glsl b/source/blender/draw/engines/overlay/shaders/armature_shape_outline_geom.glsl index bd05c7f3532..ffc941149c7 100644 --- a/source/blender/draw/engines/overlay/shaders/armature_shape_outline_geom.glsl +++ b/source/blender/draw/engines/overlay/shaders/armature_shape_outline_geom.glsl @@ -1,6 +1,6 @@ layout(lines_adjacency) in; -layout(triangle_strip, max_vertices = 6) out; +layout(line_strip, max_vertices = 2) out; in vec4 pPos[]; in vec3 vPos[]; @@ -9,55 +9,8 @@ in vec2 ssNor[]; in vec4 vColSize[]; flat out vec4 finalColor; - -vec2 compute_dir(vec2 v0, vec2 v1) -{ - vec2 dir = normalize(v1 - v0); - dir = vec2(-dir.y, dir.x); - return dir; -} - -void emit_edge(vec2 edge_dir, vec2 hidden_dir, vec2 thick, bool is_persp) -{ - float fac = dot(-hidden_dir, edge_dir); - edge_dir *= (fac < 0.0) ? -1.0 : 1.0; - - vec2 t = thick * (is_persp ? abs(vPos[1].z) : 1.0); - gl_Position = pPos[1]; -#ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_set_clip_distance(gl_in[1].gl_ClipDistance); -#endif - EmitVertex(); - gl_Position.xy += t * edge_dir; -#ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_set_clip_distance(gl_in[1].gl_ClipDistance); -#endif - EmitVertex(); - - t = thick * (is_persp ? abs(vPos[2].z) : 1.0); - gl_Position = pPos[2]; -#ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_set_clip_distance(gl_in[2].gl_ClipDistance); -#endif - EmitVertex(); - gl_Position.xy += t * edge_dir; -#ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_set_clip_distance(gl_in[2].gl_ClipDistance); -#endif - EmitVertex(); -} - -void emit_corner(const int e, vec2 thick, bool is_persp) -{ - vec2 corner_dir = ssNor[e]; - vec2 t = thick * (is_persp ? abs(vPos[e].z) : 1.0); - - gl_Position = pPos[e] + vec4(t * corner_dir, 0.0, 0.0); -#ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_set_clip_distance(gl_in[e].gl_ClipDistance); -#endif - EmitVertex(); -} +flat out vec2 edgeStart; +noperspective out vec2 edgePos; void main(void) { @@ -91,9 +44,8 @@ void main(void) return; } - float line_thickness = 2.0 * sizePixel; - vec2 thick = vColSize[0].w * (line_thickness * sizeViewportInv.xy); - vec2 edge_dir = compute_dir(ssPos[1], ssPos[2]); + vec2 perp = normalize(ssPos[2] - ssPos[1]); + vec2 edge_dir = vec2(-perp.y, perp.x); vec2 hidden_point; /* Take the farthest point to compute edge direction @@ -109,8 +61,30 @@ void main(void) } vec2 hidden_dir = normalize(hidden_point - ssPos[1]); - emit_corner(1, thick, is_persp); - emit_edge(edge_dir, hidden_dir, thick, is_persp); - emit_corner(2, thick, is_persp); + float fac = dot(-hidden_dir, edge_dir); + edge_dir *= (fac < 0.0) ? -1.0 : 1.0; + + gl_Position = pPos[1]; + /* Offset away from the center to avoid overlap with solid shape. */ + gl_Position.xy += (edge_dir - perp) * sizeViewportInv.xy * gl_Position.w; + /* Improve AA bleeding inside bone silhouette. */ + gl_Position.z -= 1e-4; + edgeStart = edgePos = ((gl_Position.xy / gl_Position.w) * 0.5 + 0.5) * sizeViewport.xy; +#ifdef USE_WORLD_CLIP_PLANES + world_clip_planes_set_clip_distance(gl_in[1].gl_ClipDistance); +#endif + EmitVertex(); + + gl_Position = pPos[2]; + /* Offset away from the center to avoid overlap with solid shape. */ + gl_Position.xy += (edge_dir + perp) * sizeViewportInv.xy * gl_Position.w; + /* Improve AA bleeding inside bone silhouette. */ + gl_Position.z -= 1e-4; + edgeStart = edgePos = ((gl_Position.xy / gl_Position.w) * 0.5 + 0.5) * sizeViewport.xy; +#ifdef USE_WORLD_CLIP_PLANES + world_clip_planes_set_clip_distance(gl_in[2].gl_ClipDistance); +#endif + EmitVertex(); + EndPrimitive(); } diff --git a/source/blender/draw/engines/overlay/shaders/armature_sphere_outline_vert.glsl b/source/blender/draw/engines/overlay/shaders/armature_sphere_outline_vert.glsl index 9dd4c444116..934485359b3 100644 --- a/source/blender/draw/engines/overlay/shaders/armature_sphere_outline_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/armature_sphere_outline_vert.glsl @@ -1,12 +1,13 @@ /* ---- Instantiated Attrs ---- */ -in vec2 pos0; -in vec2 pos1; +in vec2 pos; /* ---- Per instance Attrs ---- */ in mat4 inst_obmat; flat out vec4 finalColor; +flat out vec2 edgeStart; +noperspective out vec2 edgePos; /* project to screen space */ vec2 proj(vec4 pos) @@ -14,18 +15,6 @@ vec2 proj(vec4 pos) return (0.5 * (pos.xy / pos.w) + 0.5) * sizeViewport.xy; } -vec2 compute_dir(vec2 v0, vec2 v1, vec2 c) -{ - vec2 dir = normalize(v1 - v0); - dir = vec2(dir.y, -dir.x); - /* The model matrix can be scaled negativly. - * Use projected sphere center to determine - * the outline direction. */ - vec2 cv = c - v0; - dir = (dot(dir, cv) > 0.0) ? -dir : dir; - return dir; -} - void main() { vec4 bone_color, state_color; @@ -73,27 +62,17 @@ void main() } /* Camera oriented position (but still in local space) */ - vec3 cam_pos0 = x_axis * pos0.x + y_axis * pos0.y + z_axis * z_ofs; - vec3 cam_pos1 = x_axis * pos1.x + y_axis * pos1.y + z_axis * z_ofs; + vec3 cam_pos0 = x_axis * pos.x + y_axis * pos.y + z_axis * z_ofs; vec4 V = model_view_matrix * vec4(cam_pos0, 1.0); - vec4 p0 = ProjectionMatrix * V; - vec4 p1 = ProjectionMatrix * (model_view_matrix * vec4(cam_pos1, 1.0)); - vec4 c = ProjectionMatrix * vec4(model_view_matrix[3].xyz, 1.0); - - vec2 ssc = proj(c); - vec2 ss0 = proj(p0); - vec2 ss1 = proj(p1); - vec2 edge_dir = compute_dir(ss0, ss1, ssc); - - bool outer = ((gl_VertexID & 1) == 1); + gl_Position = ProjectionMatrix * V; + vec4 center = ProjectionMatrix * vec4(model_view_matrix[3].xyz, 1.0); - vec2 t = bone_color.w * (2.0 * sizeViewportInv.xy); - t *= (is_persp) ? abs(V.z) : 1.0; - t = (outer) ? t : vec2(0.0); + /* Offset away from the center to avoid overlap with solid shape. */ + vec2 ofs_dir = normalize(proj(gl_Position) - proj(center)); + gl_Position.xy += ofs_dir * sizeViewportInv.xy * gl_Position.w; - gl_Position = p0; - gl_Position.xy += t * edge_dir; + edgeStart = edgePos = proj(gl_Position); finalColor = vec4(bone_color.rgb, 1.0); diff --git a/source/blender/draw/engines/overlay/shaders/armature_wire_frag.glsl b/source/blender/draw/engines/overlay/shaders/armature_wire_frag.glsl new file mode 100644 index 00000000000..9413ac0f365 --- /dev/null +++ b/source/blender/draw/engines/overlay/shaders/armature_wire_frag.glsl @@ -0,0 +1,13 @@ + +flat in vec4 finalColor; +flat in vec2 edgeStart; +noperspective in vec2 edgePos; + +layout(location = 0) out vec4 fragColor; +layout(location = 1) out vec4 lineOutput; + +void main() +{ + lineOutput = pack_line_data(gl_FragCoord.xy, edgeStart, edgePos); + fragColor = finalColor; +} diff --git a/source/blender/draw/engines/overlay/shaders/armature_wire_vert.glsl b/source/blender/draw/engines/overlay/shaders/armature_wire_vert.glsl index 4e207b96016..d6d6cb6e024 100644 --- a/source/blender/draw/engines/overlay/shaders/armature_wire_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/armature_wire_vert.glsl @@ -3,6 +3,8 @@ in vec3 color; in vec3 pos; flat out vec4 finalColor; +flat out vec2 edgeStart; +noperspective out vec2 edgePos; void main() { @@ -12,6 +14,8 @@ void main() vec3 worldPosition = point_object_to_world(pos); gl_Position = point_world_to_ndc(worldPosition); + edgeStart = edgePos = ((gl_Position.xy / gl_Position.w) * 0.5 + 0.5) * sizeViewport.xy; + #ifdef USE_WORLD_CLIP_PLANES world_clip_planes_calc_clip_distance(worldPosition); #endif |