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 Add Shockwaves To GameMaker Game](/pages/gamemakerdistortscreen//i/add_shockwaves_to_gamemaker_game.gif)
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 Using Normal Maps in GameMaker to Warp The Screen](/pages/gamemakerdistortscreen//i/using_normalmaps_in_gamemaker_to_warp_screen.jpg)
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 GameMaker Fragment Shader](/pages/gamemakerdistortscreen//i/gamemaker_fragment_shader.jpg)
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 GameMaker Screen Distortion Shader](/pages/gamemakerdistortscreen//i/screen_distortion_shader_gamemaker.gif)
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 Screen Overlay Crack in GameMaker](/pages/gamemakerdistortscreen//i/screen_crack_overlay.gif)
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 Shockwave Overlay in GameMaker](/pages/gamemakerdistortscreen//i/gamemaker_shockwave_shader.gif)
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 GameMaker Warp Screen](/pages/gamemakerdistortscreen//i/gamemaker_warp_screen.gif)
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 GameMaker Ripple Shader](/pages/gamemakerdistortscreen//i/gamemaker_wripple_shader.gif)
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 Screen Warp Shader](/pages/gamemakerdistortscreen//i/screen_warp_shader.gif)
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 GameMaker Normal Map to Distort Screen](/pages/gamemakerdistortscreen//i/gamemaker_normal_map_to_distort_screen.png)
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 Lens Effect In GameMaker](/pages/gamemakerdistortscreen//i/lens_effect_in_gamemaker.gif)
![Shader Suck Screen In Shader Suck Screen In](/pages/gamemakerdistortscreen//i/gamemaker_pull_screen_in_suction.jpg)
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 GameMaker Warp Screen In](/pages/gamemakerdistortscreen//i/gamemaker_pull_screen_in_suction.gif)
It's also a great way to add rain overlays and water effects to your games.
![Rain Water Effect GameMaker Rain Water Effect GameMaker](/pages/gamemakerdistortscreen//i/gamemaker_rain_water_overlay.gif)
Show me what you make with this.