Skip to content

Instantly share code, notes, and snippets.

@cortvi
Last active June 18, 2024 06:46
Show Gist options
  • Save cortvi/876ef402b400eddc3450d147c9e4830f to your computer and use it in GitHub Desktop.
Save cortvi/876ef402b400eddc3450d147c9e4830f to your computer and use it in GitHub Desktop.
Simple shader that imitates a liquid moving inside a vessel.
// Created by @cortvi
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// This script lets you easily control the amount of fluid,
// but you have to manually set up the height values!
[ExecuteInEditMode]
public class LiquidControl : MonoBehaviour
{
[Range(0f,1f)]
public float fillLevel; // How full it is
public double fullHeight; // Height at which vessel is full
public double emptyHeight; // Height at which vessel is empty
int _Level;
Material mat;
float currentLevel;
private void Update()
{
if (fillLevel == currentLevel) return;
var lerp = Mathf.Lerp (emptyHeight, fullHeight, fillLevel);
mat.SetFloat (_Level, lerp);
// Cache the value
currentLevel = fillLevel;
}
private void OnEnable ()
{
_Level = Shader.PropertyToID ("_Level");
#if UNITY_EDITOR
if (UnityEditor.EditorApplication.isPlaying)
mat = GetComponent<Renderer> ().material;
else
mat = GetComponent<Renderer> ().sharedMaterial;
#else
mat = GetComponent<Renderer> ().material;
#endif
}
}
/// Created by @cortvi
Shader "Custom/Simple liquid volume"
{
Properties
{
_Color ("Liquid color", Color) = (1,1,1,1)
// For this shader to work properly, the mesh should
// have its pivot point on the geometric center of the object.
_Level ("Fill height (object space)", Float) = 0
}
SubShader
{
Tags
{
// You may want to modify the queue
// for the object to correctly draw behind other
// transparent materials, such as a glass vessel
"Queue"="Transparent"
}
Cull Off
CGPROGRAM
#pragma surface surf Standard fullforwardshadows vertex:vert
struct Input
{
float3 worldPos;
};
fixed4 _Color;
float _Level;
void vert (inout appdata_full v, out Input o)
{
UNITY_INITIALIZE_OUTPUT (Input, o);
// Calculate view direction in object-space
float3 viewDir = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos.xyz, 1)).xyz - v.vertex.xyz;
// Replace the face normal by the view direction
// this way you cannot see that the object is hollow
v.normal = normalize(viewDir);
}
void surf (Input IN, inout SurfaceOutputStandard s)
{
// Get the object Y by its mdoel matrix
float objectPosY = unity_ObjectToWorld._m13;
// Calculate the highest point in world-space of the liquid
float3 targetDistance = objectPosY + _Level;
// Discard pixels that are over liquid's highest point
float value = targetDistance - IN.worldPos.y;
clip(value);
// Just pass the liquid color.
// You could actually do some texture work here!
s.Albedo = _Color;
}
ENDCG
}
FallBack "Diffuse"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment