[Bug] [FIX INSIDE] Text and actor faces extremely blurry sometimes due to non-integer coordinates

rpg_el

Veteran
Veteran
Joined
Sep 3, 2020
Messages
83
Reaction score
35
First Language
English
Primarily Uses
RMMZ
I noticed that possibly any sort of text, and actor faces, can(!) be extremely blurry sometimes due to non-integer coordinates. It depends on screen resolution, the exact dialog, and it's way more visible when disabling the final canvas scaling smoothing like this (not part of the fix, just to help you look at it if you're curious):

JavaScript:
/* USE THIS ONLY TO HELP YOU SEE THE ISSUE OF BLURRINESS, NOT MEANT AS A "FIX" / TO BE INTEGRATED */
(() => {
    const _orig_Graphics_createCanvas = Graphics._createCanvas;
    Graphics._createCanvas = function() {
        let result = _orig_Graphics_createCanvas.apply(
            this, arguments
        );
        this._canvas.style["image-rendering"] = "pixelated";
        return result;
    };
})();
I have managed to fix almost all blurriness with the following plugin code which should also be a helpful guide where in the corescript all these things need to be fixed. This code should be considered public domain, and I would be very happy if the MZ developers looked at this to see how it needs to be fixed. No credit of any kind is required, I just want this fixed for as many games as possible. (Because once you notice how blurry some fonts and faces are, it'll annoy you too!)

JavaScript:
(() => {
    Window_Base.prototype.drawFace = function(
        faceName, faceIndex, x, y, width, height
    ) {
        // FIX: drawFace doesn't round sx/sy coordinates here,
        // which may cause them to be blurry at some sizes.
        // This is a copy of the original code with two lines fixed as marked below:
        width = width || ImageManager.faceWidth;
        height = height || ImageManager.faceHeight;
        const bitmap = ImageManager.loadFace(faceName);
        const pw = ImageManager.faceWidth;
        const ph = ImageManager.faceHeight;
        const sw = Math.min(width, pw);
        const sh = Math.min(height, ph);
        const dx = Math.floor(x + Math.max(width - pw, 0) / 2);
        const dy = Math.floor(y + Math.max(height - ph, 0) / 2);
        const sx = Math.round((faceIndex % 4) * pw + (pw - sw) / 2);  // FIXED.
        const sy = Math.round(Math.floor(faceIndex / 4) * ph + (ph - sh) / 2);  // FIXED.
        this.contents.blt(bitmap, sx, sy, sw, sh, dx, dy);
    };
    const _Bitmap_measureTextWidth = Bitmap.prototype.measureTextWidth;
    Bitmap.prototype.measureTextWidth = function(text) {
        // FIX: this function is used in 99% of cases for UI placement.
        // Not all UI placement rounds this number before using it,
        // which results in lots of corner cases with blurry elements.
        // Since nothing seems to rely on it returning the exact float,
        // I think this should be changed to just always return rounded ints.
        let result = _Bitmap_measureTextWidth.apply(this, arguments);
        return Math.round(result);
    };
    const _orig_Graphics_centerElement = Graphics._centerElement;
    Graphics._centerElement = function(element) {
        // FIX: canvas element should be sized to rounded
        // integers, or all the canvas contents can be extra blurry.
        // The original code doesn't ensure this after applying the
        // floating point scaler named this._realScale internally.
        let result = _orig_Graphics_centerElement.apply(
            this, arguments
        );
        const width = Math.max(0,  // FIXED COMPUTATION based on original one
            Math.floor(element.width * this._realScale)
        );
        const height = Math.max(0,
            Math.floor(element.height * this._realScale)
        );
        element.style.width = width + "px";
        element.style.height = height + "px";
        return result;
    };
    const _orig_Bitmap_drawText = Bitmap.prototype.drawText;
    Bitmap.prototype.drawText = function(text, x, y, maxWidth, lineHeight, align) {
        // FIX: force drawText to always draw at integer coordinates!
        // The original code will happily draw blurry text at floating
        // point coordinates. I think the original function should be changed
        // to just always round the coordinates it gets passed.
        try {
            x = Math.round(x);
            y = Math.round(y);
            maxWidth = Math.round(maxWidth);
            lineHeight = Math.round(lineHeight);
        } catch (e) {
            //
        }
        return _orig_Bitmap_drawText.apply(
            this, [text, x, y, maxWidth, lineHeight, align]
        );
    }
    Window_MenuStatus.prototype.drawItemStatus = function(index) {
        // FIX: drawItemStatus should round the y coordinate, due to the 1.5 float spacer:
        const actor = this.actor(index);
        const rect = this.itemRect(index);
        const x = rect.x + 180;
        const y = Math.round(  // FIXED
            rect.y + rect.height / 2 - this.lineHeight() * 1.5
        );
        this.drawActorSimpleStatus(actor, x, y);
    };
    const _orig_Scene_Base_createWindowLayer = (
        Scene_Base.prototype.createWindowLayer
    );
    Scene_Base.prototype.createWindowLayer = function() {
        // FIX: windowLayer needs to be on integer coordinates always,
        // or all the windows inside will be blurry. The original code
        // doesn't ensure this especially with uneven UI area resolutions.
        let result = _orig_Scene_Base_createWindowLayer.apply(
            this, arguments
        );
        this._windowLayer.x = Math.round(
            (Graphics.width - Graphics.boxWidth) / 2
        );
        this._windowLayer.y = Math.round(
            (Graphics.height - Graphics.boxHeight) / 2
        );
        return result;
    };
    const _orig_Scene_Options_optionsWindowRect = (
        Scene_Options.prototype.optionsWindowRect
    );
    Scene_Options.prototype.optionsWindowRect = function() {
        // FIX: the options window rect must be integer sized,
        // or it will be rendered blurry. The original code doesn't
        // ensure this especially with uneven UI area resolutions.
        let rect = _orig_Scene_Options_optionsWindowRect.apply(
            this, arguments
        );
        rect.x = Math.round(rect.x);
        rect.y = Math.round(rect.y);
        rect.width = Math.round(rect.width);
        rect.height = Math.round(rect.height);
        return rect;
    };
})();
It would be really lovely if this could be fixed in the core script. Because I want to play random people's games without blurry fonts! So please take all of this you need, devs anywhere, and make this issue go away.
 

Soaprman

Villager
Member
Joined
Aug 20, 2018
Messages
6
Reaction score
5
First Language
English
Primarily Uses
RMMV
Thanks for this! I've been wondering about some of the blurry stuff, particularly gauge numbers (they look different on the main menu vs. the status menu, for example). This seems to fix that for me.
 

rpg_el

Veteran
Veteran
Joined
Sep 3, 2020
Messages
83
Reaction score
35
First Language
English
Primarily Uses
RMMZ
It doesn't fix all instances of blurriness since as you can see from the plugin it's just a huge bunch of accidental lack of rounding of coordinates, so there are probably more instances of this in some places. (E.g. the "Game End" menu with the "To Title"/"Cancel" entries is still blurry and I haven't managed to find the particular rounding problem causing this one just yet.) But it should fix most at least, so I really hope the ones that the list in the above plugin will be fixed in the core soon. Only by fixing it in the core will it ensure that most user games will actually ship with the fixes, hence not giving the poor players eyestrain looking at it.
 

coyotecraft

Veteran
Veteran
Joined
Mar 13, 2012
Messages
150
Reaction score
94
First Language
English
Primarily Uses
I wonder if this is related to another graphic issue. Depending on the height of window, the Status Icons sometime render with the row of pixels of the icon below it on the icon sheet. 32x33 instead of 32x32. The facesets and guages are slightly blurry.
It did this whenever the height value was an Odd number. But I couldn't explain why.

And I fixed it by changing the UI Area Height in System 2 to 622.
 

rpg_el

Veteran
Veteran
Joined
Sep 3, 2020
Messages
83
Reaction score
35
First Language
English
Primarily Uses
RMMZ
@coyotecraft yes it is it likely is, and indeed the icons rendering on uneven floating point boundaries sadly is also one of the bugs I haven't managed to track down yet. That definitely happens even with my patch above, and it definitely messes up the bottom 1px row of the icons sometimes does something wrong to it in some way which might be what you're seeing, I've seen things too. (pixi.js also sometimes renders it with proper_height integer at the left side, proper_height + 1 integer at the right side, making it all slanted on top of being blurry.) Once I get around to tracking that down I will update it here, but finding these math errors is quite time consuming so that so far I only dealt with the really eye-hurting ones, which mainly was all the fonts and the portraits.

Edit: well, to be fair I don't know for 100% sure if your issue with the 1px logo row is caused by a bug like this, but it seems very likely - I've only seen it rendered slanted, but I believe instantly also the contents being 1px off is a possible outcome.
 

The Row

Veteran
Veteran
Joined
Mar 2, 2016
Messages
93
Reaction score
68
First Language
Swedish
Primarily Uses
Just a random guess: Some of the blur couldn't be due to the fact that the game res and the gui res is diffrent? (As in 2 diffrent values)
Had huge problems with aligning stuff compared to MV, and this is the only thing I can think of, unless they set new cordinates for all the ingame windows (some which they did, new menu and all that...)
Show msg for instance is not at the bottom of the screen anymore, but hovers 1-2 pixels above the window border, as well as having some blank space around it. And it is set to be 816 px.
If the gui scaled and is 1.3 or 1.4 pixels off, or something along those lines, that would cause a lot of odd problem, no?
Seen a few places were things looks off by 1-2 pixels, when trying to align text and choice windows. And so far everything point to the whole gui being scalled 2-4 pixels smaller than the given value.

Sorry, not a programmer so I can't look these things up, I can just see whats in front of me and point at it.
 

rpg_el

Veteran
Veteran
Joined
Sep 3, 2020
Messages
83
Reaction score
35
First Language
English
Primarily Uses
RMMZ
@The Row for what it's worth, at least to my knowledge, game res and gui res being different doesn't by itself break things. (But it's not like I investigated this a lot, it's also not directly relevant to the blurriness I don't think) Although if you make the gui res smaller than the game res, you will (naturally) have a gui that no longer fills the screen. And uneven gui res does trigger a few bugs, as well as the layouting generally not liking if you pick a way smaller or way bigger res than the default. Generally, the layouting code seems to just not be prepared for things resizing all too much. But this is a different issue to the one we're discussing here, which is the very concrete bug of things being put on a 0.5px in-beween position causing lots of annoying blurriness and off-by-one drawing bugs. If you want to discuss other layouting things, that would probably go best into a separate thread.

If the gui scaled and is 1.3 or 1.4 pixels off, or something along those lines, that would cause a lot of odd problem, no?
I don't think the UI is ever scaled, it is just layouted smaller if you make it smaller
 
Last edited:

The Row

Veteran
Veteran
Joined
Mar 2, 2016
Messages
93
Reaction score
68
First Language
Swedish
Primarily Uses
@The Row for what it's worth, at least to my knowledge, game res and gui res being different doesn't by itself break things. (But it's not like I investigated this a lot, it's also not directly relevant to the blurriness I don't think) Although if you make the gui res smaller than the game res, you will (naturally) have a gui that no longer fills the screen. And uneven gui res does trigger a few bugs, as well as the layouting generally not liking if you pick a way smaller or way bigger res than the default. Generally, the layouting code seems to just not be prepared for things resizing all too much. But this is a different issue to the one we're discussing here, which is the very concrete bug of things being put on a 0.5px in-beween position causing lots of annoying blurriness and off-by-one drawing bugs. If you want to discuss other layouting things, that would probably go best into a separate thread.

I don't think the UI is ever scaled, it is just layouted smaller if you make it smaller
Good to know, as I said in my post, I am no programer so I don't even know were to look at these things, just thought I should point it out as I notised the msg window, among others being smaller than the res set in the database. (which they weren't in MV, msg window there went from edge to edge.)
I honestly thought it could be a culprit for the blur.

Well, that is one potential culprit marked off.
I wish you luck with finding the real one. Or better yet, the devs figuring it out and fixing it.
 

rpg_el

Veteran
Veteran
Joined
Sep 3, 2020
Messages
83
Reaction score
35
First Language
English
Primarily Uses
RMMZ
@The Row I did find the culprit for most of the blur, see the plugin code in the first post :kaoluv: you can just add it into your project and the blur will be gone! so basically the devs just need to patch that into the core script and done
 

coyotecraft

Veteran
Veteran
Joined
Mar 13, 2012
Messages
150
Reaction score
94
First Language
English
Primarily Uses
Your script does indeed fix the blur. As well as the issue I had with it with the status icons.
However I recently noticed a problem with the window boxes too.
It does the same thing it did with the status icons, but it's the right edge of the window box. Picking up part of what should be the left board frame. Similar to the status icon problem I described.
It's really only noticeable against certain backgrounds, but it's there on some window boxes but not others depending on the dimensions, as best as I can tell.
 

Archeia

Level 99 Demi-fiend
Developer
Joined
Mar 1, 2012
Messages
15,138
Reaction score
15,464
First Language
Filipino
Primarily Uses
RMMZ
Can you give me a small test project (bare minimum resources) where this can be emulated 100%?
It's just easier to bring it up to dev team and test it ourselves.
 

coyotecraft

Veteran
Veteran
Joined
Mar 13, 2012
Messages
150
Reaction score
94
First Language
English
Primarily Uses
I can proved some test graphics to better illustrate it. Of course, screenshots don't help if they're not viewed at 100%.
I suppose the border thing might be unrelated. Rpg_el's script fixes the window contents but not the window.
I know it's not just me because it's there in the promotional screenshots as well, so they've already 100% "emulated" it.

 

Archeia

Level 99 Demi-fiend
Developer
Joined
Mar 1, 2012
Messages
15,138
Reaction score
15,464
First Language
Filipino
Primarily Uses
RMMZ
Thank you everyone and especially @coyotecraft for taking your time to send me some test graphics. I just want to be sure I'm seeing the issue before submission. We're still investigating this issue!


EDIT:
Temporarily we added a better fix in VisuStella Core Engine while we wait for an official fix.
 
Last edited:

Xelion

Veteran
Veteran
Joined
Apr 18, 2012
Messages
86
Reaction score
113
First Language
Spanish
VisuStella's fix (or using the code provided by rpg_el) actually breaks my message boxes, making a weird graphical glitch when in some cases, in my message popups, graphics are showing 1 pixel from the left (I don't know how to explain it).


Bug.png


This is GALV's Message plugin but I tried with Gabe's and it's exactly the same result, depending on the width of the text/width of the message, so sometimes it looks fine.
This is probably the same or a similar problem to what coyotecraft said.

Anyway, I had to go back to an earlier VisuStella core version which didn't provide this fix, sadly.

Edit: after reading the whole thread I realize this problem was already discovered. In my case I'm using a pixelate plugin so I don't suffer the blur problem, but only the problem shown above that disappears as long as I don't use that related code (if I deactivate the pixelate plugin, both the blur and the above problem appear)
 
Last edited:

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

Latest Threads

Latest Posts

Latest Profile Posts

Just finished composing a boss battle theme!
Scripted a multi-variable weather system that randomizes wind speed, cloudiness, rain, fogginess, etc, while attempting to realistically account for interactions between them (e.g. wind speed affects fogginess, cloudiness affects rain, etc), the current weather pattern, and the player's biome e.g. swamp, beach, etc. Now I "just" have to tie visuals and sounds to the variables so stuff actually happens...
I'm having a headache balancing the combat using flat defense so I'm gonna use percentual armor, in this pic, Simon has 16 on Defense which means all the incoming damage will be reduced by 16% this will ease my burden a bit.
!Have a nice day everybody¡
SO glad they patched outer worlds for switch! I can finally play it! Weird that other peeps are still having issues. I know it was really chugging on my lite when it first came out.

Forum statistics

Threads
105,555
Messages
1,014,623
Members
137,231
Latest member
anjing_gila
Top