Liquid Potion Shader

This shader was made for Harry Alisavakis’s weekly shader challenge.

Liquid simulation is not practical for games. It is usually faked to appear as if it is simulated, with basic dynamics. A custom shader can be used to implement it easily.

For example, a potion brewing game could use a custom shader to create a realistic looking liquid. This could be used to show the progress of a potion being brewed, with the liquid changing color and becoming more viscous over time. Furthermore, a custom shader could be used to create ripples and waves in the liquid, making it appear even more realistic.

The first step to implement the shader is to make the liquid rotate in response to the container.

float4 RotateAroundZInDegrees (float4 vertex, float degrees)
       {
            float alpha = degrees * UNITY_PI / 180.0;
            float sina, cosa;
            sincos(alpha, sina, cosa);
            float2x2 m = float2x2(cosa, -sina, sina, cosa);
            return float4(mul(m, vertex.xy), vertex.zw).zxyw;
       }
float4 RotateAroundXInDegrees (float4 vertex, float degrees)
       {
            float alpha = degrees * UNITY_PI / 180.0;
            float sina, cosa;
            sincos(alpha, sina, cosa);
            float2x2 m = float2x2(cosa, -sina, sina, cosa);
            return float4(mul(m, vertex.zy), vertex.zw).zxyw;
       }

In the vertex shader I added distortion by applying a texture to the UV

.
.
float4 wPos = mul(unity_ObjectToWorld,v.vertex);
float4 wObjPos = mul(unity_ObjectToWorld, float4(0,0,0,1));
float4 finalPos = wPos - wObjPos;
float4 posRotX = RotateAroundXInDegrees(finalPos,-90 * (1+_OffsetX));
float4 posRotZ = RotateAroundZInDegrees(finalPos,-90 * (1+_OffsetZ)); 
o.objPos = finalPos + posRotX + posRotZ;
_NoiseTex_ST.z += _Time.y;
o.uv = TRANSFORM_TEX(v.uv, _NoiseTex);
.
.

In the fragment shader, I applied some noise texture to add an organic look

.
.
float fresnel = dot(i.normal, i.viewDir);
fresnel = saturate(1 - fresnel);
fresnel = pow(fresnel, _FresnelAmount);
fixed4 fresnelColor = fresnel * _FresnelColor;
float4 noiseTex = tex2D(_NoiseTex, i.uv) * _NoiseAmount * abs(_OffsetX+_OffsetZ);
float4 lqTex = lerp(float4(1,1,1,1),noiseTex,_LiquidTexAmount)*_LiquidTexColor;
.
.