Water Shader

A Venture I wanted to pursue to satisfy my curiosity for shaders used in enviroment art, This is the project that made me realise my passion for applied math in artistry endeavours. I’m extremely satisfied with the realistic look I achieved by learning a lot of different techniques used in shader crafting, hope you enjoy!

The Final Iteration: A Rewarding Challenge
This was the final iteration — not perfect, but my brain was firing on all cylinders! I had finally tapped into the visually rewarding side of problem-solving, and that realization was a game-changer.

For this version, I implemented a UV scrolling texture to create the desired effect, and used Screen Position to simulate reflections. The combination of these techniques helped bring everything together in a way that felt both functional and visually satisfying.

Using the Depth Buffer for Foam: A GLSL-Inspired Solution
Since I have a background in graphics programming with GLSL, leveraging the depth buffer for foam was a fun and intuitive solution. By using a simple Lerp, I could smoothly interpolate between water and foam based on the depth data. It gave me exactly the effect I was after, and the implementation was straightforward.

Sampling the depth buffer, I compared the water surface’s depth with surrounding geometry to identify areas where foam should appear. Using Lerp, I could blend the foam texture into those areas — creating natural transitions that look both dynamic and organic. This method not only worked flawlessly but also allowed me to keep the shader efficient, which was key in maintaining good performance.

It was one of those moments where the right solution clicked into place, and it felt rewarding to see the result come together so easily.

Implementing Physically Accurate Color Absorption in Unity Using Camera Depth

To enhance the realism of my Unity water shader, I simulated light absorption based on depth, modeling how light intensity diminishes as it passes through water.​

Shader Implementation Details:

  • Depth Sampling: I utilized Unity’s Shader Graph to obtain the fragment’s eye depth by using the Position node set to View space, splitting and negating the B/Z axis. ​Unity Discussions
  • Absorption Calculation: Incorporating the absorption coefficient, I computed the reduction in light intensity at various depths, adjusting the water’s color based on the light’s penetration depth.​
  • Color Blending: Using Shader Graph’s Lerp function, I blended the surface color with the absorbed color based on depth, achieving smooth transitions that mimic real-world light behavior within water.​

This approach not only provided the desired visual effect but also deepened my understanding of light-material interactions, reinforcing the value of integrating physical principles into shader development.

Refining Water Shader with Normal Map Blending and Foam Effects

In Unity, I enhanced my water shader by blending two normal maps to add depth and detail to the water surface. Utilizing Unity’s Shader Graph, I employed the Normal Blend Node to combine these maps effectively, ensuring a normalized result suitable for realistic water surfaces. ​Unity Manual

To simulate dynamic foam, I incorporated noise textures within the shader. By sampling a noise texture and adjusting its UV coordinates, I controlled the foam’s distribution across the water surface, achieving a natural and evolving appearance. ​

This integration of normal map blending and noise-driven foam significantly improved the shader’s realism, contributing to a more immersive visual experience.