GML Applying shader before game scales

Wayfarer

Member
I've made a shader for rendering slopes so I can use the same 16x16 wall tiles on slopes (without having to make individual slope sprites at various sizes). The game then adds grass to the top of slopes.

The first room is set to 1920x1080 and the game size itself is 480x270, so the game scales up 4x while retaining all the subpixels (as the port is 1920x1080).

I'm just wondering, is it possible to apply the shader before the game scales so the shader uses less pixels?
 

Simon Gust

Member
You could scale the application surface by doing surface_resize(application_surface, 480, 270). But it will get rid of the subpixels.
 

Neptune

Member
Here is what I do:
[POST DRAW EVENT]
Code:
    if !surface_exists(scale_surf)
    {
        scale_surf = surface_create(480,270);
    }
    surface_set_target(scale_surf);
        shader_set(shader_cycle);
            shader_set_uniform_f(o_weather.shader_b_out, o_weather.b_add);
            shader_set_uniform_f(o_weather.shader_r_out, o_weather.r_add);
            shader_set_uniform_f(o_weather.shader_g_out, o_weather.g_add);
            shader_set_uniform_f(o_weather.shader_darkness, o_weather.night_alpha);
            texture_counter = surface_get_texture(o_weather.light_surface);
            sampler_counter = shader_get_sampler_index(shader_cycle,"lightSurface");
            texture_set_stage(sampler_counter,texture_counter);
            draw_surface(application_surface,0,0);
        shader_reset();
    surface_reset_target();

    draw_surface_ext(scale_surf,global.offset_x,global.offset_y,global.pixel_scale,global.pixel_scale,0,c_white,1);
It draws the application surface to an alternate surface with the shader applied, and then it draws that surface scaled -- honestly, I hate it. It seems wildly inefficient to be drawing twice every step, but I guess it is better than shading a 1920x1080...
 

Wayfarer

Member
Thanks for the replies :)

@Simon Gust: Yeah, I thought that'd be the case!

@Vether: Wouldn't that get rid of the subpixels also? If a pixel is overlapping another, say by 70%, how would the shader even see the overlapped pixel at the unscaled size? I'm still learning how shaders work, so maybe I'm missing the point :D

Even still, I think I've figured a way to do it (for individual sprites at least):
1. Set the shader.
2. Draw the sprite at 25% of its size (because the game is scaled 4x)
3. Have the shader divide the texture coordinates by 4, so the sprite is 4x bigger (and therefore normal size for the game).

Would this work? I'm going to try it out, but if anyone has any advice I'm happy to hear it!
 

Neptune

Member
I'm not sure what you mean by overlapped pixels.
In my case, the base resolution is 480x270 -- I draw the application surface to another surface (of the exact same size, 480x270) with the shader applied -- so the shader is working on 130,000 pixels.
Then I draw the new surface scaled by a power of 2 (which fits nicely into 1920x1080).

There may be other methods, but this one works well for my shader because its applied to all sprites (its a day night cycle).
 

Wayfarer

Member
@Vether:
Even though my game is using pixel art the pixels can overlap.

The first room is 1920x1080, and I believe that sets the application_surface to that size automatically. So when the game is scaled up to fit 1920x1080 the pixels won't snap to 480x270. For example, if the player was at position "x = 260.50" you'd actually see them half overlapping pixels (and this is intentional). Hopefully that makes sense?
 
Top