Jump to content

[CLOSED] Phaser 3.13.0 - Rendering Bug in WebGL?


jamespierce
 Share

Recommended Posts

EDIT Oct. 1st, 2018:  https://github.com/photonstorm/phaser/commit/5bdf9aa21b8ec424a607427ba163e17d0f20b434

EDIT Oct. 5th, 2018: A better way to create these fade-in transitions is to use: this.cameras.main.fadeIn()

-------------------------------------------------------------------------------------------

Since Phaser 3.12.0 and 3.13.0 I have this weird error:

phaser_error.png.a25d2c85879b65a9b93de187599210e7.png

This error / warning is not displayed in Phaser 3.11.0. With the exact same code, I just loaded an older Phaser version and no error / warning displayed whatsoever.

I did some research online and apparently this warning is shown when you render a texture before it was fully loaded into the cache. However, this error is thrown when I create a graphics object - and not a sprite or image - as follows:

let width = 288;
let height = 480;

let g = this.add.graphics({ x: 0, y: 0 });

g.fillStyle('0x000000'. 1);
g.fillRect(0, 0, width, height);

Does anyone know if this is a bug in the newer Phaser 3 versions (as of today: V 3.12.0 and V 3.13.0) or is it linked to a new feature that I'm handling wrong?

Thanks!

Link to comment
Share on other sites

What's the full code that reproduces this? As if I put the above on its own into a test, it doesn't error at all for me:

var config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    parent: 'phaser-example',
    backgroundColor: '#ffffff',
    scene: {
        create: create
    }
};

var game = new Phaser.Game(config);

function create ()
{
    let g = this.add.graphics({ x: 0, y: 0 });

    let width = 288;
    let height = 480;

    g.fillStyle(0x000000, 1);
    g.fillRect(0, 0, width, height);
}

I corrected the way you quoted the number value and removed the period before the number 1, but otherwise, the code above is the same.

Link to comment
Share on other sites

Thank you so much for the quick response @rich !

Apologies about the dot in my code snippet, that is a typo and was supposed to be a comma. And regarding the color code, I've tried it with all 3 variations and it still threw the error / warning: 0x000000, '0x000000', or '#000000'.

The exact place where it happens is here:
JS File: http://browsergameshub.com/gameapps/_dev/scenes/combat.js
Lines 103 - 106
this.veil is responsible for the error, namely this.veil.fillRect().

If I run the whole game with line 105 commented, such as
//this.veil.fillRect(0, 0, this._CONFIG.width, this._CONFIG.height);
there is no error.

To add to the confusion, I've just noticed that it doesn't happen in the PlayScene, where I am using graphics objects (rectangles) to create the UI background.

Early Alpha Dev Link: http://browsergameshub.com/gameapps/_dev/
You reach the CombatScene by successfully scanning for a monster. Once the CombatScene starts, said error / warning is thrown immediately in the console until this.veil is destroyed.

Side note:
It's obviously heavily Pokemon inspired: Walk around, find a monster, enter combat. A big difference is that combat will be done by answering vocabulary cards (language learning MMO).

Link to comment
Share on other sites

Right, so it has to be something else. I can't look through all the source, but do you do anything else with the Graphics object, like generateTexture from it? Or destroy it at some point?

There must be some combination of objects on the display list that causes it to lose its texture when it comes to rendering.

Link to comment
Share on other sites

I don't have the error in Firefox by the way, only in Chrome. So should I just ignore this error and wait until it's gone?

Anyways, here are some more details, if it helps you.

4 hours ago, rich said:

Do you do anything else with the Graphics object, like generateTexture from it? Or destroy it at some point?

I wasn't doing any of this. But to be absolutely sure, I stripped everything from the scene and still it's throwing the error. This here is virtually the whole code for the scene:

var CombatScene = new Phaser.Scene('Combat');

CombatScene.create = function()
{
	'use strict';
	
	let veil = this.add.graphics({ x: 0, y: 0 });
	veil.fillStyle(0x000000, 1);
	veil.fillRect(0, 0, 288, 480);
};

What's awkward is that when I use Phaser 3.11.0 (or earlier), there is no error. I get it only in Phaser 3.12.0 and 3.13.0.

What's even weirder is that if I create a second graphics object, there is no error for the second one... And on top of it, I'm using the graphics object in other scenes of the same game, without any errors.

4 hours ago, rich said:

There must be some combination of objects on the display list that causes it to lose its texture when it comes to rendering.

This is what I've been trying to figure out the last hours. First I thought maybe it is connected to the previous scene. However, when I remove veil.fillRect() from the CombatScene, there is no error - so it is definitely caused by the current scene. Still, I went ahead and also stripped out the graphics from the foregoing scene just to be absolutely sure - and yes the error persists... super weird.

What's even stranger is that the graphics object is properly rendered! The error says there is no texture bound, however the object renders as expected...

Final Note: The moment I run this.veil.destroy() it stops throwing the error.

Link to comment
Share on other sites

The error is a combination effect, so it's the result of something happening within the renderer and _then_ followed by the Graphics object. It isn't likely to be something obvious I'm afraid. Almost certainly something highly unexpected, or seemingly unrelated. So, if that's all the code you have in a Scene, it must be the combination of code in another Scene plus the above Scene causing it. What's the last thing the other Scene does?

Link to comment
Share on other sites

1 hour ago, rich said:

Also, could you please test the current master branch of version 3.14, because I've fixed a related bug which may have solved this one too.

I cannot find the version 3.14 on github. Do I have to use GIT or NPM to install it somehow? I've never done that before, I've always downloaded the newest Phaser version from your website directly: http://phaser.io/download/stable

phaser-github.thumb.png.3c4c8ad54ab3de36208a6da3e2e80ae6.png

I tried some other things in 3.13.0 that I'll summarize below. But if it's already fixed in 3.14.0 then better you don't waste more time on it until I can actually test it in 3.14.0 For completion's sake I still added my comments below, maybe it helps.

2 hours ago, rich said:

So, if that's all the code you have in a Scene, it must be the combination of code in another Scene plus the above Scene causing it. What's the last thing the other Scene does?

The last thing the previous scene does is:

  • Click the scan button to scan the nearby area for hidden monsters.
  • Make an Ajax call to ask the server if there was a monster within the scan radius.
  • Ajax callback: If a monster was found, go to the CombatScene.
PlayScene.clickScan = function()
{
    'use strict';
	
    if(!this.allow_input) return;
	
    // Flags
    this.allow_input = false;
	
    // Ask server if monster is nearby
    this.ajax.scanMonsters(this, this.player.ID, this.handleScanResponse);
};

PlayScene.handleScanResponse = function(result)
{
    'use strict';
	
    // Monster found
    if(result.data.monster)
    {
        this.scene.start('Combat');
    }
    // Nothing found
    else
    {
        this.allow_input = true;
        this.triggerAlert('Nothing found...', '#FF0000');
    }
};

Inconsistent Error on Startup:

I'm trying my best to encapsulate every single step but the results don't make any sense to me. For example, I've just cleared all my cache and then I was getting the exact same error upon initializing the Phaser app. However, the error was thrown just once and not multiple times like usually. Following that new error I've stopped my code after every moment where I rendered something on the canvas (images, sprites, graphics, text) to find what's causing it. There was no error. And now even when I'm clearing the whole cache again, there is no error anymore on start-up (booting the Phaser app). However, the error persists later on in the usual place where I'm using veil.fillRect().

Link to comment
Share on other sites

@rich The current version is playable online right here (I use it to test on different mobile devices): http://browsergameshub.com/gameapps/_dev/ At this URL you will notice that there are some other animations playing. I have already stripped out everything for testing all of the above things, I just didn't update the online files.

If you want a local version I will gladly set it up for you. It does need a server connection but I can adjust the local files to access my server for you. Let me know!

Link to comment
Share on other sites

@richI have finally pin-pointed where exactly the Ajax call is causing the error, however I still don't understand why. I also don't understand what any of this has to do with the Phaser 3 version because I'm still not getting any of these errors in 3.11.0 and before. To me it should not have anything to do with Phaser, but simply a mistake I'm doing somewhere.

And it appears that it doesn't matter whether I use the data from the server or not. What makes the error appear is simply waiting for the Ajax call to trigger the callback function... If I just execute the callback directly, there is no error. I added the comments towards the end of the code block below:
// No errors:
xhr.onload = xhrSuccess();
// With errors:
xhr.onload = xhrSuccess;

So obviously the difference is that in one case we wait for the server to respond and in the other we execute the callback immediately, not waiting for any server response. So it appears that this "waiting" is causing the no-texture-error. While waiting, the texture gets lost or something?

Ajax.prototype.getPlayerDataForCombat = function(ctx, id, callback)
{
	'use strict';
	
	let url = this.URL;
	
	// Send data
	let data = 'game=' + this.GAMENAME + '&p_id=' + id + '&req_type=get_player_data';
	
	// Result init
	let result = null;
	
	// Ajax call to get game from DB
	let xhr = new XMLHttpRequest();
	
	// Ajax callback functions
	function xhrSuccess()
	{
		callback.call(ctx, { success: true, error: false, data: {} });
	}
	
	function xhrError()
	{
		console.log('You have lost connection to the game server. Check your internet connection.');
		callback.call(ctx, result);
	}
	

	// HERE IS WHERE I CAN TOGGLE THE ERROR:
	// No errors:
	xhr.onload = xhrSuccess();
	// With errors:
	// xhr.onload = xhrSuccess;
    

	xhr.onerror = xhrError;
	
	xhr.open('POST', url, true);
	xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');	
	xhr.send(data);
};

 

Link to comment
Share on other sites

@rich Sorry for the multiple posts but I'm finally getting there. If I draw a graphics object in the Ajax callback function, the errors are thrown. Crucial is that I wait for the server response to execute the callback (see last comment above also). Note that it doesn't happen if I draw sprites (I tried, no errors) but only if I do this.veil.fillRect();

Edit: I tried it with some other display objects such as sprites, images and text, which were all error-free. I can confirm the errors only appear with graphics objects. The same happens if I tween a graphics object in the handlePlayerDataResponse() function: I can tween any object error free, only tweening an existing graphics object throws errors. The important detail is that these errors only appear if the callback function has to wait for some kind of response.

To summarize the last 2 posts: The error happens when I create new graphics objects, or tween existing graphics objects in a callback function that is executed after some kind of action / response has completed (such as an Ajax call).

CombatScene.create = function()
{
	'use strict';
	
	// Load player data from server
	// Code for this ajax function was posted in the previous comment
	this.ajax.getPlayerDataForCombat(this, this.P_ID, this.handlePlayerDataResponse);
};

CombatScene.handlePlayerDataResponse = function(result)
{
	'use strict';
	
	// THIS THROWS THE ERRORS IF WE WAIT FOR THE AJAX RESPONSE:
	// If we execute the callback immediately, no error
	this.veil	= this.add.graphics({ x: 0, y: 0 });
	this.veil.fillStyle(0x000000, 1);
	this.veil.fillRect(0, 0, this._CONFIG.width, this._CONFIG.height);
	this.veil.setDepth(this.DEPTH.veil);
};

 

Link to comment
Share on other sites

I guarantee it's because of when the callback is being invoked. It must be firing at a point during the game step or rendering process that is causing the display list to become out of sync. So as it iterates through the Game Object's it now suddenly has this new Graphics one to deal with, hasn't had a chance to bind the blank texture it needs, and errors during rendering.

I bet if, instead of actually creating the Graphics object in the callback, you just set a flag - and then during your main update loop you check for this flag, and if set, create the Graphics object, then it'd work fine because it would all be within the expected flow.

Link to comment
Share on other sites

So I did it like this, but it still throws the errors:

CombatScene.create = function()
{
	'use strict';
	
	// Load player data from server
	this.ajax.getPlayerDataForCombat(this, this.P_ID, this.handlePlayerDataResponse);
};

CombatScene.handlePlayerDataResponse = function(result)
{
	'use strict';
	
	this.trigger_intro	= true;
};

CombatScene.update = function()
{
	'use strict';
	
	if(this.trigger_intro)
	{
		this.trigger_intro = false;
		
		let veil = this.add.graphics({ x: 0, y: 0 });
		veil.fillStyle(0x000000, 1);
		veil.fillRect(0, 0, this._CONFIG.width, this._CONFIG.height);	
		veil.setDepth(this.DEPTH.veil);
	}
};

 

However I did find a workaround for my situation by using an image: I created a black rectangle image and I use that instead of the graphics object.

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

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