Toon Water Shader (Unity)
- Owen Hey
- Jun 3, 2021
- 3 min read
These days, the it seems the easiest way to generate traction for your game or idea is by having an impressive art style. Take a look at the Unity3D subreddit and you'll find a lot of impressive coding and projects, almost all of which are built upon an impressive groundwork of visual effects and shaders.
Some examples:
So in an effort to keep up, I've been putting a lot of effort into learning more about HLSL (High level shader languages), Unity, and the graphics pipeline in general.
My first project was a toon water shader. I decided to start here because of three reasons:
I found this wonderful tutorial by Roystan on the subject.
I love the toon art style - Breath of the Wild is one of my favorite games of the past decade.
Keeping a simple art style allows for easier expansion later on. As I'm not an artist, I don't see myself going for any photorealistic scenes any time soon. This shader could be used in my projects in the future.
Here is the final result:
A different scene with a warm-beach feel:
The one thing I thought the effect was missing was some vertex manipulation. It looked a little flat without a bobbing effect in the wind, so I added these lines to the vertex shader which alter the Y position of the vertices in a sin wave.

Following Roystan's guide, I was able to complete and understand the project fairly easily, even though I was programming in a completely new language to me (CG). That being said, it did make me reflect on why I (and assuredly others) struggle to learn shader programming.
In my experience, writing shaders presents two unique challenges:
The graphics pipeline can be tricky to work with.
If you have ever coded in OpenGL before, you know how much work it takes just to get a single cube to render on the screen. You have to set up vertex buffer arrays and objects, projection matrices, and call a million GL library functions before anything actually shows up.
In other words, drawing a cube on the GPU is never as simple as just dragging it into the scene as you would in a traditional game engine. And until recently with the advent of visual scripting for shaders, this was pretty much true in every system.
Unity's Shader Graph, which tries to fix this problem by streamlining the shader creation process:

So for someone like me, who isn't totally comfortable with relying entirely on this visual system (I want to know how it works under the hood), you need to work through the weeds of sending data to the shader, reading it in correctly, and not get frustrated with the lack of debugging tools.
Writing shaders requires a different mindset.
Shaders are weird - at least in comparision to normal coding on the CPU. Some major differences that come to mind are:
Everything being done in parallel. You no longer have access to variables from pixel to pixel - everything is happening all at once.
Code you think is way too slow to ever be used is suddenly available, and often encouraged! The GPU is so fast that you're able to write "bad" (bad in the context of CPU programming) code and be fine.
Interpolation is a strange concept. Knowing which things will get interpolated and how that will affect your output takes some getting used to.
This means that you can't just have an idea for a specific look you're trying to achieve and just make it - you need to know the right tools and techniques first. This takes practice and experience, and can be a hard hill to overcome for beginners (myself included).
All of this being said, I'm determined to learn more about the entire process, and hopefully be able to whip up great looking shaders on demand.
Comments