Graphics Shaders for hobby programmers: Newest Video: LUT maps

GM Version: GM:S 1.2+ | GMS 2
Target Platform: All
Download: N/A | Video Tutorial
Link | Playlist: https://www.youtube.com/playlist?list=PL0kTSdIvQNCNE-BDKOlYu628AalMmXy_P

Forums_Sneak_Peak.jpg

Summary:

The series is mainly for hobby programmers who are new to shaders or struggle understanding shaders. I don't intend to just deliver finished shader code for you to implement or I'd just make a marketplace asset. Instead I want the viewers to understand shaders and then be able to create their own effects in the end. So this series is most likely going to be a bit slow paced for people who are really good at programming already or people who are really good at maths - or viewers who just want the code.

I will explain how the GPU works on a basic level and how to think in GLSL. After that I'll gradually, video for video, add more functions and tools to use by showing and explaining sample code. The first few videos will be very slow paced so everyone can keep up, but after that I'll speed up a (little) bit.

Currently I plan to release one video per week but I'm not sure how long I can keep that pace when the lessons get more complicated.

I'll also provide a base project file to import into GMS2 (not GM:S1 though) with a basic setup to test shaders more quickly by providing sliders for the test room. Although convenient, this base project is not absolutely necessary to follow the series:

screenshot_brtsatcon.jpg



Contents:
  1. Shader Tutorial
  2. More shader effects
  3. Tutorials in preparation
  4. Planned (unsure yet)
  5. Not covered



1. Shader Tutorial:
These videos cover pretty much every important function in shaders. Afterwards you should be able to create your own effects without too much trouble.
  • Primer: Introduction P1: Explaining the GPU Pipeline and GLSL basics
    You will learn what the GPU does and how shaders are built.

  • Primer: Introduction P2: Working with vectors in GLSL
    You will learn how easy it is to work with vectors in GLSL. Vectors are extremely important to understand important since absolutely every shader works with them.

  • Primer: Base Project
    Aquick overview of the base project file for this tutorial series

  • Primer: First simple shaders
    A good starting point to explain a few important concepts about shaders.

  • Colours: Brightness, Saturation, Gamma & Contrast
    In many shaders you will need to understand brightness, saturation, gamma and contrast. An invaluable foundation for every shader programmer and a good opportunity to teach some more functions in GLSL.

  • Colours: Duotoning
    Time to exercise what we learned so far. Colours are so important in fragment shaders it's vital to know how they work by heart. And while learning that we'll again cover more functions in GLSL.

  • Colours: Sin City Effect & Reading Shader form Other People
    This is mainly about reading a shader written by someone else for another engine and even in another shader language.

  • Colours: Day & Night cycle
    The final 2 videos on colours in GLSL. Here we'll build a day and night cycle using GMS and GLSL.

  • Repetition 1
    A short video on the most important things learned so far for those who skipped several lessons with references to the videos a topic was taught.

  • Coords: gl_FragCoord & in_Position
    Finally it's time to learn about coordinate systems in GLSL.
    Many shaders use coordinate systems for different reasons: To change shape, to distort, to change colour based on position in room, in view, on a texture. This video is all about understanding room space and view space.

  • Introducing the new Base Project
    I created a new base project file for more flexibility and more options. This video is a short introduction on what's new and how to use some of the new features.

  • Coords: gl_FragCoord: Stans Coat (Monkey Island)
    Now that we understand gl_FragCoord it's time to put that knowledge to use replicating the Stans Coat effect from Monkey Island.

  • Coords: in_Position: Silhouette based on room position
    Now that we understand in_Position we'll be able to create a shader based on room space.

  • Coords: Vignette with texture coordinates
    Time to learn the next coordinate system. Texture coordinates are used in many shaders be it to change colours in specific regions of the image like in a vignette or to distort the image like in a blur.
    In this video we'll learn more about texture coordinates (uvs) and how to work with them.

  • Coords: Vignette with corner id
    Texture coordinates can be very difficult to handle. Sometimes you just want a coordinate system going from 0 to 1. That's where the coordinate system based on corner id comes in handy.
    In this video we'll learn what corner ids are and how to use them.

  • Blur a: Multiple Texture Samples
    This video starts a set of videos where you learn to blur an image. The first version will be very simple but very inefficient. The following videos will build on that knowledge and code to make the blur shader more efficient and finally run full screen on a tablet.

  • Blur b: Multiple Render Passes
    The first improvement will be something maybe unexpected: The performance greatly increase if we send the image twice to the shader instead of once. A horizontal pass and a vertical pass.

  • Blur c: Using the GPUs Linear Interpolation
    This improvement is simple in concept and tricky in maths. The idea is instead of taking a sample at the center of a texel we can take a sample between texels and the GPU will blur with linear interpolation at no additional cost nearly doubling the speed to calculate the blur. The tricky part is where exactly to take the sample.

  • Blur d: Blur further with scaling
    This brings a tremendous final improvement in performance - but at a cost as we will see. By downscaling, blurring and upscaling again we get a huge speed boost but depending on the game we'll also get some nasty flickering pixels if we scale by too much.

  • Blur e: Hardcoded blur
    Up to here we used a shader capable of changing blur size and quality at any given time. Often you won't needed that flexibility. So to speed up the process we can use hardcoded values. In this video I'll show how to get those values.

  • Repetition 2
    A short video on the most important things learned since the first repetition video for those who skipped several lessons with references to the videos a topic was taught.

  • Bloom 1: Multiple Textures in a Shader
    Now that we learned about burring, We can finally create a shader that builds on that knowledge: The bloom or glow shader.

  • From GLSL ES to HLSL 11
    Before going on with improving the bloom shader we'll need to learn HLSL. This video will show the basics of HLSL for people who know some GLSL ES already.

  • Bloom 2: Bloom per layer with multiple render targets (MRT)
    Multiple render targets allows a shader to draw to two surfaces with one draw call. We'll use this to create a bloom effect where each layer gets it's own bloom uniforms.



2. More shader effects:

The previous videos covered shader basics. From now on the videos will focus on specific effects.

  • Luma Mask: Dissolve Shader basics
    How to use a luma mask to create a dissolve shader. This is the basic version. More features will be added in future videos.

  • Luma Mask: uv remapping & vertex buffers
    Ever wondered how the heck you can use v_vTexcoord to get samples from a second texture on a different mixed texture page? UV-remapping and vertex buffers to the rescue!

  • Luma Mask: add a 2-coloured rim
    Time to pimp our luma mask shader. In this video we're adding a solid 2-coloured rim.

  • Luma Masks: coloured ramp
    And another way to add more juice to the luma mask shader: adding a fire effect.

  • Luma Masks: how to draw luma masks in gimp
    Sounds simple but is kinda tricky. This video will help you avoid the mistakes I made.

  • Distortions: tunnel distortion
    A distortion shader turning a 2D image into the inside of a tunnel like the spinning tnnel in Castlevania IV. The distortion is based on maths.

  • Distortions: magnifying glass 6 chromatic aberration
    A distortion shader magnifying an image or surface and colour manipulation like chromatic aberration. This distortion is based on maths.

  • Distortions: heat haze
    A distortion shader to simulate heat haze. This shader uses a distortion map instead of maths.

  • Distortions: Flag
    A distortion shader to simulate a flag waving in the wind using a distortion map.

  • Distortions: Flame
    A distortion shader to simulate a flickering flame using a distortion map.

  • Distortions: Side-Scroller Water
    A distortion shader to simulate a fore-ground water surface with reflections, distortions and colouring.

  • Distortions: Shockwave
    A sprite based showckwave distortion effect. Means the shockwave doesn't ned to be a circle.

  • Blender: Create normal maps for 2D games
    Normal maps for 2D games always use a global coordinate system where the z-axis is pointing out of the view. This video explains how to create a normal map from a 3D mesh in that global coordinate system using blender.

  • Recolouring: Gradient Maps
    A very simple recolouring technique: gradient maps like in photoshop or gimp & co

  • Recolouring: LUT Maps
    A very versatile recolouring technique: LUT maps can be created in Photoshop & other image manipulation programs and are used to remap colours.



3. Tutorials in preparation:

  • more distortion shaders & techniques



4. Planned (unsure yet):
  • A collection of useful shaders like, glitches, holograms, normals, lighting and more - depending on how much time i got available and on my maths and tech limitations



5. Not covered:
  • 3D-shaders
    Simply because I don't know much about 3D and don't plan to learn it.
  • Manipulating vertex positions
    Because GM Wolf has a great tutorial on that with a waving grass shader:
 
Last edited:
Just added a new Video.

This time is about Gamma, Brightness, Contrast and Saturation.

Those are all image manipulation methods important to many other shaders and so really important to understand.

screenshot_brtsatcon_cut.jpg
 
Last edited:
Just added a new Video.

This time is about Duotoning.

Purpose of this video is to teach some more functions and execise some more using colours. Colours are so important I thought I make a few exercise videos before moving on to completely new things. The next two weekends will still be about colours as well.

duotone-preview_small.png
 
Last edited:
Added a new Video.

This time it's a sin city effect shader.

Main purpose is learning to read a shader written for another engine and in another shader language and implementing it in GMS.

sincity_preview_small.png
 
Last edited:
J

JakeW

Guest
GM Version: GM:S 1.2+ | GMS 2
Target Platform: All
Download: N/A | Video Tutorial
Link | Playlist: https://www.youtube.com/playlist?list=PL0kTSdIvQNCNE-BDKOlYu628AalMmXy_P

View attachment 14040

Summary:

The series is mainly for hobby programmers who are new to shaders or struggle understanding shaders. It's most likely going to be a bit slow paced for people who are really good at programming already or people who are really good at maths.

I will explain how the GPU works on a basic level and how to think in GLSL. After that I'll gradually, video for video, add more functions and tools to use by showing and explaining sample code. The first few videos will be very slow paced so everyone can keep up, but after that I'll speed up a bit.

Currently I plan to release one topic per week - which can be multiple videos - but I'm not sure how long I can keep that pace when the lessons get more complicated.

I'll also provide a base project file to import into GMS2 (not GM:S1 though) with a basic setup to test shaders more quickly by providing sliders for the test room. Although convenient, this base project is not absolutely necessary to follow the series:

View attachment 14039

Uploaded Tutorials:
  • Primer: Introduction P1: Explaining the GPU Pipeline and GLSL basics
    You will learn what the GPU does and how shaders are built.

  • Primer: Introduction P2: Working with vectors in GLSL
    You will learn how easy it is to work with vectors in GLSL. Vectors are extremely important to understand important since absolutely every shader works with them.

  • Primer: Base Project
    Aquick overview of the base project file for this tutorial series

  • Primer: First simple shaders
    A good starting point to explain a few important concepts about shaders.

  • Colours: Brightness, Saturation, Gamma & Contrast
    In many shaders you will need to understand brightness, saturation, gamma and contrast. An invaluable foundation for every shader programmer and a good opportunity to teach some more functions in GLSL.

  • Colours: Duotoning
    Time to exercise what we learned so far. Colours are so important in fragment shaders it's vital to know how they work by heart. And while learning that we'll again cover more functions in GLSL.

  • Colours: Sin City Effect & Reading Shader form Other People
    This is mainly about reading a shader written by someone else for another engine and even in another shader language.

  • Colours: Day & Night cycle
    The final 2 videos on colours in GLSL. Here we'll build a day and night cycle using GMS and GLSL.

Tutorials in preparation:
  • Repetition 1
    A short video on the most important things learned so far for those who skipped several lessons with references to the videos a topic was taught.

  • Coords: gl_FragCoord & in_Position
    Finally it's time to learn about coordinate systems in GLSL.
    Many shaders use coordinate systems for different reasons: To change shape, to distort, to change colour based on position in room, in view, on a texture. This video is all about understanding room space and view space.

  • Coords: gl_FragCoord: Stans Coat (Monkey Island)
    Now that we understand gl_FragCoord it's time to put that knowledge to use replicating the Stans Coat effect from Monkey Island.

  • Coords: in_Position: Silhouette based on room position
    Now that we understand in_Position we'll be able to create a shader based on room space.

  • Coords: Vignette with texture coordinates
    Time to learn the next coordinate system. Texture coordinates are used in many shaders be it to change colours in specific regions of the image like in a vignette or to distort the image like in a blur.
    In this video we'll learn more about texture coordinates (uvs) and how to work with them.

  • Coords: Vignette with corner id
    Texture coordinates can be very difficult to handle. Sometimes you just want a coordinate system going from 0 to 1. That's where the coordinate system based on corner id comes in handy.
    In this video we'll learn what corner ids are and how to use them.

Planned (unsure yet):
  • Further Exercising texture coordinates
  • Multi-pass rendering
  • Multi-target rendering
  • Passing in multiple textures into a shader
  • Luma Masks
  • Surface, Blendmodes & premultiplying alpha
  • Using vertex buffers
  • A collection of useful shaders like tunnel distortion, glitches, holograms, normals, lighting and more
Very useful, thank you. I'll be referring back to this for sure lol
 
These look amazing. Thank you so much for these, @The Reverend. I watched a few minutes of one now, and I can tell these are going to be great. Can't wait to go through these tomorrow after work.

It looks like you might be planning some stuff like/close to this already, but I tried understanding how the common "underwater/heatwave" sine shader and "pixelate screen transition" shaders work, and couldn't get either one of them. I don't think I'll need these specific examples after watching your videos anyway, but figured I'd mention them if you're looking for ideas later on.

Either way, thanks again for the videos. Just skimming them, I can tell they're going to help a lot. They look really well thought out and thorough. Very cool of you to do these.
 
Last edited:
Thanks alot, @RichHopelessComposer

I do plan to add some distortions. The first distortion effect will be a blur however because it's the foundation for other shaders, teaches several new concepts and it is actually difficult to create a large, smooth blur that runs on a mobile full screen. A sine wave distortion wouldn't but too much different from a blur though I guess. I haven't made one yet, but it's on the todo list. I'm learning while doing this series :)

The pixelate I'd probably not do in a shader. I wonder if it's not easier to just turn off the automatic drawing of the application surface, draw that downscaled to a post processing surface in draw gui end and then draw the post processing surface upscaled to the screen. If you turn of the linear texture filter on the GPU the result is pixelated.
 

Bingdom

Googledom
I've been wanting to know how to make a day/night shader for a long time. Thank you for this!

To be a bit nit-picky with the math, you can use this:
Code:
y=cos(2*x*pi)*a - s
cos pretty much gives you that .5 offset.

You can write pi in both game maker and desmos.

If you ever want to specify the limits for the graph, use brackets. e.g.
Code:
y=cos(2*x*pi)*a-s {0<=y<=1} {0<=x<=1}
upload_2017-11-13_23-51-10.png
Will do this
upload_2017-11-13_23-48-32.png
It probably doesn't help visualise though.

The pixelate I'd probably not do in a shader. I wonder if it's not easier to just turn off the automatic drawing of the application surface, draw that downscaled to a post processing surface in draw gui end and then draw the post processing surface upscaled to the screen. If you turn of the linear texture filter on the GPU the result is pixelated.
It might be better to resize the application_surface using surface_resize then just draw the surface upscaled using draw_surface_ext (if it needs to be upscaled or drawn manually, otherwise I think it upscales automatically if it's drawn automatically).

Also, the neutral position you pointed out in photoshop in the second part, 128 isn't the centre. 127 is because it starts from 0. 256 - 1 = 255. 256/2 - 1 = 127
 
Last edited:
To be a bit nit-picky with the math, you can use this:
That's what I mean when I state I'm not really good at maths in every video. Thank you :)
I'm really glad if you guys help me and other viewers getting better by giving tips. Please write a comment below the videos if you see improvement because I think more people will be reading it then (at least as long as there's not lots of comments).

If you ever want to specify the limits for the graph, use brackets. e.g.
Thanks, nice to know that functionality :)
 
Just added a new Video.
This time we'll learn about the coordinate systems gl_FragCoord and in_Position.

gl_FragCoord_and_in_Position-preview-256px.png


The next two videos we'll create two simple shaders using these systems and after that we'll move on to new coordinate systems: texture coords and then corner id.
 
A

AleHitti

Guest
Nice playlist! I'll check it out in a bit, since there seem to be a few things I don't know about shaders here. Keep it up!
 
Just added a new Video.

This time it's about blurring.

Since blurring is a rather big topic, I'll split that into several videos. This first video is about the basics and creating a foundation to build upon. After this video you'll understand how we can blur and have an extremely inefficient blur shader. During the next videos we'll improve the code step by step though.

4-slice-preview-small.png
 
Last edited:

Juju

Member
Fabulous work as always. I don't check the GMC so often but I'll try to stay informed via YouTube.

If you feel the inclination, we'd certainly like for you to share your work on the /r/GameMaker Discord server: https://discord.gg/By6u9pC
 
Just added a new Video.

This time we're once more going to increase the performance of our blur shader by downscaling before blurring. This is a huge improvement in performance but depending on what you blur, can also cause an annoying flickering effect.

4-slice-preview.png
 
Hey, @The Reverend! Thanks for the great work again. I fell off the shader wagon for awhile, but I'm starting to watch your videos again. I'm rewatching the first blur video right now, and there's one thing I'm not sure of, and would like to confirm with you. When we do a fragment shader like a blur....we blur a pixel by taking an average of all the pixels around it, and changing its color based on that. Then the fragment shader moves onto the next fragment/pixel that needs to be blurred, and we repeat the process. My question is this: is the second pixel being blurred based on the original unaltered pixel on the side of it? Or is it being blurred based the first pixel's new color after being blurred?

I imagine the fragment shader must base everything we do on the original unaltered image, right? And then change every fragment "at once" when the shader is done running for the frame? Otherwise we'd get weird results?
Probably a stupid question, but it's been bothering me a little, hahah. Thanks again for your videos and help! I'm going to try getting back into them again! =D
 

Lonewolff

Member
Hey, @The Reverend! Thanks for the great work again. I fell off the shader wagon for awhile, but I'm starting to watch your videos again. I'm rewatching the first blur video right now, and there's one thing I'm not sure of, and would like to confirm with you. When we do a fragment shader like a blur....we blur a pixel by taking an average of all the pixels around it, and changing its color based on that. Then the fragment shader moves onto the next fragment/pixel that needs to be blurred, and we repeat the process. My question is this: is the second pixel being blurred based on the original unaltered pixel on the side of it? Or is it being blurred based the first pixel's new color after being blurred?

I imagine the fragment shader must base everything we do on the original unaltered image, right? And then change every fragment "at once" when the shader is done running for the frame? Otherwise we'd get weird results?
Probably a stupid question, but it's been bothering me a little, hahah. Thanks again for your videos and help! I'm going to try getting back into them again! =D
It's based on the original unaltered pixel.
 
It's based on the original unaltered pixel.
Thanks, dude! That's what I figured, but it always freaked me out and confused me a little, hahah!
So basically, the shader stores a copy of the original image, works off that whenever we grab a fragment, and then writes to a new image whenever we tell it to write anything, right?
....yes, that's exactly what you just said. I have OCD or something, though. Stuff like this gives me a mental block unless I know with 100% certainty what I'm working with, hahah. X'D
 

Lonewolff

Member
Yep, pretty much.

All the shader does is look at a pixel and then performs the calculation on that, then passes it to the output.

That's why GPU's have so many cores. They can calculate a heap of these pixels concurrently as the calculation is done on a single pixel, it doesn't care what is going on with the pixels around it.
 
So basically, the shader stores a copy of the original image, works off that whenever we grab a fragment, and then writes to a new image whenever we tell it to write anything, right?
Actually we're passing in a texture, take samples from the current fragment and surrounding fragments on that texture and draw the result to a different texture.
In example in the very first blur shader (the very ugly inefficient one) in "obj_blur_1_pass_isoweight_discrete"s draw event we drew a sprite texture to the application surface. So the original texture, the sprite, remains unchanged. Same goes for all other blurs in this series.

Afaik you shouldn't draw to the same texture as the one you're drawing (I don't know for sure, just read you shouldn't). So you shouldn't i.e. do this:
surface_set_target(srf_main);
shader_set(shd_cool_gfx);
draw_surface(srf_main);
shader_reset();
surface_reset_target();

I don't know if you can do that at all, but if you can:
Afaik you can't control the order in which the fragments are drawn. I read somewhere that the cores on the GPU just pick any unprocessed fragment and when they're done pick any other unprocessed fragment. So they're not processed one by one from top left to bottom right or the like if I understood that correctly.

But as I keep mentioning, I'm no pro in shader stuff; just sharing what I learned and read :)
 

bbbower

Member
I first seen this and thought, hey neat .. then i listened and thought wow cool, now i've watched almost all of them and seen the tools, freaking awesome! Thanks a bunch! I search the tutorial stuff all the time i don't know I hadn't stumbled across your videos by now!
 
Just added a new Video.

This time is about translating a GLSL ES shader to HLSL. We'll need that in the next video because that shader won't be possible with GLSL ES.
 
Top