fix(render): miter the joints of wide polyline bands

Each band segment was a rectangle ending square at its vertex, so the
outer corner of every joint showed a notch. Every segment end now carries
the tangent of half its turn, and the shader slides that end's corners
onto the joint's bisector so neighbours meet in a miter. Turns sharper
than the limit keep butt ends. Constant-width runs inside a polyline split
around its arcs no longer count as tapered, which had kept them unmitred.

Fixes #1565

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Hakan SevenandClaude Opus 5.5 committed 2026-10-04 20:44:08 +03:00
1 parent 4cfcc9dc38
commit d6dfd0d46d
6 files changed
+161 -23

No files matched your search

+8 -2
View File
@@ -69,6 +69,8 @@ struct InstanceIn {
const MODEL_LINEWEIGHT_BOOST: f32 = 2.0;
const MODEL_LINEWEIGHT_MAX_PX: f32 = 10.0;
// Must match `MITER_LIMIT` in wire_gpu.rs.
const MITER_LIMIT: f32 = 8.0;
struct VertexOut {
@builtin(position) clip_pos: vec4<f32>,
@@ -191,13 +193,17 @@ fn marker_relative(position_high: vec3<f32>, position_low: vec3<f32>, instance:
}
perp_world = normalize(perp_world);
// A constant-width band slides each corner along the segment onto
// its joint's bisector (miter), so neighbours meet without a notch.
let miter = vec2<f32>(in.marker_origin_high.w, in.marker_origin_low.w) * MITER_LIMIT;
let along = mix(miter.x, miter.y, which_end) * eff_hw * side;
let pos_rel = mix(rel_a, rel_b, which_end);
let world_pos = pos_rel + perp_world * (eff_hw * side);
let world_pos = pos_rel + perp_world * (eff_hw * side) + world_dir * along;
var clip_pos = u.view_rot * vec4<f32>(world_pos, 1.0);
clip_pos = apply_draw_order(clip_pos, in.misc.x);
final_clip = clip_pos;
out_dist = mix(in.dists.x, in.dists.y, which_end);
out_dist = mix(in.dists.x, in.dists.y, which_end) + along * (in.dists.y - in.dists.x) / max(world_len, 1e-6);
out_cap = vec2<f32>(which_end * world_len, eff_hw * side);
out_cap_ends = vec3<f32>(world_len, world_hw_a, world_hw_b);
} else {