• 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!

Fog 2D animated

skofrant

Member
Hi All:)

How to get the exact effect of animated 2D fog in a game maker studio 1.4??
Something similar to this video




Could anyone help me to rewrite my code so that I could get a similar effect to the film?

Thanks:)

I tried to use shaders. But that's not the effect here on this video. My code looks like this:


SHADER

shrFOG

HTML:
//
// Simple passthrough 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;

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;
}

objFog

CREATE

HTML:
u_color = shader_get_uniform(shrFog, "color");
u_octaves = shader_get_uniform(shrFog, "OCTAVES");
u_time = shader_get_uniform(shrFog, "TIME");

DRAW GUI BEGIN

HTML:
shader_set(shrFog);
shader_set_uniform_f(u_color, 0.35, 0.48, 0.95);
shader_set_uniform_i(u_octaves, 4);
shader_set_uniform_f(u_time, current_time * 0.001);
// shader uzywa UV, mozesz tez stworzyc mesha dla post processow
draw_background(bgJazzJackrabbit, 0, 0);
shader_reset();
 

Bart

WiseBart
This effect is created in the fragment shader, so you'll need to show that instead of the vertex shader.
That one is fine as it is, since the vertex and uv coordinates don't need to be changed in any way.

It seems like the shader in the video is quite straightforward to port to GameMaker.
Everything in the 'void fragment() {}' goes into the fragment shader's 'void main () {}', the function definitions (rand, noise, fbm) you define above that. 'COLOR' becomes gl_FragColor, 'UV' becomes 'v_vTexcoord' when using the built-in vertex format and passthrough shader. The 'TIME' uniform you have to define yourself, though.

You don't need a noise texture, a simple sprite (enable 'Separate texture page') or draw_rectangle should work as long as the uv coordinates range from [0, 0] tot [1, 1].

Depending on how you want it to work, you'll want to use one of the following:
  • Set the shader and draw something with a rectangular shape in an object's Post Draw event (instead of Draw GUI, for more info, see the manual on draw events)
  • Add a new asset layer on top of the others, drag a sprite onto it and set the shader to be used using layer_shader
The latter option is probably the cleanest way to do it.
 
R

Rukiri

Guest
I've never written any shader for any engine but based on the data types it almost seems you can point blank just copy/paste it into GMS2 as I didn't see anything that wasn't used.
 
J

Janey_Springs

Guest
This effect is created in the fragment shader, so you'll need to show that instead of the vertex shader.
That one is fine as it is, since the vertex and uv coordinates don't need to be changed in any way.

It seems like the shader in the video is quite straightforward to port to GameMaker.
Everything in the 'void fragment() {}' goes into the fragment shader's 'void main () {}', the function definitions (rand, noise, fbm) you define above that. 'COLOR' becomes gl_FragColor, 'UV' becomes 'v_vTexcoord' when using the built-in vertex format and passthrough shader. The 'TIME' uniform you have to define yourself, though.

You don't need a noise texture, a simple sprite (enable 'Separate texture page') or draw_rectangle should work as long as the uv coordinates range from [0, 0] tot [1, 1].

Depending on how you want it to work, you'll want to use one of the following:
  • Set the shader and draw something with a rectangular shape in an object's Post Draw event (instead of Draw GUI, for more info, see the manual on draw events)
  • Add a new asset layer on top of the others, drag a sprite onto it and set the shader to be used using layer_shader
The latter option is probably the cleanest way to do it.
I rewrote the Shader, looks good, but if you use draw_sprite_tiled, the gaps between the squares are visible. How to fix it? I can't draw fog using (0, 0, room_width, room_height) since my room is too big and the fog becomes invisible
 

Attachments

NightFrost

Member
If you're using sprites instead of a noise shader, then you have to make sure your fog sprite is tileable, and that's something you need to resolve in a graphics editor (GIMP, Photoshop, whatever you use).

(A noise shader is fast so there's really no need to use sprite, unless you're going for a custom fog appearance.)
 
J

Janey_Springs

Guest
If you're using sprites instead of a noise shader, then you have to make sure your fog sprite is tileable, and that's something you need to resolve in a graphics editor (GIMP, Photoshop, whatever you use).

(A noise shader is fast so there's really no need to use sprite, unless you're going for a custom fog appearance.)
It is a shader
Code:
//Fragment
varying vec2 v_vTexcoord;
varying vec4 v_vColour;


uniform vec3 color;
uniform int OCTAVES;
uniform float TIME;

float rand(vec2 coord) {
    return fract(sin(dot(coord, vec2(56, 78)) * 1000.0) * 1000.0);
}

float noise(vec2 coord) {
    vec2 i = floor(coord);
    vec2 f = fract(coord);

    // 4 corners of a rectangle surrounding our point
    float a = rand(i);
    float b = rand(i + vec2(1.0, 0.0));
    float c = rand(i + vec2(0.0, 1.0));
    float d = rand(i + vec2(1.0, 1.0));

    vec2 cubic = f * f * (3.0 - 2.0 * f);

    return mix(a, b, cubic.x) + (c - a) * cubic.y * (1.0 - cubic.x) + (d - b) * cubic.x * cubic.y;
}


float fbm(vec2 coord) {
    float value = 0.0;
    float scale = 0.5;

    for(int i = 0; i < OCTAVES; i++){
        value += noise(coord) * scale;
        coord *= 2.0;
        scale *= 0.5;
    }
    
    return value;
}

void main()
{
    vec2 coord = v_vTexcoord * 20.0;

    vec2 motion = vec2( fbm(coord + vec2(TIME * -0.5, TIME * 0.5)) );

    float final = fbm(coord + motion);

    gl_FragColor = vec4(color, final * 0.14);
}
Code:
//draw
shader_set(glsl_2dfog);
shader_set_uniform_f(u_color, 0.3, 0.3, 0.45);
shader_set_uniform_i(u_octaves, 4);
shader_set_uniform_f(u_time, current_time * 0.002);

draw_sprite_tiled(fxNoice,0,oCamera.x,oCamera.y);
shader_reset();
 

Attachments

Top