Why am I getting pixel distortion when I resize the window?

Olivebates

Member
I have a piece of code, that should automatically scale the view to whatever size the window is, so no pixel distortion would happen, but for some reason, I am still experiencing pixel distortion? I shouldn't be dealing with any half-pixels as far as I can tell, so what is happening?



GML:
// Create event
windowWidth = window_get_width();
windowHeight = window_get_height();
view_enabled = true;
view_visible[0] = true;
view_wport[0] = windowWidth;
view_hport[0] = windowHeight;
view_camera[0] = camera_create_view(0, 0, windowWidth, windowHeight, 0, -1, -1, -1, 0, 0);
camera_set_view_size(view_camera[0], windowWidth, windowHeight);
display_set_gui_size(windowWidth, windowHeight);

// Step event
if (windowWidth != window_get_width() or windowHeight != window_get_height())
{
    window_set_size(floor(window_get_width()), floor(window_get_height()));
    windowWidth = window_get_width();
    windowHeight = window_get_height();
    view_wport[0] = windowWidth;
    view_hport[0] = windowHeight;
    camera_set_view_size(view_camera[0], windowWidth, windowHeight);
    display_set_gui_size(windowWidth, windowHeight);
}


How it should look:


How it's looking after I resize the window:

 
Last edited:

Micah_DS

Member
EDIT: TL;DR:
I may have been too quick on giving my code alternative. Your code should be fine, it just needs a frame to update after the floored window size.

- original message -
Unless I'm misunderstanding your code, you are trying to update the resolution of everything, not just the GUI, right?

If this is the case, instead of using display_set_gui_size, it should work just fine to resize the application surface using surface_resize. I recently did this in a project and it properly updates text drawn in the GUI event, maintaining size and form without any distortions. Here is my code from said project:
GML:
// Step event
var win_width, win_height;
win_width  = window_get_width();
win_height = window_get_height();

if window_width != win_width || window_height != win_height{
    surface_resize(application_surface, win_width, win_height);
    window_width  = win_width;
    window_height = win_height;
    camera_update(); // to avoid confusion, this is equivalent to your view port and camera updates, but it's 3D
}

// Script
function camera_update(){

    var vx, vy, vz;
    vx = cos(pan) * cos(tilt);
    vy = sin(pan) * cos(tilt);
    vz = sin(tilt);

    var matrix_look = matrix_build_lookat(vx * zoom, vy * zoom, -MODEL_MID + vz * zoom, 0, 0, -MODEL_MID, 0, 0, 1);
    var proj_matrix = matrix_build_projection_perspective_fov(53, window_width/window_height, 1, 16000)
    camera_set_proj_mat(global.camera, proj_matrix);
    camera_set_view_mat(global.camera, matrix_look);
}
-
EDIT (because I should probably try to answer your question and not just give a possible solution.. sorry):

To answer your question, I expect it's slightly distorted because you're flooring the window size, then directly afterward you get the window size.
You probably need to wait a frame to actually get the new floored window size. Getting window size directly after setting it likely won't get the new size but the old one. IIRC, this is a problem I had before and it was resolved by waiting a frame to get the new window size.

-

EDIT 2:

Hopefully you figured it out by now, but if not, I wanted to say that I realize now by how you worded your post that you probably only tried to floor the window size because you were ALREADY having distortion issues BEFORE attempting to set a new window size on the same frame as getting the window size, right?

If that's the case, I'm not sure what the problem could be. I don't think I've ever used the display_set_gui_size function myself.
What I do know is that the code I put in my spoiler works, and it uses surface_resize on the application surface, so perhaps my code could actually help, assuming you haven't already resolved the issue.


TIP: If none of this helps you, take this as a chance to develop your problem solving skills. Break the issue down to a test using only what is needed, use debugging to monitor values to make sure code is doing what you think it is, try removing or changing something to get an expected new result, and if it does, the problem isn't there, but if the result is wrong, you've narrowed down the issue - try stuff like this. You will find the problem if you go through things thoughtfully and systematically.
 
Last edited:

Olivebates

Member
EDIT: TL;DR:
I may have been too quick on giving my code alternative. Your code should be fine, it just needs a frame to update after the floored window size.

- original message -
Unless I'm misunderstanding your code, you are trying to update the resolution of everything, not just the GUI, right?

If this is the case, instead of using display_set_gui_size, it should work just fine to resize the application surface using surface_resize. I recently did this in a project and it properly updates text drawn in the GUI event, maintaining size and form without any distortions. Here is my code from said project:
GML:
// Step event
var win_width, win_height;
win_width  = window_get_width();
win_height = window_get_height();

if window_width != win_width || window_height != win_height{
    surface_resize(application_surface, win_width, win_height);
    window_width  = win_width;
    window_height = win_height;
    camera_update(); // to avoid confusion, this is equivalent to your view port and camera updates, but it's 3D
}

// Script
function camera_update(){

    var vx, vy, vz;
    vx = cos(pan) * cos(tilt);
    vy = sin(pan) * cos(tilt);
    vz = sin(tilt);

    var matrix_look = matrix_build_lookat(vx * zoom, vy * zoom, -MODEL_MID + vz * zoom, 0, 0, -MODEL_MID, 0, 0, 1);
    var proj_matrix = matrix_build_projection_perspective_fov(53, window_width/window_height, 1, 16000)
    camera_set_proj_mat(global.camera, proj_matrix);
    camera_set_view_mat(global.camera, matrix_look);
}
-
EDIT (because I should probably try to answer your question and not just give a possible solution.. sorry):

To answer your question, I expect it's slightly distorted because you're flooring the window size, then directly afterward you get the window size.
You probably need to wait a frame to actually get the new floored window size. Getting window size directly after setting it likely won't get the new size but the old one. IIRC, this is a problem I had before and it was resolved by waiting a frame to get the new window size.

-

EDIT 2:

Hopefully you figured it out by now, but if not, I wanted to say that I realize now by how you worded your post that you probably only tried to floor the window size because you were ALREADY having distortion issues BEFORE attempting to set a new window size on the same frame as getting the window size, right?

If that's the case, I'm not sure what the problem could be. I don't think I've ever used the display_set_gui_size function myself.
What I do know is that the code I put in my spoiler works, and it uses surface_resize on the application surface, so perhaps my code could actually help, assuming you haven't already resolved the issue.


TIP: If none of this helps you, take this as a chance to develop your problem solving skills. Break the issue down to a test using only what is needed, use debugging to monitor values to make sure code is doing what you think it is, try removing or changing something to get an expected new result, and if it does, the problem isn't there, but if the result is wrong, you've narrowed down the issue - try stuff like this. You will find the problem if you go through things thoughtfully and systematically.
Yes, you are correct that I set the window size to floor, because I was getting pixel distortion before attempting to set the window size.
All I am trying to do is resize the view to fit the window size :)

I tried flooring the windowWidth and windowHeight variables like you said, as well as every x/y position of every object in the room, but it doesn't change anything.

In your code, what do I set the variables "pan, tilt, zoom and MODEL_MID" to?
 

Micah_DS

Member
Sorry, I should have worded things differently, but the good news is that I made a test project to try your original code, because it seemed like it should work, and it did!

For the test, I used your exact creation code and then this for step and draw events:
GML:
// Step event
if (windowWidth != window_get_width() or windowHeight != window_get_height())
{
    windowWidth = window_get_width();
    windowHeight = window_get_height();
    view_wport[0] = windowWidth;
    view_hport[0] = windowHeight;
    camera_set_view_size(view_camera[0], windowWidth, windowHeight);
    display_set_gui_size(windowWidth, windowHeight);
}

// Draw event
draw_text(16, 16, "Pick your destination");
So it seems the issue is elsewhere. Maybe these questions can narrow down the problem:
  • Are you on the latest IDE and Runtime?

    My test was run with everything up to date (I think):
    1635332700913.png

  • Is your font being drawn on a sub-pixel position?

    Depending on how you are placing your text, it could be drawing 'between' pixels, which will create distortions similar to what you show in your OP.
    If your text moves into position or in some way that it ends up a non-integer value, it may be necessary to floor the x y position of the drawn text.

  • Are you using a font resource or just the default?

    I used the default in my test.
    If you used a font resource, it's possible a certain font or setting within the font resource is giving problems for some reason.

  • Have you tried clearing the cache?

    If you don't know how to do this, just click this:
    1635332181183.png

    Running the game after cleaning the cache will cause the project to rebuild some (all?) things from scratch (this may or may not be a good description of what occurs).
    The result should be that it builds an error-free cache the next time you run the project. This has resolved issues for me on many occasions.
    ( EDITED : worded things better)
 
Last edited:

Olivebates

Member
Yes, same IDE and Runtime.


I try rounding the x/y position of the text, but it still happens.


I created a new font resource and left it at the default values, but it still happens.


Clearing the cache didn't fix it.


I will also note that the pixel distortion only happens around every 10-30 times I resize the window to a random size. Eg it happened when the window size was (w 1815, h 877)
 
Last edited:

Micah_DS

Member
Hmm, alright, at this point, I'd say do a process of elimination by starting with the most basic text drawing, like the test I did, just using the default font, without aligning text or anything like that.
Then, try bringing back each part of the code one at a time, rerunning the program with each thing you add back until it distorts again, then you have found your culprit, hopefully.

You could also try regenerating the font texture (button on the lower-left in the font resource window).
I may be misremembering, but I thought I had a distortion error with a font resource before and it was fixed with that. Except in my case, I think the font was always messed up, not just after resizing the window, so it might not be the issue here. Still worth a try.
 

Micah_DS

Member
Ok, double posting just to be sure you see this. I ran my test project some more and I was able to get the text distorting consistently when double-clicking to maximize the window, though I'm not sure you'll have the same result, but yea, apparently there is a problem with even the basic resizing part.

But I haven't been able to get any distortions after replacing the display_set_gui line of code with this:
GML:
surface_resize(application_surface, windowWidth, windowHeight);
The window refresh behavior is different, and this will resize the application surface, of course, but hopefully that doesn't matter.

Anyway, it's pretty late where I'm at in the world and I must call it a day. Good luck.
 

Olivebates

Member
Ok, double posting just to be sure you see this. I ran my test project some more and I was able to get the text distorting consistently when double-clicking to maximize the window, though I'm not sure you'll have the same result, but yea, apparently there is a problem with even the basic resizing part.

But I haven't been able to get any distortions after replacing the display_set_gui line of code with this:
GML:
surface_resize(application_surface, windowWidth, windowHeight);
The window refresh behavior is different, and this will resize the application surface, of course, but hopefully that doesn't matter.

Anyway, it's pretty late where I'm at in the world and I must call it a day. Good luck.
Yes, replacing that line seems to have completely fixed it. Thank you so much šŸ¦Šā¤ā¤
 
Top