Black opaque background on transparent Phaser.Text textures in Phaser 4.2.1 on older iOS WebGL
Maintainers usually reply within 2 days
Nobody has claimed this yet.
Assessment
- Difficulty
- 1/5
- Estimated time
- Under an hour
- Newbie friendliness
- 85/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- javascript
- Domain
- game-dev
Research direction
Locate the ApplyTint.glsl WebGL shader file in the Phaser source tree. Add the provided early return guard for zero-alpha texels before the unpremultiply division to resolve the opaque black background issue on older iOS WebGL devices. Verify the fix using the included sample text rendering code to confirm transparent text renders correctly.
Written by the indexing model from the issue text.
Description
Version
- Phaser Version: 4.2.1
- Operating system: iPad OS 16.4
Description
Problem
In our game Tvers (www.nrk.no/spill/tvers) we got reports from people playing on older iPads that there were black backgrounds behind out letter tiles after we upgraded to Phaser 4.2.1. We spent a lot of time trying to debug the behaviour and traced it to a division by zero issue in ApplyTint.glsl.
On older iOS devices (<= iPad OS 16.4), Phaser Text objects with black fill rendered on top of a transparent background show as black rectangles with faint aliased edges. On newer devices the transparency works as expected. In Phaser 3.8 this was not a problem.
Cause
The WebGL tint shader (ApplyTint.glsl) performs an unpremultiply of the text texture:
vec3 unpremultTexture = texture.rgb / texture.a;
Outside the character glyph, the canvas-generated texture stores pixels with RGB = 0 and alpha = 0. Dividing zero by zero results in undefined behavior (NaN or Infinity). How the shader handles that NaN varies between GPUs/drivers. On the affected devices it propagates, producing a visible opaque black rectangle instead of transparent.
Fix
Guard the division by returning early for zero-alpha texels:
if (texture.a <= 0.0) {
return vec4(0.0);
}
vec3 unpremultTexture = texture.rgb / texture.a;
Example Test Code
const textStyling = {
fontSize: '80px',
color: 'black',
fontFamily: 'sans-serif',
fontStyle: 'bold',
padding: { x: 10, y: 10 },
}
const background = this.scene.add
.image(0, 0, 'tile')
.setTint(palette.boardSquare)
.setTintMode(Phaser.TintModes.FILL)
const letter = this.scene.add.text(0, 0, this.letter, textStyling)
Phaser.Display.Align.In.Center(letter, background)
- Dominant language
- JavaScript
- Stars
- 40.4k
- Forks
- 7.2k
- PR merge metrics
- No merged PRs in 30d
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from phaserjs/phaser
-
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
Maintainers usually reply within 2 days
-
Shader.preDestroy leaks its ShaderQuad's vertex buffer and VAO on every create/destroy cycle (4.2.1)Open
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
Maintainers usually reply within 2 days
-
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
Maintainers usually reply within 2 days
-
WebGL stroke of a Polygon drops a vertex when its origin-shifted position equals the previous raw vertexPossibly taken @ICOM725 claimed this 36 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
phaserjs/phaser#7361 · 1 comment ·
Maintainers usually reply within 2 days
-
MouseManager.stopListeners never removes the wheel listener — destroyed Game stays retained through the canvasPossibly taken @schulerj89 claimed this 76 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 2 days
Similar issues
-
enhancement good first issue
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
anoopcodehack/DevBoard#609 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
openai/codex-plugin-cc#813 ·
-
area: ops type: test
Difficulty 2/5 1-3 hours Newbie friendliness 79/100
accensa/x402-facilitator-stellar#559 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
bilawalsidhu/gods-eye-view#1060 ·
Maintainers usually reply within 1 day
-
Progress difficulty filter lists Hard before MediumPossibly taken @Pandamachi claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
sysprog21/codetrial#281 · 1 comment ·
Maintainers usually reply within 1 day