Learning Shaders
Shaders are essentially programs written in specific “shading languages” targeted to run on GPUs, to control various aspects of the rendering pipeline such as lighting, color, texture.
You can think of shaders as the equivalent of the Gutenberg press for graphics. Shaders are a set of instructions for parallel processing every pixel on the screen. It’s like a high-level program for pixel pumping.
Shaders itself is not a language. The language used, especially in modern shaders programming, is usually GLSL (OpenGL Shading Language). The syntax is similar to C, but with lots of math involving vectors and matrices.
Shaders are executed directly by device GPU, maximizing as much parallel processing power as possible to render pixels. That’s kinda the whole point: it’s a program designed around the parallel processing capabilities of GPU for the end goal of putting graphics on the screen.
In some ways, you can think of shaders as a hyper-multi-threaded language for creating graphics using your device’s GPU. Except each pixel is like a thread.
A Mental Model of Shaders
There’s a scene from the Simpsons where homer demonstrates one of his new inventions: a makeup gun. Instead of having to spend a bunch of time applying makeup, the gun shoots all of the makeup onto a face in one shot, poof.
Applying makeup the traditional way is kind of like rendering a graphic the traditional way — piece by piece, stroke by stroke. We add a polygon and fill it. We add a stroke and fill it. Just like we apply one stroke of eyeliner, then apply blush, etc.
Shaders are like the makeup gun: every pixel comes out at the same time in one concurrent blast. GPU goes boom and everything is on the screen.
Let’s ignore the fact that this would definitely not pass the vibe check nowadays, definitely not okay to shoot your partner in the face.
Developing Shaders
That makeup example might help us realize: shaders are not executed line by line like a normal programming language. Because of this multi-threaded/concurrent nature of the way shaders are executed, it’s harded to debug and harder to observe the values that are actually being passed through the shader.
It’s like building a tiny ship in a bottle.
That’s the best way I can describe it.