If you've been using GameMaker Studio 2 for any length of time, you will almost certainly have come across blend modes, and probably even used them in your games. Blend modes are a great way to change how something is drawn to give interesting and specific graphical effects, but do you know how they work? This is a subject that can confuse people and so in this and the following article we hope to dispel some of the mystery surrounding blend modes and enable you to use them to their fullest extent in your games.
Blend modes basically tell your game to draw certain things blended with whatever else is already drawn beforehand. Everything you draw to the screen is made up of four component parts - red, green, blue and alpha - and by default they are drawn to the screen using the blend mode
bm_normal. This blend mode draws all pixels with their colour and alpha values essentially unchanged (although, in part two of this article you'll see that this isn't quite true...), but GameMaker Studio 2 has a number of built in blend modes that can be set to change this behaviour.
When GameMaker Studio 2 goes to draw a pixel there's a source colour (the colour of the pixel you are going to draw) and a destination colour (the colour that's already in the pixel we're drawing to). When determining the new colour of the pixel, GameMaker will combine the source and destination colours according to the blend mode, as mentioned above. Each component of the colours is stored as a floating point value between 0 and 1, and the new colour is calculated by multiply each component of the source colour by some factor and by multiplying each component of destination colour by some other factor and then adding the results together component by component.
BASIC BLEND MODES
GameMaker Studio 2 uses the function
gpu_set_blendmode() to change the blending that your game uses for drawing. You would call this before (for example) drawing a sprite, then set it back again afterwards, something like this:
gpu_set_blendmode(bm_add); draw_self(); gpu_set_blendmode(bm_normal);
That code draws the instance sprite using an additive blend mode. The additive blend mode is set using one of the available GML constants, of which there are four for basic modes:
bm_normal bm_add bm_subtract bm_max
We have seen already how
bm_normal looks - since that's what everything defaults to! - so let's continue on to look at the other three in a bit more detail...
This blend mode adds the colours of the source and destination pixels together (but does not affect the alpha values). For example, if your background image is a solid colour with an RGB value of (100,15,70), and then you draw a rectangle with an RGB of (120,25,30), then (using
bm_add) the fina RGB values for each pixel of the rectangle would be (220,40,100). Note that colour values can't go over 255 (or under 0), so anything that adds up to more than that will be clamped to 255.
Using this blend mode is a great way to get that "neon glow" look, and is most often used for lighting effects, or lasers or just about anything that you want to appear to glow or have luminescence.
This blend mode is a bit different to the previous one, as it it works on a percentage basis rather than a direct value. This percentage is what will be subtracted from the destination colour (the colour of the pixel being drawn to). To explain this better, let's look at an example.
Imagine you want to reduce the red value of all pixels drawn in an area of the room by 25%. You would first need to get 25% of 255, then convert that into an RGB colour value, and then finally use that along with
bm_subtract to draw over the area. Something like this:
var red = (25 / 100) * 255; var col = make_colour_rgb(red, 0, 0); gpu_set_blendmode(bm_subtract); draw_rectangle_colour(0, 0, 128, 256, col, col, col, col, false); gpu_set_blendmode(bm_normal);
Following the same rule, if you wanted to simply reduce the brightness of a background by 50% then you would have a colour that is 50% red, 50% green and 50% blue, ie: RGB (128, 128, 128). This blend mode is mainly used for drawing shadows, or creating interesting fade out effects.
This blend mode is more complex to explain, but it basically multiplies the source colours by the source alpha, then adds them to the destination colour values multiplied by the inverse source colour values. The actual maths behind
bm_max (and the other blend modes) we'll cover in part two of our article, but all you need to know is that the result will be a more "saturated" and brighter colour, without leading to the same pure white brilliance that using
bm_add will cause.
This blend mode can be useful when you need to draw overlapping images without them becoming so bright that they can't be seen. The bright parts will become brighter, but they should still maintain a level of colour and hue. Note though that the alpha value of the source image will also influence in the final effect when using this blend mode.
Now you know the very basics behind using a blend mode in GameMaker Studio 2. It takes the RGB and alpha values for the source image (what is being drawn) and it then blends these with the RGB and alpha values of the destination (what is being drawn too). This blending is done by multiplying the individual components for each pixel colour and alpha by different amounts, depending on the effects that we wish to achieve. With this knowledge, you can start to use blend modes in your games to get glowing lasers, realistic shadows, or saturated transition effects, but there is still more to be learned here! In part two of this article we will look at the extended blend modes, as well as explore a bit of the maths behind them, so that you can create your own blending effects like multiply or overlay.
One final thing to note about using blend modes... they break the vertex batch when drawing, so you should try not to call them in a load of different instances at once. It'll be more efficient to have a controller object that sets the blend mode and then uses
with() or some other method to draw the required images before resetting the blend mode back to normal again.