It was a busy two weeks experimenting on some tech to make the game look better. I’ll be talking on Normal Maps for 2d sprites and drawing hand made normal maps, deferred lighting and myst/fog shader

Normal Maps

These are typically used in 3d where you have the normals information stored in RGB of each pixel, so if you have 1,0,0 color the normal is sticking to the right (x), 0,1,0 the normal is sticking upward (y), and 0,0,1 the normal is sticking out in the Z direction.

These normals information are used with the lighting part of the shader so that it gives more depth to the rendering.

Go and have a look at this online tool to generate normal maps: https://cpetry.github.io/NormalMap-Online/

Unfortunately the generated normal maps (especially when it’s just from 1 diffuse image) are not accurate. There are other tools which will generate normal maps, some from multiple images with different lighting conditions, but I always wanted to experiment with drawing normal maps by hand.

You basically pick a color from a normal map containing a sphere, and paint with that color. You can use photoshop/Gimp or a more focused tool like Sprite Illuminator.

If you want to use Photoshop, you can use the 3d system where you can drop in a light and move it around to see how your normal map is behaving. This gives a nice tutorial on how to start: https://magazine.artstation.com/2019/04/handpainting-normal-maps-in-photoshop-with-nick-lewis/

Here are some other interesting articles on 2d sprites and normal maps:

https://www.gamasutra.com/view/news/312977/Adding_depth_to_2D_with_handdrawn_normal_maps_in_The_Siege_and_the_Sandfox.php
https://www.gamasutra.com/blogs/SvyatoslavCherkasov/20181023/329151/Graveyard_Keeper_How_the_graphics_effects_are_made.php
https://www.gamasutra.com/blogs/OliverFranzke/20140828/224326/Dynamic_2D_Character_Lighting.php

Deferred Lighting in Game Maker Studio 2

In order to calculate lighting on sprites, you need to use a shader to do the calculations per pixel, and if you have more than one light, the ideal is to use a deferred lighting shader. What this entails is to have different surfaces (buffers) where to draw the diffuse, normal maps, and specular, then pass these surfaces to the shader to calculate the resulting image. This causes a bit of nuisance in GM because you have to render the thing multiple times with different sprites (diffuse, normal, specular). I opted for splitting these 3 phases using GameMaker’s Draw Begin, Draw, and Draw End for diffuse, normal, and specular respectively. Then pass the surfaces at the end to finally draw to the application surface. Since I didn’t have time to draw all the normal/specular maps, I created default shaders to have a flat normal map for the current sprite, and no specular for current sprite.

I created the deferred lighting shader following this great resource:

https://learnopengl.com/

Myst/Fog Shader

I’m no shader guru but there are lots out there who do crazy stuff with black magic, i.e. insane math. There are some cool demos over shadertoy.com and you can easily adapt them to GameMaker Studio 2 with some tweaking to get it like you want it.

Also this resource is also interesting when it comes to shaders: https://thebookofshaders.com