Phaser: Stroke rounded rect visual artifacts

Created on 20 Aug 2018  路  20Comments  路  Source: photonstorm/phaser

Vesion: 3.12 beta 2, also 3.11

2018-08-20 11 58 41

screenshot taken from example - https://labs.phaser.io/view.html?src=src/game%20objects/graphics/stroke%20rounded%20rectangle.js

These artifacts appear only on Android devices.


Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.

鈱涳笍 Time Consuming 馃敭 Renderer (WebGL)

Most helpful comment

Thank you for submitting this issue (yes, 2 years ago!). We have fixed this and the fix has been pushed to the master branch. It will be part of the next release. If you get time to build and test it for yourself we would appreciate that, although of course given the age of this issue, isn't expected at all.

All 20 comments

Does this happen in Canvas _and_ WebGL, or just one of them? My guess would be it only happens in Canvas.

@photonstorm Nope, it happen in Webgl

Canvas on the screenshot
2018-08-20 13 57 53

Can you test this with the current master version please? I pushed a fix for the arc function today which I'm hoping will solve this too.

@photonstorm CANVAS looks good, but WEBGL still has artifacts

Can you make this happen in any desktop browsers? (as I can't) - and which Android browser is it? Or is this a compiled app? May have to leave this as a known issue, because the time involved investigating it is likely prohibitive.

@photonstorm it happens only on Android devices, and actually not on every. It visible in Android browser (chrome), also in fb messenger (instant games)

What about the filled rounded rectangles?

And is it just rounded rects? Do other Graphics shapes appear ok?

only stroked rounded rect has artifacts, default rect (filled, stroked) looks fine, the same as filled rounded rect

This is what the function does:

    strokeRoundedRect: function (x, y, width, height, radius)
    {
        if (radius === undefined) { radius = 20; }

        var tl = radius;
        var tr = radius;
        var bl = radius;
        var br = radius;

        if (typeof radius !== 'number')
        {
            tl = GetFastValue(radius, 'tl', 20);
            tr = GetFastValue(radius, 'tr', 20);
            bl = GetFastValue(radius, 'bl', 20);
            br = GetFastValue(radius, 'br', 20);
        }

        this.beginPath();
        this.moveTo(x + tl, y);
        this.lineTo(x + width - tr, y);
        this.arc(x + width - tr, y + tr, tr, -MATH_CONST.TAU, 0);
        this.lineTo(x + width, y + height - br);
        this.arc(x + width - br, y + height - br, br, 0, MATH_CONST.TAU);
        this.lineTo(x + bl, y + height);
        this.arc(x + bl, y + height - bl, bl, MATH_CONST.TAU, Math.PI);
        this.lineTo(x, y + tl);
        this.arc(x + tl, y + tl, tl, -Math.PI, -MATH_CONST.TAU);
        this.strokePath();

        return this;
    },

Which is basically just a bunch of Graphics commands in a sequence. Could you try re-creating the above (so just calling the Graphics commands directly) but add in a closePath before the stroke? I'm thinking it's something like that.

i recreated, but it doesn't help at all.

this.graphics = this.add.graphics();
    const width = 100;
    const height = 50;
    const tl = 5;
    const tr = 5;
    const bl = 5;
    const br = 5;
    const x = window.innerWidth / 2;
    const y = 20;
    this.graphics.beginPath();
    this.graphics.lineStyle(2, 0x00ff00);
    this.graphics.moveTo(x + tl, y);
    this.graphics.lineTo(x + width - tr, y);
    this.graphics.arc(x + width - tr, y + tr, tr, -Math.PI * 0.5, 0);
    this.graphics.lineTo(x + width, y + height - br);
    this.graphics.arc(x + width - br, y + height - br, br, 0, Math.PI * 0.5);
    this.graphics.lineTo(x + bl, y + height);
    this.graphics.arc(x + bl, y + height - bl, bl, Math.PI * 0.5, Math.PI);
    this.graphics.lineTo(x, y + tl);
    this.graphics.arc(x + tl, y + tl, tl, -Math.PI, -Math.PI * 0.5);
    this.graphics.closePath();
    this.graphics.strokePath();

i think we can mark this bug as known issue
bug

How about breaking it down a bit - so rather than the whole rectangle, how about just having the first moveTo, lineTo and arc calls? Do you still see it then? (comment out the rest of the commands) - if not, add the next line in and try again. I'm curious to know at which point you get one of those extra lines to appear. I'd rather solve this than leave it as-is.

moveTo -> lineTo -> arc
2018-08-25 10 43 25

moveTo -> lineTo
2018-08-25 10 47 41

Hi, i added moveTo after lineTo and then call arc - suddenly that moveTo fixed artifacts -__-
123

Does it work if you repeat for all 4 corners? If so we can merge this back in with master.

Could there be a problem with the negative angles? I guess there should not be as angles can be negative, but you never know. Below the angles are changed to be positive.

        this.beginPath();
        this.moveTo(x + tl, y);
        this.lineTo(x + width - tr, y);
        this.arc(x + width - tr, y + tr, tr, 3*MATH_CONST.TAU, 2*Math.PI);
        this.lineTo(x + width, y + height - br);
        this.arc(x + width - br, y + height - br, br, 0, MATH_CONST.TAU);
        this.lineTo(x + bl, y + height);
        this.arc(x + bl, y + height - bl, bl, MATH_CONST.TAU, Math.PI);
        this.lineTo(x, y + tl);
        this.arc(x + tl, y + tl, tl, Math.PI, 3*MATH_CONST.TAU);
        this.strokePath();

@photonstorm yeah it does

@alexeymolchan you could try the non-negative version above, but otherwise please paste the full working combination here so I can merge it into master, as I've never been able to reproduce this, so I need to see what combination gets it working for you.

@photonstorm i already tried with non-negative angles, but it still produce artifacts.
Working combination:

strokeRoundedRect: function (x, y, width, height, radius)
    {
        if (radius === undefined) { radius = 20; }

        var tl = radius;
        var tr = radius;
        var bl = radius;
        var br = radius;

        if (typeof radius !== 'number')
        {
            tl = GetFastValue(radius, 'tl', 20);
            tr = GetFastValue(radius, 'tr', 20);
            bl = GetFastValue(radius, 'bl', 20);
            br = GetFastValue(radius, 'br', 20);
        }

        this.beginPath();
        this.moveTo(x + tl, y);
        this.lineTo(x + width - tr, y);
        this.moveTo(x + width - tr, y);
        this.arc(x + width - tr, y + tr, tr, -MATH_CONST.TAU, 0);
        this.lineTo(x + width, y + height - br);
        this.moveTo(x + width, y + height - br)
        this.arc(x + width - br, y + height - br, br, 0, MATH_CONST.TAU);
        this.lineTo(x + bl, y + height);
        this.moveTo(x + bl, y + height);
        this.arc(x + bl, y + height - bl, bl, MATH_CONST.TAU, Math.PI);
        this.lineTo(x, y + tl);
        this.moveTo(x, y + tl);
        this.arc(x + tl, y + tl, tl, -Math.PI, -MATH_CONST.TAU);
        this.strokePath();

        return this;
    },

Just to say that I can re-create this locally now, so I'll look into it further. While the above did work for me I need to understand why it's happening at all, so will carry on debugging it.

Thank you for submitting this issue (yes, 2 years ago!). We have fixed this and the fix has been pushed to the master branch. It will be part of the next release. If you get time to build and test it for yourself we would appreciate that, although of course given the age of this issue, isn't expected at all.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

samme picture samme  路  4Comments

BigZaphod picture BigZaphod  路  4Comments

Colbydude picture Colbydude  路  4Comments

frob picture frob  路  4Comments

Secretmapper picture Secretmapper  路  3Comments