Problem with scaling the surfaces.

Chris G.

Member
Hi there, I'm a beginner and I come with a problem that I'm struggling with for a while. I searched on the internet but I have no luck so, my game is low resolution (640x360) and I use surface_resize to upscaled two times for a good look, I also use a vibrant light system with shaders that I found the problem is that I draw the application surface In the draw event for lights to work and have the vibrant effect and the scaling Is way bigger than the view :
unknown.png

But for fixing this I divided the scale two times and it seems to work but now Is another problem, because I scaled down the size of the application surface In the draw event the image Is now 640x360 and everything looks very low res when I move or rotate something:
88802907a93c26c686f071dea202a1e4.png

I think this happens because I increased the scale two times on the application surface, and redrawing the application surface in the draw event it's displaying the surface bigger than the view that I have, and if I downscale it's back to the original resolution.
My question is why this happens? I want the surface to stay on the same scale as the view while still being high res maybe I don't understand how surfaces work and someone can help me? Here is the code:

GML:
var _u_pos = u_pos;
var _u_zz = u_zz;
var _cameraX = cameraX;
var _cameraY = cameraY;

if !surface_exists(shad_surf) {
    shad_surf = surface_create(cam_w,cam_h);   
}   

matrix_set(matrix_world,matrix_build(-cameraX,-cameraY,0,0,0,0,1,1,1));
surface_set_target(shad_surf);
draw_clear_alpha(c_black,0);
draw_surface_ext(application_surface,cameraX,cameraY,1/2,1/2,0,c_white,0.2);
with(p_lights) {
    gpu_set_blendmode_ext_sepalpha(bm_inv_dest_alpha,bm_one,bm_zero,bm_zero);
    shader_set(shd_light);
    shader_set_uniform_f(_u_pos,x,y);
    shader_set_uniform_f(_u_zz,size);
    draw_surface_ext(application_surface,_cameraX,_cameraY,1/2,1/2,0,color,1);
}
shader_reset();
surface_reset_target();
matrix_set(matrix_world,matrix_build(0,0,0,0,0,0,1,1,1));

gpu_set_blendmode_ext(bm_dest_alpha,bm_inv_dest_alpha);
draw_surface(shad_surf,cameraX,cameraY);

gpu_set_blendmode(bm_normal);
 

basementApe

Member
my game is low resolution (640x360) and I use surface_resize to upscaled two times for a good look
What is the good look you're trying to achieve? If you want everything to be drawn with a bilinear filter applied to it you can draw the application_surface to a separate surface and then resize that instead. As far as I know it's generally not a good idea to try and manipulate application_surface directly.
 

Chris G.

Member
What is the good look you're trying to achieve? If you want everything to be drawn with a bilinear filter applied to it you can draw the application_surface to a separate surface and then resize that instead. As far as I know it's generally not a good idea to try and manipulate application_surface directly.
I should've explained that part better sorry, I'm using PixelatedPope's method to scale my game and set the camera, with a "good look" I mean that I'm upscaling the application_surface so that when I rotate an object it will still be smooth and not distorted. Because of this if I draw the application_surface in the draw event as an effect for the lights it's much bigger than the view and I also can't downscale it to be In the view size cause it will not be high res anymore and pretty much the upscaled application_surface that I draw manually is covered by this that is low resolution. Here is the code for scaling If It helps.

GML:
application_surface_draw_enable(false);

//Aspect Ratio
aspect_ratio = display_get_width()/display_get_height();

view_height = 360;
view_width = round(view_height*aspect_ratio);

if view_width & 1 view_width++;
if view_height & 1 view_height++;

max_window_scale = min(floor(display_get_width()/view_width),floor(display_get_height()/view_height));
if view_height * max_window_scale == display_get_height()
    max_window_scale--;

window_scale = max_window_scale;

window_set_size(view_width*window_scale,view_height*window_scale);
alarm[0]=1;

surface_resize(application_surface,view_width*window_scale,view_height*window_scale);
display_set_gui_size(view_width,view_height);

//Shake Camera
shake_length = 0;
shake_magnitude = 0;
shake_remain = 0;
buff = 2;

//fullscreen
fullscreen = false;
 

basementApe

Member
Did you try to just draw application_surface at 3x resolution and all your sprites, tiles etc at 1x res?

Code:
draw_surface_ext(application_surface, 0, 0, 3, 3, 0, c_white, 1);
How do your rotated sprites look if you do that?

I'm doing the same thing here. One zombie is rotated and the other one isn't:

gms_rotate.png


They're both drawn at 1x scale with the application_surface drawn at 4x scale (my game resolution is 480x270 which I divide by display_get_width()/height() to scale it all to my display resolution):

GML:
draw_sprite_ext(spr_zombie_walk, frame, x, y, facing, 1, 60, c_white, 1);          // rotated 60 degrees

...

draw_surface_ext(application_surface, 0, 0, display_get_width() / 480, display_get_height() / 270, 0, c_white, 1);
What I'm trying to say is that all graphics rendered to application_surface get scaled up to match application_surface's scale *before* they're rendered to that surface. At least as far as I can tell. In other words, it isn't necessary to resize application_surface to get higher pixel fidelity and it's best to avoid it. If you really need super-high pixel fidelity (higher than your screen resolution) then it's probably better to draw to a custom surface and manipulate that instead.
 

Chris G.

Member
I tried and It's good to know but sadly I still have the same problems with the application surfaces drawn In the light surface and I don't why It's so big than the viewport, only those In the light surface render this big.
unknown.png

I tried to move the light code in the Draw GUI or to tweak it for a while but it's still the same.
 
Top