arc flattening; inner join winding fixes
diff --git a/examples/scenes/src/mmark.rs b/examples/scenes/src/mmark.rs index ac4924a..71d5347 100644 --- a/examples/scenes/src/mmark.rs +++ b/examples/scenes/src/mmark.rs
@@ -105,6 +105,7 @@ element.is_split ^= true; } } + /* let label = format!("mmark test: complexity: {}, {} path elements (up/down to adjust)", c, n); params.text.add( scene, @@ -114,6 +115,7 @@ Affine::translate((100.0, 1100.0)), &label, ); + */ } }
diff --git a/vello_shaders/shader/flatten.wgsl b/vello_shaders/shader/flatten.wgsl index 039ef20..6f863b1 100644 --- a/vello_shaders/shader/flatten.wgsl +++ b/vello_shaders/shader/flatten.wgsl
@@ -495,6 +495,39 @@ start_p: vec2f, t_range: vec2f, ) -> vec2f { +#ifdef arc_lowering + let es = params.es; + let arc_len = params.chord_len / es.params.ch; + let k0 = es.params.k0; + let k1 = es.params.k1; + let rho_int_0 = cbrt(1. / (k0 + (t_range.x - 0.5) * k1)); + let rho_int_1 = cbrt(1. / (k0 + (t_range.y - 0.5) * k1)); + let rho_int = rho_int_1 - rho_int_0; + let est_err = abs(rho_int) * arc_len / params.tol; + // TODO: apply scaling factor to est_err to tune actual error. + // Math suggests 27. / 40. but eyeball error seems too large. + let range_size = t_range.y - t_range.x; + let n_subdiv = max(ceil(cbrt(est_err) * range_size), 1.0); + let n = u32(n_subdiv); + var last_k = k0 + (t_range.x - 0.5) * k1; + var last_r = sqrt(abs(last_k)); + let sign4 = select(4., -4., sign(-k0) == -1.); + var lp0 = start_p; + for (var i = 0u; i <= n; i++) { + let t = f32(i) / n_subdiv; + let u = rho_int_0 + t * rho_int; + let s_0_1 = (1. / pow(u, 3.) - k0) / k1 + 0.5; + let s = t_range.x + range_size * s_0_1; + let lp1 = es_seg_eval_evolute(es, s); + let k = k0 + (s - 0.5) * k1; + let r = sqrt(abs(k)); + let es_k = sign4 * pow((r - last_r), 2.) / (k1 / k - k1 / last_k); + output_double_line_with_transform(params.path_ix, lp0, lp1, params.transform, params.offset >= 0.); + last_k = k; + last_r = r; + lp0 = lp1; + } +#else let es = params.es; let arc_len = params.chord_len / es.params.ch; let ratio = es.params.k0 / es.params.k1; @@ -515,6 +548,7 @@ output_double_line_with_transform(params.path_ix, lp0, lp1, params.transform, params.offset >= 0.); lp0 = lp1; } +#endif return lp0; } @@ -805,11 +839,11 @@ switch style_flags & STYLE_FLAGS_JOIN_MASK { case STYLE_FLAGS_JOIN_BEVEL: { #ifdef inner_join - let p0 = select(front0, back0, is_backside); - let p1 = select(front1, back1, is_backside); + let p0 = select(front0, back1, is_backside); + let p1 = select(front1, back0, is_backside); output_line_with_transform(path_ix, p0, p1, transform, true); #else - output_two_lines_with_transform(path_ix, front0, front1, back0, back1, transform); + output_two_lines_with_transform(path_ix, front0, front1, back1, back0, transform); #endif } case STYLE_FLAGS_JOIN_MITER: { @@ -887,20 +921,20 @@ // Handle inner join if abs(cr) < 1e-6 { // smooth join, don't need to draw inner join - let inner0 = select(back0, front0, is_backside); - let inner1 = select(back1, front1, is_backside); + let inner0 = select(back1, front0, is_backside); + let inner1 = select(back0, front1, is_backside); if any(inner0 != inner1) { output_line_with_transform(path_ix, inner0, inner1, transform, true); } } else { - let inner0 = select(back0, front0, is_backside); - let inner1 = select(back1, front1, is_backside); + let inner0 = select(back1, front0, is_backside); + let inner1 = select(back0, front1, is_backside); let line_ix = atomicAdd(&bump.lines, 4u); write_line_with_transform(line_ix, path_ix, inner0, p0, transform); write_line_with_transform(line_ix + 1, path_ix, p0, inner1, transform); write_line_with_transform(line_ix + 2, path_ix, inner0, p0, transform); write_line_with_transform(line_ix + 3, path_ix, p0, inner1, transform); - flatten_arc(path_ix, inner1, inner0, p0, -abs(atan2(cr, d)), transform); + flatten_arc(path_ix, inner0, inner1, p0, abs(atan2(cr, d)), transform); } #endif } @@ -1052,6 +1086,14 @@ write_line(line_ix, path_ix, tp0, tp1); } +fn write_line_with_transform_and_dir(line_ix: u32, path_ix: u32, p0: vec2f, p1: vec2f, t: Transform, forward: bool) { + let tp0 = transform_apply(t, p0); + let tp1 = transform_apply(t, p1); + let l0 = select(tp1, tp0, forward); + let l1 = select(tp0, tp1, forward); + write_line(line_ix, path_ix, l0, l1); +} + fn output_line(path_ix: u32, p0: vec2f, p1: vec2f) { let line_ix = atomicAdd(&bump.lines, 1u); write_line(line_ix, path_ix, p0, p1);
diff --git a/vello_shaders/src/compile/mod.rs b/vello_shaders/src/compile/mod.rs index 150a2c9..d6971bf 100644 --- a/vello_shaders/src/compile/mod.rs +++ b/vello_shaders/src/compile/mod.rs
@@ -203,6 +203,7 @@ defines.push("evolutes"); defines.push("inner_join"); //defines.push("arc_lowering"); + //defines.push("ablate_arc_flattening"); defines.into_iter().map(|s| s.to_owned()).collect() }; for entry in shader_dir