pixijs / pixijs

The HTML5 Creation Engine: Create beautiful digital content with the fastest, most flexible 2D WebGL renderer.
http://pixijs.com
MIT License
43.9k stars 4.78k forks source link

Bug: inner strokes sometimes are drawn out of shape #9502

Open UlyssesZh opened 1 year ago

UlyssesZh commented 1 year ago

Current Behavior

const graphics = new PIXI.Graphics();
graphics.x = 100;
graphics.y = 100;
function drawPath() {
    graphics.arc(0, 0, 50, -0.7, 1);
    graphics.lineTo(200, 0);
    graphics.closePath();
}

graphics.lineStyle(10, 0xffff00, 1, 1);
drawPath();
graphics.lineStyle(1, 0xff0000, 1, 1);
drawPath();

output Look at the edge at the bottom left of the shape. The yellow stroke just gets out of the shape although it is an inner stroke. The edge at the top left of the shape is however fine.

Expected Behavior

The two left edges on the image above should qualitatively look similarly.

Steps to Reproduce

...

Environment

Possible Solution

No response

Additional Information

No response

tangerine-orange commented 1 year ago

I think this is expected behavior. Check the docs for .lineStyle (width, color, alpha, alignment, native): https://pixijs.download/dev/docs/PIXI.Graphics.html#lineStyle

In particular, the fourth argument, alignment, has the following spec:

alignment of the line to draw, (0 = inner, 0.5 = middle, 1 = outer). WebGL only.

Since you're setting alignment = 1, you'd expect the stroke to be outside of the path that you defined. Try setting it to 0.5 or 0.

UlyssesZh commented 1 year ago

@tangerine-orange Thank you for your opinion, but you did not get me.

First, the alignment argument is not simply defining whether the line should be drawn inner or outer, it means whether the stroke is drawn to the left or to the right. Actually, alignment = 1 means that the stroke is drawn to the left of the line, and alignment = 0 means to the right. Therefore, this is the expected behavior: with alignment = 1, the line is drawn outside the shape only if the stroke is drawn clockwise. You can write a simple code to verify this behavior on your own.

Second, you misunderstood what behavior I think is wrong, and you did not even look at the output of my codes in the original issue closely. The red line is the border, and what it is supposed to draw (in yellow) should be totally inside the shape given by the red line because I am drawing counterclockwisely with alignment = 1. The output is largely expected except the bottom left corner.

tangerine-orange commented 1 year ago

I do see the output of your code and the exterior yellow, and I understand your issue.

You're correct about alignment = 1 meaning left of the line, alignment = 0 meaning right of the line. Thank you for pointing that out; I hadn't realized that before.

Still, I think behavior is intended. Consider these two cases: https://jsfiddle.net/cwh9t2od/1/ https://jsfiddle.net/e5ausjxp/ This is the same as your code, but I extended the arc by adjusting the last parameter (endAngle) of graphics.arc. I think we can agree that in https://jsfiddle.net/e5ausjxp/, the exterior yellow strokes are doing the correct thing, as they are now tracing around a secant arc. So if they are correct in https://jsfiddle.net/e5ausjxp/, but incorrect in your original example, how should we make the distinction? At what point should we start and stop rendering the exterior strokes?

UlyssesZh commented 1 year ago

@tangerine-orange In the two cases that you provided, the arc has two intersections with the lower line segment, while in my case, it only has one intersection.

You must have found something inconsistent here if you play more around the angle parameters of the graphics.arc call. Consider these two cases:

graphics.arc(0, 0, 50, -0.7, 0.7);

image

graphics.arc(0, 0, 50, -0.7, 1);

image

The second case is the same as my origional post. Notice the top left corner in both cases. In these cases, the strokes drawn in the top left corner of the shape are different, while the geometric shape of that corner is the same in these two cases. This shows inconsistent behavior, which means at least one of them should be unexpected.

tangerine-orange commented 1 year ago

Indeed, there are definitely inconsistencies there. In particular with your two examples, graphics.arc(0, 0, 50, -0.7, 0.7); and graphics.arc(0, 0, 50, -0.7, 1);, the top left corner should be exactly the same, but clearly it is not rendered the same.

I agree with you, it should either bleed out in all cases or bleed out in no cases.

bigtimebuddy commented 1 year ago

This definitely seems like a bug. Here's another example without the arc: https://jsfiddle.net/bigtimebuddy/hcgdy38k/

An alignment of 1 and miterLimit do some funny things.

bigtimebuddy commented 1 year ago

@dev7355608 you're pretty familiar with the Graphics drawing. Do you think you could look at this?