• Hey! Guest! The 39th GMC Jam will take place between November 26th, 12:00 UTC and November 30th, 12:00 UTC. Why not join in! Click here to find out more!

Shader resolution problems

Jam373

Member
I'm pretty new to shaders and have used a guide to create an entire-screen underwater wavey effect. Works perfectly both in windowed mode and 16:9 rooms in fullscreen (my monitor resolution is 16:9). But on rooms that are in 4:3, rather than give me my black bars on either side in fullscreen, the shader draws everything (except gui) starting in the top left corner, giving me a double size black bar on the right.

How do I fix this?

I'll post pics if the explanation doesn't help.
 

Jam373

Member
If you're drawing in the GUI event, you'll need to manually offset what you're drawing.
I think you misunderstand, the gui is the only part that works (because it's a gui and isn't effected by the shader) everything else is offset to the left corner. I think I'm asking how to make my shader draw to the centre of the screen rather than starting at the leftmost side of my monitor.
 

sp202

Member
I think you misunderstand, the gui is the only part that works (because it's a gui and isn't effected by the shader) everything else is offset to the left corner. I think I'm asking how to make my shader draw to the centre of the screen rather than starting at the leftmost side of my monitor.
I wasn't referring to the GUI itself but rather the Draw GUI event, unless you're drawing with the shader in the Post Draw event instead.
 

Jam373

Member
@sp202 Ah, well actually it was drawing in the Post Draw event. I just tried moving it to the Gui draw event and It actually fixed my issue! But it has given me a new issue.

I stole the shader from a yt video, that stole the shader from quake 1, so I really don't have technical knowledge of what the shader actually does. But the effect is to have the screen be all wavy like its underwater. When I draw the shader in the Gui event, fullscreening makes the effect more "dense".
So for example, rather than a full sine wave cycle being 10 in game pixels long, its 10 monitor/display pixels long. Does that make sense?

To reiterate, this means that before when drawing in Post Draw, no matter what the view port size, the effect appeared the same. Now in Gui, the effect is the same in relation to my monitor, but not the same in relation to my view port size. Essentially I want the effect to scale as the view port scales up to fullscreen.

@Fanatrick here is the code:

Code:
//Underwater Fragment Shader

varying vec2 v_vTexcoord;
varying vec4 v_vColour;

varying vec2 fragCoord;

uniform vec2  iResolution; // viewport resolution (in pixels)
uniform float iGlobalTime; // shader playback time (in seconds)

uniform sampler2D tex_wave;

// Jason Allen Doucette
// http://xona.com/jason/
//
// Quake-style Underwater Distortion
// May 15, 2016

// ---- SETTINGS ----------------------------------------------------------------

#define speed 3.0

// the amount of shearing (shifting of a single column or row)
// 1.0 = entire screen height offset (to both sides, meaning it's 2.0 in total)
#define xDistMag 0.00125
#define yDistMag 0.00125

// cycle multiplier for a given screen height
// 2*PI = you see a complete sine wave from top..bottom
#define xSineCycles 6.126
#define ySineCycles 6.126


// ---- CODE ----------------------------------------------------------------

void main()
{
  vec2 uv = vec2(fragCoord.x,fragCoord.y);

  uv = fragCoord.xy / iResolution.xy;

  
  // the value for the sine has 2 inputs:
  // 1. the time, so that it animates.
  // 2. the y-row, so that ALL scanlines do not distort equally.
  float time = iGlobalTime*speed;
  float xAngle = time + fragCoord.y * ySineCycles;
  float yAngle = time + fragCoord.x * xSineCycles;
  
  
  vec2 distortOffset =
  vec2(sin(xAngle), sin(yAngle)) * // amount of shearing
  vec2(xDistMag,yDistMag); // magnitude adjustment

  // shear the coordinates
  uv += distortOffset; 
  


  gl_FragColor = texture2D(tex_wave, uv);

}


Draw event (now Gui, used to be Post Draw):

GML:
shader_set(sh_underwater);

full_width = view_wport * (display_get_height()/view_hport);
//if (window_get_fullscreen()) shader_set_uniform_f(u_resolution,full_width,display_get_height()); //This was code used in Post Draw, now redundant in Gui Draw
//else
shader_set_uniform_f(u_resolution,view_wport,view_hport);
shader_set_uniform_f(u_seconds,sec);

texture_set_stage(u_texture_wave,surface_get_texture(application_surface));

//if (window_get_fullscreen()) draw_rectangle(0,0,full_width,display_get_height(),false); //This was code used in Post Draw, now redundant in Gui Draw
//else
draw_rectangle(0,0,view_wport,view_hport,false);

shader_reset();
 
Last edited:

Yal

šŸ§ *penguin noises*
GMC Elder
To reiterate, this means that before when drawing in Post Draw, no matter what the view port size, the effect appeared the same. Now in Gui, the effect is the same in relation to my monitor, but not the same in relation to my view port size. Essentially I want the effect to scale as the view port scales up to fullscreen.
display_set_gui_size makes the GUI layer have a set size rather than resize to fit your window size. I strongly recommend always using it so you don't need to keep track of resizing GUI elements all the time.

If you still have letterboxing (black bars) issues, there's a function to get the coordinates the application surface (main game drawing) is drawn at... I don't remember the name of it, but that's what you want here. (Instead of applying the shader to the entire window as you do now, draw the rectangle over the region the app surface would normally be drawn to)
 

Jam373

Member
@Yal I did what you said, though maybe I misunderstood what you meant exactly. In the gui draw event for the shader I did:

full_width = view_wport * (display_get_height() / view_hport);
if (fullscreen) display_set_gui_size(full_width,display_get_height());
else display_set_gui_size(view_wport, view_hport);

This seemingly fixed my effect scaling problem, but has broken my actual UI. My actual gui/ui that has it's own object that draws in a gui draw event, is now tiny when fullscreen. I tried applying the same code to that gui but it doesn't change anything.
 

Yal

šŸ§ *penguin noises*
GMC Elder
@Yal I did what you said, though maybe I misunderstood what you meant exactly. In the gui draw event for the shader I did:

full_width = view_wport * (display_get_height() / view_hport);
if (fullscreen) display_set_gui_size(full_width,display_get_height());
else display_set_gui_size(view_wport, view_hport);

This seemingly fixed my effect scaling problem, but has broken my actual UI. My actual gui/ui that has it's own object that draws in a gui draw event, is now tiny when fullscreen. I tried applying the same code to that gui but it doesn't change anything.
GG, you just managed to manually perform the default behavior I was trying to save you from :p Set the GUI size to the size you want it to have normally (e.g. view_wport, view_hport, or something like 640 x 360 if you're on GMS2 and it's a bit more messy to get viewport sizes) once (in e.g. the create event of the title screen object or something), and then never change it. The GUI layer will be that size from now on, but stretched to fit the window application surface area. So basically its scaling will now match the rest of the game's instead of being independent of it in confusing ways.
 

Jam373

Member
GG, you just managed to manually perform the default behavior I was trying to save you from :p
haha thought u were gunna say that. Though my results don't exactly match up with what you suggested. Setting gui size once is giving me the scaling issue when fullscreening ( I think? It's hard to see the effect when in 480x270 windowed). Whereas what I did before that you say is a default behaviour actually fixed that issue. So I'm kinda confused tbh.
 
Top