• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

Shaders Having trouble applying Vignette shader and distortion on screen

S

Sidartha

Guest
Sorry folks, I`m still a rookie on Game Maker and despite of watching some tutorials I couldn`t apply a distortion shader with a vignette shader on the whole game screen.


I`ve created two shaders: One named "sh_underwater" and the other named "shd_vignette_noise":

SHD_VIGNETTE_NOISE---------------------------------------------------------------------------------------------

VERTEX SHADER

attribute vec3 in_Position;
attribute vec4 in_Colour;
attribute vec2 in_TextureCoord;

varying vec2 var_texcoord;
varying vec4 v_vColour;

void main()
{
gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * vec4(in_Position, 1.0);

v_vColour = in_Colour;
var_texcoord = in_TextureCoord;
}



FRAGMENT SHADER

varying vec2 var_texcoord;
varying vec4 v_vColour;

uniform vec4 u_settings; //vignette inner circle size, vignette outter circle size, noise strength
uniform vec3 u_vignette_colour; //R,G,B

float random(vec3 _scale, float _seed)
{
return fract(sin(dot(vec3(var_texcoord, 1.0)+_seed, _scale))*43758.5453+_seed);
}

void main()
{
vec4 base = texture2D( gm_BaseTexture, var_texcoord );

float vignette = distance( vec2(0.5, 0.5), var_texcoord );
vignette = u_settings.x - vignette * u_settings.y;
vec3 vignette_colour = (u_vignette_colour/255.0) * vignette;

float noise_strength = u_settings.z;
float noise = noise_strength * ( 0.5 - random( vec3( 1.0 ), length( vec2(var_texcoord.x/var_texcoord.y, var_texcoord.y)) ) );
if (u_settings.w == 1.0) {vignette_colour += noise;}

gl_FragColor = v_vColour * vec4(base.rgb * vignette_colour, base.a);
}

SH_UNDERWATER-------------------------------------------------------------------------------------------------

VERTEX SHADER

attribute vec3 in_Position; // (x,y,z)
//attribute vec3 in_Normal; // (x,y,z) unused in this shader.
attribute vec4 in_Colour; // (r,g,b,a)
attribute vec2 in_TextureCoord; // (u,v)

varying vec2 v_vTexcoord;
varying vec4 v_vColour;

varying vec2 fragCoord;

void main()
{
vec4 object_space_pos = vec4( in_Position.x, in_Position.y, in_Position.z, 1.0);
gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * object_space_pos;

v_vColour = in_Colour;
v_vTexcoord = in_TextureCoord;

fragCoord = in_Position.xy;
}


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 float modificaOndaX;
uniform float modificaOndaY;

uniform sampler2D tex_water;



// ---- 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.01500 // 0.00125
#define yDistMag 0.00500 // 0.00125

// cycle multiplier for a given screen height
// 2*PI = you see a complete sine wave from top..bottom
#define xSineCycles 6.126 // 6.126
#define ySineCycles 6.126 // 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 * modificaOndaX,yDistMag * modificaOndaY); // magnitude adjustment

// shear the coordinates
uv += distortOffset;



gl_FragColor = texture2D(tex_water, uv);

}



And I`ve created an object "obj_control" to apply the effect:


CREATE

//distortion effect shader
u_resolution_water = shader_get_uniform(sh_underwater, "iResolution");
u_seconds_water = shader_get_uniform(sh_underwater, "iGlobalTime");
u_modifica_ondaX = shader_get_uniform(sh_underwater, "modificaOndaX");
u_modifica_ondaY = shader_get_uniform(sh_underwater, "modificaOndaY");
u_texture_water = shader_get_sampler_index(sh_underwater, "tex_water");

sec = 0;
//Vignette effect shader
uni_settings = shader_get_uniform(shd_vignette_noise, "u_settings");
uni_vignette_colour = shader_get_uniform(shd_vignette_noise, "u_vignette_colour");



//Stopping the automated draw at application surface on postdraw event
application_surface_draw_enable(false);


STEP

sec += 1/room_speed;


POST-DRAW

shader_set(sh_underwater);

shader_set_uniform_f(u_resolution_water,1080.0,810.0);

shader_set_uniform_f(u_seconds_water,sec);

shader_set_uniform_f(u_modifica_ondaX, /*irandom_range(5, 15)*0.1 */ .250);
shader_set_uniform_f(u_modifica_ondaY, /*irandom_range(5, 15)*0.1 */ .750);

texture_set_stage(u_texture_water, surface_get_texture(application_surface)); //feed application surface into shader

draw_rectangle(0,0,1080,810,false);

shader_reset();

shader_set(shd_vignette_noise);
shader_set_uniform_f(uni_settings, 1.2, 1.9, 0.06, 1); //vignette inner circle size, vignette outter circle size, noise strength, noise enable (1 or 0 only).
shader_set_uniform_f(uni_vignette_colour, 245, 223, 201); //R,G,B - 0 to 255
draw_surface(application_surface,0,0);
shader_reset();



Thanks for your patience, guys!
 
Last edited by a moderator:
Have you disabled automatic drawing of the application surface?

application_surface_draw_enable(false);

If you don't do that, just after you draw to the post draw event, the application surface will be redrawn over everything you just tried to draw in that event.

Also, and I don't know if this is what you're going for exactly, but if you want your noise function to change over time, you'll need to add a time uniform variable to your shader.
 
S

Sidartha

Guest
Issue.jpg Hi flyingsaucerinvasion,
Thanks a lot for the help, but actually I did.
I was having trouble updating the actual complete issue, so I have just done it now.
For instance, the result was this:
 
Last edited by a moderator:
S

Sidartha

Guest
What is the size of your application surface vs. the size of your window?
I`m a noob :/
But I think the size of my window is 1080 x 810 and the size of my application surface I haven`t configure.
As a matter of fact I tried to merge two different programs in one (my own crazy way).
Ps.: Did you saw that I updated the Original Post with the complete code this time, right? :)
 
S

Sidartha

Guest
What about the size of your view ports?

Are you having problems with the shaders or just where they are being drawn on your game window?
I just have 1 viewport: CAMERA W: 480 H: 360 ---- ViewPort Properties: W: 640 H: 480 --> Following my obj_camera

I think the shaders are good. I`m having the problem of the screen with the vignette_noise being draw smaller and over the mainscreen (as in my first response, that I`ve printed) that has the distortion applyed.
 
You have a size mismatch between your window and view port, and thus between your window and application surface. You should be able to fix this problem by drawing your application surface scaled during the post draw event. Actually, it'd be easier to just use draw_surface_stretched()
 
L

Lonewolff

Guest
As @flyingsaucerinvasion said. Looks like a view port thing. (Funny that the smaller section of the image is exactly 640 pixels wide).

Either that or it is the dimensions you are feeding to the shader. The shader probably thinks it is working with a 2048 x 1024 texture, given your window dimensions. So you may have to calculate the actual area that is in use (eg, 1080 width will be from 0 to 0.52734375 on the surfaces texture page and 810 will likely be 0 to 0.791015625 on the TP - assuming it is working with 2048 x 1024 area)
 
S

Sidartha

Guest
Not sure what tutorial you watched, but I can recommend the shader tutorials by The Reverend.

He covers vignettes in a couple of his tutorials:
https://forum.yoyogames.com/index.p...programmers-newest-video-gradient-maps.35832/
Yes! I`ve watched precisely a tutorial from the Reverend before, to understand vignette, but even being a tutorial for begginers, I think I need a little bit of leveling up to become one XD
He applyed vignette to an image. I need to apply vignette to the whole screeen and over my other effect (water distortion), but failing so far as you can see in the image I uploaded.
So I`ve found a simple Vignette for free in the market place (the only one). My problem is the drawing part (I think), because somehow the logic to draw them both together is flawed.
 
S

Sidartha

Guest
You have a size mismatch between your window and view port, and thus between your window and application surface. You should be able to fix this problem by drawing your application surface scaled during the post draw event. Actually, it'd be easier to just use draw_surface_stretched()
Thanks again, bud!
But now I`ve got the following problem: I`ve draw the screen with the vignette over the scren with the distortion:


shader_set(sh_underwater);

shader_set_uniform_f(u_resolution_water,1080.0,810.0);

shader_set_uniform_f(u_seconds_water,sec);

shader_set_uniform_f(u_modifica_ondaX, /*irandom_range(5, 15)*0.1 */ .250);
shader_set_uniform_f(u_modifica_ondaY, /*irandom_range(5, 15)*0.1 */ .750);

texture_set_stage(u_texture_water, surface_get_texture(application_surface)); //feed application surface into shader

draw_rectangle(0,0,1080,810,false);

shader_reset();

shader_set(shd_vignette_noise);
shader_set_uniform_f(uni_settings, 1.2, 1.9, 0.06, 1); //vignette inner circle size, vignette outter circle size, noise strength, noise enable (1 or 0 only).
shader_set_uniform_f(uni_vignette_colour, 245, 223, 201); //R,G,B - 0 to 255
draw_surface_stretched(application_surface,0,0,1080.0,810.0);
shader_reset();
issue2.JPG
 
Last edited by a moderator:
S

Sidartha

Guest
As @flyingsaucerinvasion said. Looks like a view port thing. (Funny that the smaller section of the image is exactly 640 pixels wide).

Either that or it is the dimensions you are feeding to the shader. The shader probably thinks it is working with a 2048 x 1024 texture, given your window dimensions. So you may have to calculate the actual area that is in use (eg, 1080 width will be from 0 to 0.52734375 on the surfaces texture page and 810 will likely be 0 to 0.791015625 on the TP - assuming it is working with 2048 x 1024 area)
Thanks Mr Sorcerer, but your spellnation is to sofisticated to me... o_O I`m trying my best to figure out what to do right now, nevertheless! >:|
 
@Sidartha please describe your problem as fully as you can before you post the code.

I am assuming your current problem is that the wave distortion is not visible because the vignette is being drawn over it. Is this correct?
 
S

Sidartha

Guest
@Sidartha please describe your problem as fully as you can before you post the code.

I am assuming your current problem is that the wave distortion is not visible because the vignette is being drawn over it. Is this correct?
Yes, man, you are correct. The wave distortion is not visible because the vignette is being drawn over it.
I`ve posted the whole code on the Original Post.
 
L

Lonewolff

Guest
You should be able to combine the two shaders in to the one. Just use the gl_FragColor of the first part as the input to the second part.
 
S

Sidartha

Guest
@Sidartha please describe your problem as fully as you can before you post the code.

I am assuming your current problem is that the wave distortion is not visible because the vignette is being drawn over it. Is this correct?
You should be able to combine the two shaders in to the one. Just use the gl_FragColor of the first part as the input to the second part.
Thanks, man, but could you, please, give an exemple? :)
I`ve no Idea how to do that, since there are variables with the same name in both Shaders.
 
L

Lonewolff

Guest
Something like this (completely untested and you'll need to fix up some things)

Code:
void main()
{
    // Shader 1

    vec4 base = texture2D( gm_BaseTexture, var_texcoord );

    float vignette = distance( vec2(0.5, 0.5), var_texcoord );
    vignette = u_settings.x - vignette * u_settings.y;
    vec3 vignette_colour = (u_vignette_colour/255.0) * vignette;

    float noise_strength = u_settings.z;
    float noise = noise_strength * ( 0.5 - random( vec3( 1.0 ), length( vec2(var_texcoord.x/var_texcoord.y, var_texcoord.y)) ) );
    if (u_settings.w == 1.0) {vignette_colour += noise;}

    // gl_FragColor = v_vColour * vec4(base.rgb * vignette_colour, base.a);
    // ^^ Old return fragment
  
    vec4 frag_input = v_vColour * vec4(base.rgb * vignette_colour, base.a);


    // Shader 2
  
    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 * modificaOndaX,yDistMag * modificaOndaY); // magnitude adjustment

    // shear the coordinates
    uv += distortOffset;

  
    // gl_FragColor = texture2D(tex_water, uv);
    // ^^ use the fragment from the original shader pass instead (see below)
  
    gl_FragColor = texture2D(frag_input, uv);
}
Actually you'll probably want to swap the passes around so the vignette gets applied last, but hopefully you get the gist of what I mean here.
 
There's a problem you might encounter if you have your game's graphic settings set to "keep aspect ratio". If that is the case, and your window and application_surface have different aspect ratios, you might find it difficult to draw your application surface in the correct location.

If you have that problem, I suggest turning off "keep aspect ratio", switching to "Full Scale" instead, and if you want to keep the appearance of "keep aspect ratio", use the following code to draw your application surface:
Code:
var _app_surf_w = surface_get_width(application_surface);
var _app_surf_h = surface_get_height(application_surface);
var _window_w = window_get_width();
var _window_h = window_get_height();
if (_app_surf_w/_window_w) < (_app_surf_h/_window_h) {
    var _h = _window_h;
    var _w = _h * _app_surf_w/_app_surf_h;
    var _x = (_window_w-_w)/2;
    var _y = 0;
} else {
    var _w = _window_w;
    var _h = _w * _app_surf_h/_app_surf_w;
    var _x = 0;
    var _y = (_window_h-_h)/2;
}
draw_surface_stretched(application_surface,_x,_y,_w,_h);
 
S

Sidartha

Guest
Thanks, guys!
I`ll try harder tomorrow and, with all your help, I`ll be in touch to keep you informed of the progress.
If I succeed or not, I`ll post the results.
Thanks again!
 
Top