Potion Liquid Shader Breakdown

Hi there, Perren here.
Welcome to my first post and quite an exciting one at that!

As of this post, 2Ginge will be in the process of submitting a nifty little asset that incorporates a little bit of trickery and approximated physics. I found the approach we took with the liquid shader included in this asset pack quite interesting and I 'd love to share the process with you on the chance that you will also find it interesting or at least informative. The following will breakdown the trickery and show exactly what is happening.

Present in this asset pack is a 'liquid' inside a 'glass' bottle with simulated liquid physics - animated in relation to overall bottle movement - and a variable liquid fill level, great for interactive bottle props in VR for example. We have a created a series of scripts and shaders that allow users to simulate the liquid physics (faked!) easily using their own meshes, or those provided in the asset pack.

Concepts covered in this breakdown:

  • Cutoff, level (or % of fill) of the liquid within the bottle.
  • Rendering an arbitrary fill surface of 'liquid'.

Not Covered:

  • Animation of the liquid (though it will be apparent how and to what variables it is applied, it will be covered in a follow up post). 
  • Glass Shader.
  • Volume of liquid 



The first image is the final result (minus the emission as it lessens the impact of lighting). As you can see, there is a surface to the liquid that responds to the directional light in the scene.

The image to the left shows the 'world' up as the vector in Red.
The dotted and (blue/) black line is the termination line (in local space) that the shader will start discarding fragments (not rendered).

(Note: if the up vector is rotated then the liquid itself can be rotated).

Illusionary Surface rendering:

Note: the image to the left is for reference for normal directions.

This is an example of the liquid mesh cut across the middle, which is a common occurrence when using discard shaders. Notice that the geometry facing away is lit darkly, we can use this to our advantage.

Let us suppose we render this mesh in two ways, one normally for ALL geometry that is facing us (basically a standard back face culled shader) and another for the geometry that is facing away from us.

For the geometry that is facing away we know that it will resemble the shell of the mesh, thus if instead of using the normals provided by the mesh we create some of our own that will represent our surface. Realistically, a surface is defined by light, not necessarily geometry.

Using the 'world up' vector as a normalized vector for the normal of the liquid surface, due to the front facing geometry rendering over most of this surface, it gives the illusion of a surface at the top of the mesh.

Surface Normal (inside vertex shader):

//Surface Normal
//_point is the middle of the surface
//_lowerBound is the bottom of the liquid,
    //hint when this rotates around the _point
    //then the surface changes angles!!!
out.normal = normalize(_point - _lowerBound);

Cutoff (inside fragment shader):

//Surface Level
//_point is the middle of the surface
//_localPos is the position of the pixel in local space
//_lowerBound is the bottom of the liquid,
    //hint when this rotates around the _point
    //then the surface changes angles!!!
fixed3 pixelDir = normalize(_localPos - _point);
fixed3 volumeDir = normalize(_point - _lowerBound);

//essentially if the angle is greater than 90 degrees, dont render.
if(dot(pixelDir,volumeDir) > 0)
    //dont render the fragment

Thank you for reading and supporting 2Ginge, we appreciate your interest and hope we are able to help you create your next great game with the tools we are providing.

If you have any questions, do get in contact with us at contact@2ginge.com.

- Perren Spence-Pearse

December Update

The end of 2016 is finally upon us! No matter what you may feel about the events that have transpired this year, now is an awesome time to take a break and have some much needed rest ahead of 2017. We hope you have a safe holiday period with family/ friends and can't wait to see you again next year!

Hello World

We're here! We did it. 

This post marks the beginning of 2Ginge, a game making partnership consisting of Perren Spence-Pearse and Jair McBain.

Presently we are putting the finishing touches on a number of tools for other developers that we have been working away on for the past few months. These tools will be available via the Unity Asset Store in the coming weeks and we hope you'll find them mighty useful. Keep your eyes peeled for release announcements via our mailing list, we'll be sure to make sure you're the first to hear.

As well as our tool development efforts, we've been working on a free to play Dice Rolling app with a very premium feel. We noticed that while there are many solutions for those looking for a simple digital dice roller, there were none that really made it an aesthetically pleasing experience. This is where we come in. Aside from simple dice rolling mechanics for RPG players, we're also going to be giving you a large variety of custom dice and rolling environments so you can control every element of your next tabletop RPG campaign. This project will be dropping Q1 2017 on iOS/ Android and Steam.

We're very excited to announce this venture and we hope that you will join us on the journey.

- Jair McBain