The goal is to make some cool effects using shaders and data that is passed in. But, before we do that, we are going to need to learn how to pass sprites, textures, and surfaces into a shader.




All four of the above images are made using the same tech, which we are going to walk through over the course of many articles.
I will be using GameMaker and GLSL for all of this. Also, I will be using the words “Sprites”, “Textures”, and “Surfaces” fairly interchangeably. Sprites and textures are technically the same thing, both are images containing data but while a sprite might be a drawing of an enemy or photo of a cat, a texture is more likely to be data used to manipulate things later on. Textures might also be seamless which means if you tile the same image next to each other they perfectly join together and the pattern continues.

For anyone not using GameMaker, a Surface is a temporary canvas that can be drawn on so that whole image can be used later on, these can also be passed into the shader to do all the cool stuff. You will just need to remember if my code says sprite_get_texture() you will need to put surface_get_texture().
And just for completeness a Texture Page or Sprite Sheet is just a collection of sprites all on one image.
If you are already familiar with the basics of shaders you will want to jump forwards to where we start sending texture information into the shaders.
Firstly, I want to very quickly go over how to send a simple number from your GameMaker code into a shader (like GLSL). Once we have this it’s easier to see the changes between sending a number and sending a texture into a shader.
CREATE EVENT:send_to_shader = shader_get_uniform(SHADER NAME, "name_in_shader")DRAW EVENT:
shader_set(SHADER NAME) shader_set_uniform_f(send_to_shader,DATA TO SEND) Draw something here shader_reset()SHADER CODE:
uniform float name_in_shader; // This will now contain the data put in the draw event.
While I didn’t intend this to become a full tutorial on shaders because there are better places to learn that, it is really important to understand vec2(), vec3(), vec4() because they are used so much in shaders. You can see these as being very similar to structs in GameMaker however they only contain either 2, 3, or 4 bits of data. The clever thing about them is any maths done on that variable is done to all of them. For example:
vec4 demo = vec4(1.0, 2.0, 3.0, 4.0); // This is how we create a vec in a shader demo *= demo; // This will now contain the values 1, 4, 9, 12 because the maths was done on all values inside the vec.
To access just one value inside we can refer to them as rgba or xyzw the shader doesn’t care which one and you can switch between them freely. For example, if you wanted to access the 3rd element of demo you could write either demo.b or demo.z (Both of these would return 3)
With this in mind lets now send and make a vec 2 in the shader.
CREATE EVENT:send_to_shader = shader_get_uniform(SHADER NAME, "name_in_shader")DRAW EVENT:
shader_set(SHADER NAME) shader_set_uniform_f(send_to_shader,FIRST DATA TO SEND, SECOND DATA TO SEND) // Notice this line has changed to add more data Draw something here shader_reset()SHADER CODE:
uniform vec2 name_in_shader; // This will now contain the TWO BITS OF DATA put from the draw event.
Just to complete the picture this is how you send an array to a shader:
CREATE EVENT:send_to_shader = shader_get_uniform(SHADER NAME, "name_in_shader")DRAW EVENT:
shader_set(SHADER NAME) shader_set_uniform_f_array(send_to_shader,[0,1,2,3,4,5,6,7,8,9]) // Notice this line has changed Draw something here shader_reset()SHADER CODE:
uniform float name_in_shader[10]; // This will now contain the all the data from the array
With all the code above we are able to send values from our GameMaker GML code that can be used inside the GLSL shader.
Lets just make one more example shader to practically do something with this code. I’m going to write a shader now where we pass in a decimal value from 0 to 1 and anything on the left of this value will be red and everything on the right of this value will be green.

CREATE EVENT:
shader_name = SHADER NAME send_to_shader = shader_get_uniform(SHADER NAME, "u_value");DRAW EVENT:
shader_set(shader_name); shader_set_uniform_f(send_to_shader , mouse_x/room_width); draw_sprite(spr_img,0,0,0) shader_reset();SHADER CODE:
varying vec2 v_vTexcoord; varying vec4 v_vColour; uniform float u_value; // passed from GM void main() { if (u_value > v_vTexcoord.x) { gl_FragColor = vec4(1.,0.,0.,1.); // Red } else { gl_FragColor = vec4(0.,1.,0.,1.); // Green } }
Please notice how the x value goes from 0 to 1 rather than using pixels. This is going to be really important later on because graphics cards don’t really use the measurement of pixels.
This first article has been longer than I hoped, however now we have these basics down it isn’t a big step more to do the fun stuff coming up.