phaserjs / phaserjs/phaser

`Controller.paddingOverride` default prevents Glow filter from calculating framebuffer padding

Open
#7,242 0 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
JavaScript
Stars
40.3k
Forks
7.2k
PR merge metrics
No merged PRs in 30d

Description

Version

  • Phaser Version: 4.0.0 RC6
  • Operating system: Linux
  • Browser: Chrome 133

Description

The Controller base class initializes paddingOverride to new Rectangle() (Controller.js:67), which is a zero-valued but truthy object.

The Glow filter overrides getPadding() and checks if (this.paddingOverride) before falling through to its own distance-based padding calculation (Glow.js:218). Since paddingOverride is always truthy, the Glow's distance * scale calculation never executes, and the framebuffer gets zero extra padding.

Expected: Glow extends beyond the sprite outline by distance pixels, following the alpha edges of the opaque pixels.

Actual: Glow is confined within the sprite's rectangular bounds and abruptly cuts off at the frame edges. The effect looks like a square gradient that stops at the sprite frame boundary.

Example Test Code

// Minimal reproduction
const config = {
    type: Phaser.AUTO,
    width: 400,
    height: 300,
    backgroundColor: '#2d2d2d',
    scene: {
        preload: function () {
            // Use any sprite with transparency (non-rectangular shape)
            this.load.image('star', 'https://labs.phaser.io/assets/sprites/star.png');
        },
        create: function () {
            const sprite = this.add.sprite(200, 150, 'star');
            sprite.enableFilters();
            const glow = sprite.filters.internal.addGlow(0xffff00, 4, 0, 1, false, 10, 16);

            // BUG: glow is clipped to sprite's rectangular bounds
            // WORKAROUND: uncomment the next line to fix it
            // glow.setPaddingOverride(null);
        }
    }
};

new Phaser.Game(config);

Additional Information

Root cause: Controller.js:67 sets this.paddingOverride = new Rectangle(). This zero-valued Rectangle is always truthy, so when Glow.getPadding() checks if (this.paddingOverride), it always takes the override path and returns zero padding instead of calculating distance * scale.

Workaround:

glow.setPaddingOverride(null);

Suggested fix: In Controller.js:67, change:

this.paddingOverride = new Rectangle();

to:

this.paddingOverride = null;

This lets filters with custom getPadding() implementations (Glow, Blur) fall through to their own padding logic by default. setPaddingOverride() can still be called explicitly when an override is desired.

This likely affects any filter that overrides getPadding() with a truthy check on paddingOverride.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with src/filters/Controller.js at the paddingOverride initialization and compare it with Glow.getPadding() in src/filters/Glow.js. Use the minimal reproduction with a transparent sprite to verify that Glow padding is calculated from distance by default while setPaddingOverride() still enables an explicit override. Done means the glow extends beyond the sprite edges without being clipped.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
game-dev
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.