How to Distort the Screen in GameMaker

I know shaders can seem like a scary world for some however in just a few lines of code I want to give you an easy to implement and impressive shader that will be a great starting point for learning your first shader.

Today I will show you how to make a shader to warp your screen and add ripples and other distortions to your games.

Add Shockwaves To GameMaker Game

The concept is very simple, we are going to pass a Surface into the shader with all the information about where each pixel should actually draw to the screen. This works just like a lens.

Using Normal Maps in GameMaker to Warp The Screen

First we are going to make a new shader with Alt+A and you will notice it comes as two files, the Vertex Shader and the Fragment Shader. We will only be using the Fragment Shader which in GameMaker is the second tab along, this code runs on the graphics card for every pixel on the screen.

GameMaker Fragment Shader

This shader will look at the surface and for every pixel on the surface the colour will tell the shader where to offset when selecting what colour to draw.

GameMaker Screen Distortion Shader

Shader Code Fragment Shader:

varying vec2 v_vTexcoord;
varying vec4 v_vColour;

uniform sampler2D distortion_texture_page; // the name of the surface in the shader	

void main()
{
    // find the offset colour for this location (this is where the magic happens) 
    vec2 distort_amount = vec2( (v_vColour * texture2D( distortion_texture_page, v_vTexcoord)).xy);

	
    // FOR NORMAL MAPS:  (	either directX or OpenGL flip the green channel, 
    //			while you dont need to worry about it in GM more 
    //			normal maps have green pointing the wrong way)
    distort_amount.x = 1.0 - distort_amount.x;
	
    distort_amount -= 0.5;//128.0;
    if (distort_amount.x > 0.5) {distort_amount.x -= 1.0;}// wrap around
    if (distort_amount.y > 0.5) {distort_amount.y -= 1.0;}// wrap around
    distort_amount /= 4.0;


    gl_FragColor = v_vColour * texture2D( gm_BaseTexture, v_vTexcoord+distort_amount);

}

Now that we have the shader we need to apply it to something

Object Create Event:


#macro COLOUR_FOR_NO_MOVE make_colour_rgb(127,127,255)

// name of what you want it to be called in the shader
distortion_stage = shader_get_sampler_index(shader_fullscreen, "distortion_texture_page") 

application_surface_draw_enable(false)

Object Post Draw Event:

surface_distort = surface_create(room_width,room_height);
surface_set_target(surface_distort)

    draw_clear_alpha(COLOUR_FOR_NO_MOVE,0)

    // Anything we draw here will distort the screen
    draw_sprite(spr_example_distort,0,500,500)

surface_reset_target()

var surface_texture_page = surface_get_texture(surface_distort)

shader_set(shader_fullscreen)

    texture_set_stage(distortion_stage, surface_texture_page);
    draw_surface(application_surface,0,0)

shader_reset()

surface_free(surface_distort) // always remember to remove the surface from memory 

Whatever you draw to the Surface will now distort the screen, you can draw as many distortions on it as you like and those can have different amounts of opacity (which would end up changing the magnitude of the warping). You can replace spr_example_distort with as many bending images and changes as you like.

Screen Overlay Crack in GameMaker

The important part is texture_set_stage() we use this to pass the surface into the shader so it can read the information on it. surface_distort is the name I gave to the surface that has information about where every pixel should offset where it selects it's colour from.

Shockwave Overlay in GameMaker

So you can see this is a really easy way to add shockwaves to your GameMaker game or just bend the screen and use warping to add more juice to your projects like; cool water effects, impact ripples, glass effects, magnified glass zoom in/out.

GameMaker Warp Screen

How does it preform? It really doesn't have much of an impact, and while there might be a small overhead it doesn't increase much with huge numbers of simultaneous distortions.

GameMaker Ripple Shader

I've been calling these lens images Normal Maps in my mind, however they are technically not Normal Maps. You can grab any Normal Map and input it into this shader and it will work just fine, they are also much easier to find online so I'm keeping this format as close as I can to regular Normal Maps used for lighting.

Screen Warp Shader

Here is a nice image to get you started that will zoom out your screen that you can use for cool lens effects:

GameMaker Normal Map to Distort Screen

For anyone wanting to make these distortion images themselves I have some great tips on making them in GIMP/Photoshop so drop me a message.

Using a bit of masking you can even do some cool advanced things like this:

Lens Effect In GameMaker Shader Suck Screen In

Overlaying these two images allows you to pick only a selection of the warping you want. Using this we can create a direction to point the masking and in this case only suck things into the point you want.

GameMaker Warp Screen In

It's also a great way to add rain overlays and water effects to your games.

Rain Water Effect GameMaker

Show me what you make with this.

Medium Difficulty
GameMaker
By David Strachan