Guide to Upgrade MV to PIXI v5

LTN Games

Code Sorcerer
Veteran
Joined
Jun 25, 2015
Messages
690
Reaction score
587
First Language
English
Primarily Uses
RMMV
I created a small guide for those who want to tackle upgrading their projects to PIXI v5. This guide includes the js files from a working upgraded version of MV.

What changes does PIXI v5 bring?
  • WebGL 2
  • Performance improvements
  • Batch rendering
  • Graphics now as fast as Sprites
  • and more..
Compatibility

This upgrade still requires more investigation and it is highly likely this upgrade will break plugins or cause memory leaks due to some of the changes made.
  • pixi-pictures is incompatible with pixi v5, so blend modes will be disabled for all pictures.
    • TilingSprite now uses PIXI's built in PIXI.TilingSprite class
  • It appears the WindowLayer class is broken so a quick fix has been applied, unfortunately it may cause unintended behavior to plugins and the way all windows are drawn.
    • Although tested with a few plugins and no issues arised

Download And Guide

Report Issues
Feel free to report any issues you have here in this thread, while I am not going to be tech support for you, it will be good to have a list of any possible issues for when I do decide to investigate the upgrade further.
 
Last edited:

Jonforum

Veteran
Veteran
Joined
Mar 28, 2016
Messages
1,617
Reaction score
1,426
First Language
French
Primarily Uses
RMMV
Dont forget migration guide here for track new change
 

LTN Games

Code Sorcerer
Veteran
Joined
Jun 25, 2015
Messages
690
Reaction score
587
First Language
English
Primarily Uses
RMMV
Ah Yes the migration guide, I have a link in the article on my website but I should add it to the main thread as well, thanks for mentioning it.
 

ImaginaryVillain

Now A YouTube Cool Kid! =D
Veteran
Joined
Jun 22, 2019
Messages
631
Reaction score
2,703
First Language
Absurdism
Primarily Uses
RMMV
So I made two new projects, one with your code (Project 5) and one without (Project 6).... I changed
only the screenWidth and screenHeight properties in the Community basic plugin to 1280x720 in both projects and got these results. If you're curious Yanfly's Core Engine also does the same if you change the resolution in that.
project5.jpg

project6.jpg

Everything else appears to work fantastically so far. Thanks! :LZSexcite:
 

LTN Games

Code Sorcerer
Veteran
Joined
Jun 25, 2015
Messages
690
Reaction score
587
First Language
English
Primarily Uses
RMMV
Awesome thanks for the report, I'll be sure to take a look at it when I get the chance. I'm assuming it has to do with me messing with the renderer part of the codebase. I added a resolution and autoDensity option while I was fooling around and never changed it back before submitting the guide.
 

ImaginaryVillain

Now A YouTube Cool Kid! =D
Veteran
Joined
Jun 22, 2019
Messages
631
Reaction score
2,703
First Language
Absurdism
Primarily Uses
RMMV
Ah okay, I commented out...
autoDensity: true
...in rpg_core

And the problem appears to be resolved.

Now the only problems I seem to encounter are poor Terrax Lighting only applying itself to the player and not events now... And some strange error with one red PIXI font displaying as black when all the others work perfectly. Still for such an upgrade, I was expecting way more problems. :LZSexcite:
 

DoubleX

Just a nameless weakling
Veteran
Joined
Jan 2, 2014
Messages
1,617
Reaction score
671
First Language
Chinese
Primarily Uses
N/A
I've tried to follow your guide and it does drastically increase the performance in my android phone.
However, after updating Pixi to v5 this way, showing a message will usually just show the 1st character, despite the fact that Bitmap.prototype.drawText has drawn all characters.
While I suspect that it's because the same canvas can't be drawn too frequently, I still have no idea what's really going on at all, I'd like your help :)
 
Last edited:

LTN Games

Code Sorcerer
Veteran
Joined
Jun 25, 2015
Messages
690
Reaction score
587
First Language
English
Primarily Uses
RMMV
Hey thanks for the report, Interesting it only renders the first few characters especially considering menu's appear to render fine, sounds like another WindowLayer/Window issue, possibly not updating or being stopped by something. Anyway, I've been really busy but I'll defenitly take a deeper look at this once I get the chance/free time.
 

DoubleX

Just a nameless weakling
Veteran
Joined
Jan 2, 2014
Messages
1,617
Reaction score
671
First Language
Chinese
Primarily Uses
N/A
Hey thanks for the report, Interesting it only renders the first few characters especially considering menu's appear to render fine, sounds like another WindowLayer/Window issue, possibly not updating or being stopped by something. Anyway, I've been really busy but I'll defenitly take a deeper look at this once I get the chance/free time.
Thanks to your reply, I've figured somethig out :D

I've added the following log to Window_Base.prototype.processNormalCharacter:
JavaScript:
Window_Base.prototype.processNormalCharacter = function(textState) {
    var c = textState.text[textState.index++];
    var w = this.textWidth(c);
    console.info("Window_Base.prototype.processNormalCharacter", textState, c, w);
    this.contents.drawText(c, textState.x, textState.y, w * 2, textState.height);
    textState.x += w;
};
I've also changed the following in Window_Message.prototype.updateMessage:
JavaScript:
Window_Message.prototype.updateMessage = function() {
    if (this._textState) {
        while (!this.isEndOfText(this._textState)) {
            if (this.needsNewPage(this._textState)) {
                this.newPage(this._textState);
            }
            this.updateShowFast();
            this.processCharacter(this._textState);
            // This part's changed
            if (!this._showFast && !this._lineShowFast) {
                console.info("Window_Message.prototype.updateMessage !this._showFast && !this._lineShowFast");
                // Removing this seems to partially solve the apparent issues
                // break;
                //
            }
            if (this.pause || this._waitCount > 0) {
                console.info("Window_Message.prototype.updateMessage this.pause || this._waitCount > 0");
                // Removing this seems to partially solve the apparent issues
                // break;
                //
            }
            //
        }
        if (this.isEndOfText(this._textState)) {
            this.onEndOfText();
        }
        return true;
    } else {
        return false;
    }
};
While both versions of Window_Message.prototype.updateMessage causes Window_Base.prototype.processNormalCharacter to show the exact same 15 logs(from the 1st 1 to the last 3 with everything logged as correct), the version with some codes commented out can show all characters(also with 15 logs in Window_Message.prototype.updateMessage), while the original one only shows the 1st character.

As for the root cause, I think that the window's updating just fine, otherwise those log added my mine wouldn't be able to log all the 15 characters to be drawn. The difference between the original version and mine is that, the original one draws each character per frame, while mine draws all characters in the same frame, even though they're still drawn one by one.
Also, as Bitmap.prototype.drawText just uses strokeText and fillText from a CanvasRenderingContext2D dom, which doesn't seem to have anything to do with Pixi directly, I wonder if Pixi 5.3.0 has subtly changed some CanvasRenderingContext2D behaviors, causing it to fail to keep drawing in consecutive frames.

Edit: After some more investigation, I think I've finally found the root causes of the issue.
It's that, after every Bitmap draw, be it text, fill rect, blt, etc, the bitmap will become dirty.
Normally, this._baseTexture.update() should be called for the bitmap when it becomes dirty, then that bitmap should become clean again, so subsequent drawing will be allowed.

In Pixi 4.5.4, it's done by calling Sprite.prototype._renderWebGL and TilingSprite.prototype.renderWebGL per frame(the former can be called multiple times per frame).

In Pixi 5.3.0, however, none of them are ever called at all, causing a dirty bitmap to never update its base texture nor become clean again, thus preventing subsequent drawing(that's probably because of _renderWebGL becoming _render and renderWebGL becoming render, which is mentioned in the v5 migration guide).

That's why, drawing everything on the same bitmap all at once on the same frame works fine(the same applies to those window drawings involving creating a new bitmap altogether via createContents), while drawing little by little on consecutive frames fail.

So I'm proposing these additional changes:
rpg_core.js(Around line 4331) -
From:
JavaScript:
Sprite.prototype._renderWebGL_PIXI = PIXI.Sprite.prototype._renderWebGL;
To:
JavaScript:
Sprite.prototype._render_PIXI = PIXI.Sprite.prototype._render;
rpg_core.js(Around line 5935) -
From:
JavaScript:
TilingSprite.prototype._renderWebGL_PIXI = PIXI.extras.PictureTilingSprite.prototype._renderWebGL;
To:
JavaScript:
TilingSprite.prototype._render_PIXI = PIXI.extras.PictureTilingSprite.prototype._render;
Change Sprite.prototype._renderWebGL in rpg_core.js(Around line 4381) to this:
JavaScript:
/**
* @method _render
* @param {Object} renderer
* @private
*/
Sprite.prototype._render = function(renderer) {
    if (this.bitmap) {
        this.bitmap.touch();
    }
    if(this.bitmap && !this.bitmap.isReady()){
        return;
    }
    if (this.texture.frame.width > 0 && this.texture.frame.height > 0) {
        if (this._bitmap) {
            this._bitmap.checkDirty();
        }

        //copy of pixi-v4 internal code
        this.calculateVertices();

        if (this.pluginName === 'sprite' && this._isPicture) {
            // use heavy renderer, which reduces artifacts and applies corrent blendMode,
            // but does not use multitexture optimization

            // Edited by DoubleX on GMT 0800 5-Jul-2020 to stop using blend which isn't supported in v5
            // this._speedUpCustomBlendModes(renderer); // Blend's not supported in v5.3.0
            //
         
            // Edited by DoubleX on GMT 0800 5-Jul-2020 to use batch renderer instead
            // renderer.setObjectRenderer(renderer.plugins.picture);
            renderer.batch.setObjectRenderer(renderer.plugins.picture);
            //

            renderer.plugins.picture.render(this);
        } else {
            // use pixi super-speed renderer
         
            // Edited by DoubleX on GMT 0800 5-Jul-2020 to use batch renderer instead
            // renderer.setObjectRenderer(renderer.plugins[this.pluginName]);
            renderer.batch.setObjectRenderer(renderer.plugins[this.pluginName]);
            //

            renderer.plugins[this.pluginName].render(this);
        }
        //
    }
};
Change TilingSprite.prototype._renderWebGL in rpg_core.js(Around line 6097) to this:
JavaScript:
/**
* @method _render
* @param {Object} renderer
* @private
*/
TilingSprite.prototype._render = function(renderer) {
    if (this._bitmap) {
        this._bitmap.touch();
        this._bitmap.checkDirty();
    }

    // Edited by DoubleX on GMT 0800 5-Jul-2020 to stop using blend which isn't supported in v5
    // this._speedUpCustomBlendModes(renderer);
    //

    this._render_PIXI(renderer);
};
P.S.: Because the default pixi filter padding has changed from 4 to 0 in v5, I wonder if these are needed as well:
JavaScript:
Sprite.voidFilter.padding = 4;
WindowLayer.voidFilter.padding = 4;
ToneFilter.padding = 4;
P.S.S.: I've just uploaded the rpg_core.js withh my additional changes :p
 

Attachments

Last edited:

ImaginaryVillain

Now A YouTube Cool Kid! =D
Veteran
Joined
Jun 22, 2019
Messages
631
Reaction score
2,703
First Language
Absurdism
Primarily Uses
RMMV
Thanks! This fixed the issues Terrax Lighting and SRD HUDMaker had with the update. Though so far PIXI text displays incorrectly as evidenced in the screenshots. Same font information, though this bug isn't from the most recent changes, it's been present since the initial changes.
 

Attachments

LTN Games

Code Sorcerer
Veteran
Joined
Jun 25, 2015
Messages
690
Reaction score
587
First Language
English
Primarily Uses
RMMV
@DoubleX Thank you for hunting down the problem, it saves me from trying to find some free time and do it, you're a godsend! I'll be sure to add you as a contributor on the original guide once I update it.

Now all that is left is getting the original WindowLayer class working correctly, I spent about 45minutes when I first wrote the guide but couldn't dig in any further. Mind you, the original WindowLayer class is nothing special, its just to prevent windows from being shown behind other windows.
 

DoubleX

Just a nameless weakling
Veteran
Joined
Jan 2, 2014
Messages
1,617
Reaction score
671
First Language
Chinese
Primarily Uses
N/A
@DoubleX Thank you for hunting down the problem, it saves me from trying to find some free time and do it, you're a godsend! I'll be sure to add you as a contributor on the original guide once I update it.

Now all that is left is getting the original WindowLayer class working correctly, I spent about 45minutes when I first wrote the guide but couldn't dig in any further. Mind you, the original WindowLayer class is nothing special, its just to prevent windows from being shown behind other windows.
I didn't notice any issue with WindowLayer yet, but it seems that, with my fix added, the performance boost from upgrading to Pixi v5.3.0 isn't as drastic as before, maybe it's because such "drastic" improvement partially come up the fact that the upgrade was somehow incomplete.
In my case, before my fix, I can reach 45+fps in battle most of the time with my snapdragon 450 phone(with the dirty bitmap problem of course), but with my fix, 40fps is all I got.
While it's still definitely a significant improvement from 30fps in v4.5.4, I wonder if further optimization in rpg_core.js can be done along with the v5.3.0 upgrade :)
 

ImaginaryVillain

Now A YouTube Cool Kid! =D
Veteran
Joined
Jun 22, 2019
Messages
631
Reaction score
2,703
First Language
Absurdism
Primarily Uses
RMMV
So I have two versions of my game at this point, one using the changes here, and the other using PIXI 4.8.9... Granted because I use excessive amounts of PIXI particles and random map creation on the fly, it's going to be way more CPU intensive than most people's stuff.

That being said, the PIXI 5.3 game appears to use excessively more CPU than the 4.8.9 one. To the point where it starts maxing out cores over time where the 4.8.9 version is stable. There's so many X factors... This probably isn't the most useful report, but it did mean I had to switch back to using 4.8.9.

As for the PIXI Text problem from earlier, the fill property appears to simply do the wrong colors, and drop shadow no longer works at all. As far as I can tell the other font properties work fine.
 

DoubleX

Just a nameless weakling
Veteran
Joined
Jan 2, 2014
Messages
1,617
Reaction score
671
First Language
Chinese
Primarily Uses
N/A
I've just tested the memory leak issue with my adaption on Pixi v5.3.0, and I'm surprised that it can leak as much as 50 - 61 MB per battle.
Until I can drastically reduce the leak to something like 2MB per battle or there's such a fix already, I don't think the 5 FPS boost in my phone's worth such leaks, so for now I've reverted back to Pixi v4.5.4 :)
 

ImaginaryVillain

Now A YouTube Cool Kid! =D
Veteran
Joined
Jun 22, 2019
Messages
631
Reaction score
2,703
First Language
Absurdism
Primarily Uses
RMMV
Ouch yeah, just a tiny leak there. You should really check out 4.8.9 it works out of the box with MV, and has drastic performance improvements over 4.5.4.
 

LTN Games

Code Sorcerer
Veteran
Joined
Jun 25, 2015
Messages
690
Reaction score
587
First Language
English
Primarily Uses
RMMV
@ImaginaryVillain Odd that CPU usage is more and @DoubleX I assumed a memory leak was possible and I think both issues are related to the WindowLayer class which is broken. The temp fix I did in the guide was to simply add the window directly to the scene but was in no way a permanent solution. I'm hoping to have free time next week to dig into this further and attempt a more appropriate fix for the WindowLayer class but for now I need to continue work on my lighting plugin and other projects. Don't worry though this is definitely on my list of things I want to do.
 

DoubleX

Just a nameless weakling
Veteran
Joined
Jan 2, 2014
Messages
1,617
Reaction score
671
First Language
Chinese
Primarily Uses
N/A
@LTN Games
As you've hinted that the memory leaks comes from WindowLayer, I've took a look on that, and the following's my progress so far:
rpg_scene.js -
JavaScript:
/**
* Create the layer for the windows children
* and add it to the rendering process.
*
* @method createWindowLayer
* @instance
* @memberof Scene_Base
*/
Scene_Base.prototype.createWindowLayer = function() {
    var width = Graphics.boxWidth;
    var height = Graphics.boxHeight;
    var x = (Graphics.width - width) / 2;
    var y = (Graphics.height - height) / 2;
    // Edited by DoubleX On GMT 0200 9-Jul-2020 to use back the WindowLayer
    this._windowLayer = new WindowLayer();
    // this._windowLayer = new PIXI.Container();
    this.addChild(this._windowLayer);
};

/**
* Add the children window to the windowLayer processing.
*
* @method addWindow
* @instance
* @memberof Scene_Base
*/
Scene_Base.prototype.addWindow = function(window) {
    // Edited by DoubleX On GMT 0200 9-Jul-2020 to use back the WindowLayer
    // this.addChild(window);
    this._windowLayer.addChild(window);
    //
};
rpg_core.js -
JavaScript:
/**
* @method _render
* @param {Object} renderSession
* @private
*/
WindowLayer.prototype._render = function(renderer) {
    if (!this.visible || !this.renderable) {
        return;
    }

    if (this.children.length==0) {
        return;
    }

    renderer.batch.flush();
    this.filterArea.copyFrom(this);

    // Removed by DoubleX on GMT 0200 9-Jul-2020 to stop flooding the console
    // console.log(this.filterArea.copyFrom(this))
    //

    renderer.filter.push(this, this.filters);
    renderer.batch.currentRenderer.start()

    var shift = new PIXI.Point();
    var rt = renderer.projection
    var projectionMatrix = rt.projectionMatrix;
    shift.x = Math.round((projectionMatrix.tx + 1) / 2 * rt.sourceFrame.width);
    shift.y = Math.round((projectionMatrix.ty + 1) / 2 * rt.sourceFrame.height);
    for (var i = 0; i < this.children.length; i++) {
        var child = this.children[i];
        if (child._isWindow && child.visible && child.openness > 0) {
            renderer.mask.enableScissor = true
            this._maskWindow(child, shift);
           
            // Removed by DoubleX on GMT 0200 9-Jul-2020 to reduce memory leaks
            // const data = new PIXI.MaskData(new PIXI.Sprite(renderer.generateTexture(this._windowMask)))
            // data._target = this
            //
            // Removed by DoubleX on GMT 0200 9-Jul-2020 to fix the window not drawing issue
            // renderer.mask.pushSpriteMask(data);
            //
            // Edited by DoubleX on GMT 0200 9-Jul-2020 to stop the gl from clearing the whole screen
            // renderer.clear();
            renderer.renderTexture.bind();
            renderer.renderTexture.clear(undefined, renderer.mask);
            //
            // Removed by DoubleX on GMT 0200 9-Jul-2020 to fix the window not drawing issue
            // renderer.mask.popSpriteMask();
            //

            renderer.batch.currentRenderer.start();
            child.render(renderer);
            renderer.batch.flush();
        }
    }
    renderer.batch.currentRenderer.flush();
    renderer.filter.pop();
   
    // Removed by DoubleX on GMT 0200 9-Jul-2020 to avoid crash by redundant pops
    // renderer.mask.popSpriteMask();
    //

    for (var j = 0; j < this.children.length; j++) {
        if (!this.children[j]._isWindow) {
            this.children[j].render(renderer);
        }
    }
};
While it's leaking even more memory than before, at least it seems to me that these changes make WindowLayer working again.
Right now the issue of this fix is that, calling renderer.renderTexture.clear() will clear literally everything on the screen, but not doing so will lead to memory leaks.
Unfortunately, I think that I've reached my dead ends there for now, so I'd better off just sharing my progress here :)
 

ImaginaryVillain

Now A YouTube Cool Kid! =D
Veteran
Joined
Jun 22, 2019
Messages
631
Reaction score
2,703
First Language
Absurdism
Primarily Uses
RMMV
That really seems to be the most exciting thing about MZ, looking at the code and see exactly what they did with well... everything. :LZSwink:
 

Hudell

Dog Lord
Veteran
Joined
Oct 2, 2014
Messages
3,395
Reaction score
3,239
First Language
Java's Crypt
Primarily Uses
RMMV
I did tell you that your windowlayer changes would cause leaks, right? I think it may have been in a different thread but I remember something like that
 

Users Who Are Viewing This Thread (Users: 0, Guests: 1)

Latest Threads

Latest Profile Posts

I'm having a fun time working with the MZ RTP. The waterfall hasn't changed, though, so I'm wondering if they didn't make a new one or if they forgot to put it in...

good progress on the typescript Definitions files almost done all the Manager and yet I still have to do the Battle Manager...who is seriously so much data lol
Are the export options for MZ known yet?
I thought they were supposed to be my friends T_T
Anyone else ever feel bad about always needing to ask for help on their game..?

Forum statistics

Threads
100,642
Messages
978,058
Members
132,259
Latest member
RegularManGuy
Top