mirror of
https://github.com/italicsjenga/vello.git
synced 2025-01-09 12:21:31 +11:00
Sederberg error metric
Use proper math to compute number of subdivisions. This works but is not very satisfying, as it over-subdivides.
This commit is contained in:
parent
b571e0d10c
commit
eaa1d261c3
|
@ -317,7 +317,6 @@ void main() {
|
|||
case Element_FillLine:
|
||||
case Element_StrokeLine:
|
||||
LineSeg line = Element_StrokeLine_read(this_ref);
|
||||
PathStrokeLine path_line;
|
||||
vec2 p0 = st.mat.xy * line.p0.x + st.mat.zw * line.p0.y + st.translate;
|
||||
vec2 p1 = st.mat.xy * line.p1.x + st.mat.zw * line.p1.y + st.translate;
|
||||
PathStrokeCubic path_cubic;
|
||||
|
@ -338,6 +337,30 @@ void main() {
|
|||
pathseg[path_out_ref.offset >> 2] = out_tag;
|
||||
PathStrokeCubic_write(PathStrokeCubicRef(path_out_ref.offset + 4), path_cubic);
|
||||
break;
|
||||
case Element_FillQuad:
|
||||
case Element_StrokeQuad:
|
||||
QuadSeg quad = Element_StrokeQuad_read(this_ref);
|
||||
p0 = st.mat.xy * quad.p0.x + st.mat.zw * quad.p0.y + st.translate;
|
||||
p1 = st.mat.xy * quad.p1.x + st.mat.zw * quad.p1.y + st.translate;
|
||||
vec2 p2 = st.mat.xy * quad.p2.x + st.mat.zw * quad.p2.y + st.translate;
|
||||
path_cubic;
|
||||
path_cubic.p0 = p0;
|
||||
path_cubic.p1 = mix(p1, p0, 1.0 / 3.0);
|
||||
path_cubic.p2 = mix(p1, p2, 1.0 / 3.0);
|
||||
path_cubic.p3 = p2;
|
||||
path_cubic.path_ix = st.path_count;
|
||||
if (tag == Element_StrokeQuad) {
|
||||
path_cubic.stroke = get_linewidth(st);
|
||||
} else {
|
||||
path_cubic.stroke = vec2(0.0);
|
||||
}
|
||||
// We do encoding a bit by hand to minimize divergence. Another approach
|
||||
// would be to have a fill/stroke bool.
|
||||
path_out_ref = PathSegRef((st.pathseg_count - 1) * PathSeg_size);
|
||||
out_tag = tag == Element_FillQuad ? PathSeg_FillCubic : PathSeg_StrokeCubic;
|
||||
pathseg[path_out_ref.offset >> 2] = out_tag;
|
||||
PathStrokeCubic_write(PathStrokeCubicRef(path_out_ref.offset + 4), path_cubic);
|
||||
break;
|
||||
case Element_FillCubic:
|
||||
case Element_StrokeCubic:
|
||||
CubicSeg cubic = Element_StrokeCubic_read(this_ref);
|
||||
|
|
Binary file not shown.
|
@ -33,7 +33,8 @@ layout(set = 0, binding = 2) buffer TileBuf {
|
|||
#define SX (1.0 / float(TILE_WIDTH_PX))
|
||||
#define SY (1.0 / float(TILE_HEIGHT_PX))
|
||||
|
||||
#define Q_ACCURACY 0.025
|
||||
#define ACCURACY 0.25
|
||||
#define Q_ACCURACY 0.01
|
||||
#define MAX_HYPOT2 (432.0 * Q_ACCURACY * Q_ACCURACY)
|
||||
|
||||
vec2 eval_cubic(vec2 p0, vec2 p1, vec2 p2, vec2 p3, float t) {
|
||||
|
@ -76,10 +77,16 @@ void main() {
|
|||
case PathSeg_FillCubic:
|
||||
case PathSeg_StrokeCubic:
|
||||
PathStrokeCubic cubic = PathSeg_StrokeCubic_read(ref);
|
||||
// Commented out code is for computing error bound on conversion to quadratics
|
||||
/*
|
||||
vec2 err_v = 3.0 * (cubic.p2 - cubic.p1) + cubic.p0 - cubic.p3;
|
||||
float err = err_v.x * err_v.x + err_v.y * err_v.y;
|
||||
// The number of quadratics.
|
||||
uint n = max(uint(ceil(pow(err * (1.0 / MAX_HYPOT2), 1.0 / 6.0))), 1);
|
||||
*/
|
||||
// This calculation is based on Sederberg, CAGD Notes section 10.6
|
||||
vec2 l = max(abs(cubic.p0 + cubic.p2 - 2 * cubic.p1), abs(cubic.p1 + cubic.p3 - 2 * cubic.p2));
|
||||
uint n = max(uint(ceil(sqrt(length(l) * (0.75 / ACCURACY)))), 1);
|
||||
vec2 p0 = cubic.p0;
|
||||
float step = 1.0 / float(n);
|
||||
uint path_ix = cubic.path_ix;
|
||||
|
|
Binary file not shown.
Loading…
Reference in a new issue