Jump to content

Sprite is not rendered correctly (extra lines on the edge)


pingu
 Share

Recommended Posts

How avoiding the texture bleeding issues on WebGL.  

Tile Extruder is a node based CLI app that automatically fixes tileset images for WebGL, so they no longer have edge bleeding where the tiles join at the sides. It's easy to build into your workflow and includes sample code showing how to use the extruded tiles in Phaser 3.

tile-extruder --tileWidth 32 --tileHeight 32 --input ./tile_jungle_ground_brown.png --output ./tile_jungle_ground_brown-extruded.png

Note: you'll have to adjust your margin & spacing because of the extrusion. If you had no margin & spacing, then the new margin is 1px and the spacing is 2px.

Link to comment
Share on other sites

I'm just gonna add to all this that if you use TileSprite, it would cause this kind of issue too due to aforementioned pixel bleeding. And that's regardless of where the sprite is on the atlas, rather it depends on how the TileSprite cuts it out (as it actually creates a new texture).

Link to comment
Share on other sites

Hey guys,

Thanks for the responses. I don't use any tileset or texture packing / atlas. My code is as follows:

<!DOCTYPE html>
<html>
<head>
    <script src="//cdn.jsdelivr.net/npm/[email protected]/dist/phaser.js"></script>
</head>
<body>

    <script>
    var screenWidth = 450;
    var screenHeight = 800;
    var config = {
        type: Phaser.AUTO,
        width: screenWidth,
        height: screenHeight,
        physics: {
            default: 'arcade',
            arcade: {
                gravity: { x: 0, y: 0 }
            }
        },
        scene: {
            preload: preload,
            create: create,
            // update: update
        },
        backgroundColor: 0xF4F1EC
    };

    function preload ()
    {
        this.load.image('sprite', 'sprite.png');
    }

    function create ()
    {
        var turn;
        turn = this.physics.add.sprite(screenWidth / 2, screenHeight / 2, 'sprite').setTint(0x00000);
        turn.setScale(screenHeight / turn.height * 0.406, screenHeight / turn.height * 0.406);
        turn.depth = 1;

        return;
    }
    </script>

</body>
</html>

My sprite is attached to this reply. I am clueless why this would happen with a simple image. I checked the image and made sure those bleeding artifacts don't actually exist.

 

sprite.png

Link to comment
Share on other sites

@pingu found the problem... it is related to Phaser texture creating. See method createTextureFromSource() (https://github.com/photonstorm/phaser/blob/master/src/renderer/webgl/WebGLRenderer.js#L1144)

It sets wrap mode to CLAMP_TO_EDGE by default, which would be OK and no bleeding would be shown. But... if texture dimensions are power of two (which is your case), then it changes wrap mode to REPEAT. You can encounter imprecisions in GPU calculations, so your texture is drawn and small part is repeated - it is that bleeding. Your current sprite scale is 0.406, if you set it to 0.5, then calculations are little different and bleeding is not shown. If you animated scale, then bleeding would probably blink - sometimes shown, sometimes not.

So, solutions are:
 - add extra padding around your shape as @bossikkk suggested. If you want to preserve texture size 512x512, then draw your shape 510x510 and leave 1px empty on all sides,
 - simply change dimensions of your texture to not be power of 2 - like add 1 empty line and column to make it 513x513 texture (this is OK for development, but I do not like this solution - not sure, but I have somewhere back in my mind, that some GPUs are adding extra space for non POT textures to force them to nearest POT - in your case it would be 1024x1024 with lot of memory eaten.)

 

Link to comment
Share on other sites

  • 1 year later...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...