Water Shaders
- Arjun Singh
- Jul 9, 2017
- 3 min read

I decided to follow up my island project with an ocean. My intent was to spend a day animating some vertexes, but it didn't take long before I realized that's not how it works (I'm being ambiguous on purpose bear with me). In order to save memory and valuable processing cycles, developers figured out how to leverage the GPU. Simply put, the GPU's job is to take information about light and calculate the color of ever pixel on screen. The programmers control the GPU using a shader language. The graphics pipeline is a sequence run by the GPU that takes shader code and calculates output.
Of course, where better place to start my search than the internet. I looked through low poly art galleries to find out what properties of water I should pay attention to. Most of the professionals did one of two things: they used deep shades of flat blues or they used shiny, light blues. Some got creative by giving their water reflective or translucent properties. I wanted to try all of the above.
I first started experimenting with the standard shader. Unity gives it many useful properties. Being the default shader, I figured I didn't have to play with the code to get the water to look good. After reading the documentation, messing with the shader, and perusing forums, I figured out how to make my optimal shiny/reflective water. I found the metal and smoothness properties were the most useful. A skybox, a metal value of 1, and a smoothness value of 0.7 made the water super reflective. The addition of strategically placed reflective probes transformed the water into a mirror. In the picture above, I settled for a matte finish by decreasing the metal property to 0.3.
It was time to get my hands dirty by writing my own shaders. For all the beginners out there, writing your own shaders is tough and takes an exorbitant amount of time to learn; however, that shouldn't discourage you. Shaders are your ticket to the GPU. Let me say it again. The GRAPHICS PROCESSING UNIT! With study and practice you will make any visual you can think of. Unity has it's own thing called ShaderLab, but I used CG to write my code. I followed the beginner and intermediate shader tutorial series by unitycookie from CGCookie. The series are old but they contain a lot of powerful information. The few days I spent learning were well worth it. I could understand other people's shader code and study their techniques. Soon after, I was adding my own lighting effects to my creations.
I encountered a short video series by Creagines on YouTube that discussed toon-style water. The shorelines around the rocks caught my eye and I wanted to learn how to make my own. There is an interesting repository on GitHub that I downloaded and studied. It contains all sorts of assets that I ended up using in my final water. The repository has a script that uses a radial function for animating waves across a plane. I ended up testing all of my water shaders against that model. Also, the shaders he wrote revealed the way to use depth textures to create shorelines.
I want to point out some food for thought: a closer look at the script in the GitHub repository reveals a function that reorganizes all of the vertexes in the plane. This function can be discarded if the plane is procedurally generated and the vertexes are appropriately stored. Eliminating that function would probably increase efficiency.
Along the way I did experiment with translucent shaders, but I could never get them to look the way I wanted. For anyone who is interested, this blog describes a way to use geometry shading for poly water. I'm going to save procedural water for another time. I want to move on to my next project and move off of the Unity island. Ciao.
Commentaires