phaserjs / phaser

Phaser is a fun, free and fast 2D game framework for making HTML5 games for desktop and mobile web browsers, supporting Canvas and WebGL rendering.
https://phaser.io
MIT License
37.09k stars 7.1k forks source link

Additive Blend Objects showing Black instead of Transparent Pixels in WebGL #5667

Closed Overld closed 1 year ago

Overld commented 3 years ago

Version

Description

If "PixelArt" phaser configuration is set to true, all sprites that use Phaser.BlendModes.ADD no longer shows transparent pixels on iPhone or iPad. Tested it on Macintosh Computer with Safari, Windows running Chrome, Android Tablet, iPhone 12 Pro, and iPad. Only the iOS devices (iPhone and iPad) exhibit the issue. Tested both on Chrome and Safari on iOS, and the problem looked exactly the same. If "PixelArt" configuration is set to false, then the graphic displays the correct transparency.

For the game I am developing, I need "PixelArt" active otherwise I get a lot of blur and distortion on my game graphics.

I did a quick test since I had an older version of my code and it was working fine on version 3.24.1 of Phaser 3. No issues were displayed on iPhone or iPad. I need the latest version of Phaser since I am doing some advanced Spine graphics in my game.

I have only included one animation from my game that exhibits the issue, but the issue was appearing with also single image sprites, and even with particle effects. It appeared any image object or particle that had Phaser.BlendMode.ADD enabled exhibits this black "transparency" issue.

Example Test Code

This code is the absolute minimum needed to exhibit the issue:

"use strict";

// Create a new scene
var gameScene = new Phaser.Scene('Game');

// Load assets
gameScene.preload = function () {
    // Load images
    this.load.image('background', 'assets/background.png');

    this.load.multiatlas("spin_wave", "assets/e_spinwave.json", "assets/");
};

// Called once after preLoad ends
gameScene.create = function () {
    // Create BG Sprite
    let bg = this.add.sprite(0, 0, 'background');

    let gameW = this.sys.game.config.width;
    let gameH = this.sys.game.config.height;

    // Set Position
    bg.setPosition(gameW/2, gameH/2);

    this.anims.create({
        key: "spin_wave",
        frames: this.anims.generateFrameNames('spin_wave', {
            start: 0,
            end: 31,
            zeroPad: 3,
            prefix: 'e_spinwave_',
            suffix: '.png'
        }),
        frameRate: 15,
        yoyo: false,
        repeat: -1
    });

    // Gong Animation when triggering the 8th spin
    let spinWave = this.add.sprite(400,
        150,
        "spin_wave",
        "e_spinwave_000.png");
    spinWave.setOrigin(0.5, 0.5);
    spinWave.setBlendMode(Phaser.BlendModes.ADD);
    spinWave.anims.load("spin_wave");
    spinWave.anims.play("spin_wave");
    spinWave.setVisible(true);
};

// Set the configuration of the Game
let config = {
    type: Phaser.WebGL,  // Phaser will use WebGL if Available
    width: 640,
    height: 360,
    pixelArt: true,
    scene: gameScene
}

// Create a new game, pass the configuration
let game = new Phaser.Game(config);

Additional Information

Image captured from iPhone 12 Pro: image0

All files to get this example running: blend-pixelArt-issue.zip

photonstorm commented 1 year ago

This is (or was) a bug in iOS and outside of our control. Thankfully, Apple has since fixed it in iOS 15:

iPhone12Pro-iOS14 iPhone12Pro-iOS16 iPhone13Pro-iOS15