272 lines
12 KiB
GLSL
272 lines
12 KiB
GLSL
// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
|
|
|
|
Shader "MesshingAround/Liquid_Effect (Built-in)"
|
|
{
|
|
Properties
|
|
{
|
|
[Header(Surface Inputs)]
|
|
[Header(Main Color)]
|
|
[NoScaleOffset]_LUTTex ("GradientTexture", 2D) = "white" {}
|
|
[HDR]_TopColor ("Top Color", Color) = (0, 0.6946828, 0.764151, 1)
|
|
[HDR]_Tint ("Tint", Color) = (1,1,1,1)
|
|
[NoScaleOffset]_MainTex ("Main Texture", 2D) = "white" {}
|
|
|
|
_GradientIndex ("GradientIndex", Float) = 73.9
|
|
_GradientCount ("GradientCount", Float) = 110
|
|
|
|
[Header(Foam Edge)]
|
|
_LineSmooth ("Foam Smoothness", Range(0,0.3)) = 0.026
|
|
[HDR]_FoamColor ("Foam/EdgeColor", Color) = (1,1,1,1)
|
|
_Line ("FoamWidth", Range(0,0.3)) = 0
|
|
|
|
[Header(Sine)]
|
|
_Freq ("Frequency", Range(0,25)) = 0
|
|
_Amplitude ("Amplitude", Range(0,0.2)) = 0
|
|
|
|
[Header(Rim)]
|
|
_RimPower ("Rim Power", Range(0,5)) = 2.44
|
|
[HDR]_RimColor ("Rim Color", Color) = (0.693879, 1, 0.3254717, 1)
|
|
|
|
// Hidden properties set by script - DO NOT REMOVE
|
|
[HideInInspector]_WobbleX ("Wobble X", Float) = 0
|
|
[HideInInspector]_WobbleZ ("Wobble Z", Float) = 0
|
|
[HideInInspector]_FillAmount ("Fill Amount", Vector) = (0,0,0,0)
|
|
[HideInInspector][NoScaleOffset]_GrayscaleTex ("GrayScaleTexture", 2D) = "white" {}
|
|
}
|
|
|
|
SubShader
|
|
{
|
|
Tags {"Queue"="Geometry" "RenderType"="Opaque" "DisableBatching" = "True" }
|
|
|
|
Pass
|
|
{
|
|
Zwrite On
|
|
Cull Off
|
|
AlphaToMask On
|
|
|
|
CGPROGRAM
|
|
#pragma vertex vert
|
|
#pragma fragment frag
|
|
#pragma multi_compile_fog
|
|
#pragma multi_compile_instancing
|
|
|
|
#include "UnityCG.cginc"
|
|
|
|
struct appdata
|
|
{
|
|
float4 vertex : POSITION;
|
|
float2 uv : TEXCOORD0;
|
|
float3 normal : NORMAL;
|
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
|
};
|
|
|
|
struct v2f
|
|
{
|
|
float2 uv : TEXCOORD0;
|
|
UNITY_FOG_COORDS(1)
|
|
float4 vertex : SV_POSITION;
|
|
float3 viewDir : COLOR;
|
|
float3 normal : COLOR2;
|
|
float3 fillPosition : TEXCOORD2;
|
|
float3 worldNormal : TEXCOORD3;
|
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
|
UNITY_VERTEX_OUTPUT_STEREO
|
|
};
|
|
|
|
sampler2D _MainTex;
|
|
float4 _MainTex_ST;
|
|
sampler2D _LUTTex;
|
|
sampler2D _GrayscaleTex;
|
|
|
|
// Non-instanced properties (fallback when instancing is disabled)
|
|
#if !defined(UNITY_INSTANCING_BUFFER_START)
|
|
float _GradientIndex;
|
|
float _GradientCount;
|
|
float3 _FillAmount;
|
|
float _WobbleX;
|
|
float _WobbleZ;
|
|
float4 _TopColor;
|
|
float4 _RimColor;
|
|
float4 _FoamColor;
|
|
float4 _Tint;
|
|
float _Line;
|
|
float _RimPower;
|
|
float _LineSmooth;
|
|
float _Freq;
|
|
float _Amplitude;
|
|
#endif
|
|
|
|
// GPU Instancing: Properties that can vary per instance
|
|
UNITY_INSTANCING_BUFFER_START(Props)
|
|
UNITY_DEFINE_INSTANCED_PROP(float, _GradientIndex)
|
|
UNITY_DEFINE_INSTANCED_PROP(float, _GradientCount)
|
|
UNITY_DEFINE_INSTANCED_PROP(float3, _FillAmount)
|
|
UNITY_DEFINE_INSTANCED_PROP(float, _WobbleX)
|
|
UNITY_DEFINE_INSTANCED_PROP(float, _WobbleZ)
|
|
UNITY_DEFINE_INSTANCED_PROP(float4, _TopColor)
|
|
UNITY_DEFINE_INSTANCED_PROP(float4, _RimColor)
|
|
UNITY_DEFINE_INSTANCED_PROP(float4, _FoamColor)
|
|
UNITY_DEFINE_INSTANCED_PROP(float4, _Tint)
|
|
UNITY_DEFINE_INSTANCED_PROP(float, _Line)
|
|
UNITY_DEFINE_INSTANCED_PROP(float, _RimPower)
|
|
UNITY_DEFINE_INSTANCED_PROP(float, _LineSmooth)
|
|
UNITY_DEFINE_INSTANCED_PROP(float, _Freq)
|
|
UNITY_DEFINE_INSTANCED_PROP(float, _Amplitude)
|
|
UNITY_INSTANCING_BUFFER_END(Props)
|
|
|
|
float3 Unity_RotateAboutAxis_Degrees(float3 In, float3 Axis, float Rotation)
|
|
{
|
|
Rotation = radians(Rotation);
|
|
float s = sin(Rotation);
|
|
float c = cos(Rotation);
|
|
float one_minus_c = 1.0 - c;
|
|
|
|
Axis = normalize(Axis);
|
|
float3x3 rot_mat =
|
|
{ one_minus_c * Axis.x * Axis.x + c, one_minus_c * Axis.x * Axis.y - Axis.z * s, one_minus_c * Axis.z * Axis.x + Axis.y * s,
|
|
one_minus_c * Axis.x * Axis.y + Axis.z * s, one_minus_c * Axis.y * Axis.y + c, one_minus_c * Axis.y * Axis.z - Axis.x * s,
|
|
one_minus_c * Axis.z * Axis.x - Axis.y * s, one_minus_c * Axis.y * Axis.z + Axis.x * s, one_minus_c * Axis.z * Axis.z + c
|
|
};
|
|
float3 Out = mul(rot_mat, In);
|
|
return Out;
|
|
}
|
|
|
|
float4 SampleLUTFromGrayscale(float2 uv, float gradientIndex, float gradientCount)
|
|
{
|
|
float grayscaleValue = tex2D(_GrayscaleTex, uv).r;
|
|
float v = (round(gradientIndex) + 0.5) / gradientCount;
|
|
float2 lutUV = float2(grayscaleValue, v);
|
|
return tex2D(_LUTTex, lutUV);
|
|
}
|
|
|
|
v2f vert (appdata v)
|
|
{
|
|
v2f o;
|
|
|
|
UNITY_SETUP_INSTANCE_ID(v);
|
|
UNITY_TRANSFER_INSTANCE_ID(v, o);
|
|
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
|
|
|
o.vertex = UnityObjectToClipPos(v.vertex);
|
|
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
|
|
UNITY_TRANSFER_FOG(o,o.vertex);
|
|
|
|
// Access instanced properties
|
|
float wobbleX = UNITY_ACCESS_INSTANCED_PROP(Props, _WobbleX);
|
|
float wobbleZ = UNITY_ACCESS_INSTANCED_PROP(Props, _WobbleZ);
|
|
float3 fillAmount = UNITY_ACCESS_INSTANCED_PROP(Props, _FillAmount);
|
|
|
|
// Calculate world position of vertex
|
|
float3 worldPos = mul(unity_ObjectToWorld, float4(v.vertex.xyz, 1.0)).xyz;
|
|
|
|
// Get object pivot position in world space (same as SHADERGRAPH_OBJECT_POSITION in URP)
|
|
float3 objectPosition = unity_ObjectToWorld._m03_m13_m23;
|
|
|
|
// Calculate position relative to object pivot
|
|
float3 worldPosRelative = worldPos - objectPosition;
|
|
|
|
// Apply fill amount offset
|
|
float3 worldPosOffset = worldPosRelative - fillAmount;
|
|
|
|
// Apply wobble rotations to the offset
|
|
float3 worldPosX = Unity_RotateAboutAxis_Degrees(worldPosOffset, float3(0,0,1), 90);
|
|
float3 worldPosZ = Unity_RotateAboutAxis_Degrees(worldPosOffset, float3(1,0,0), 90);
|
|
|
|
// Combine wobble effects
|
|
float3 wobbleOffset = (worldPosX * wobbleX) + (worldPosZ * wobbleZ);
|
|
|
|
// Final fill position: offset + wobble
|
|
o.fillPosition = worldPosOffset + wobbleOffset;
|
|
|
|
o.viewDir = normalize(WorldSpaceViewDir(v.vertex));
|
|
o.normal = v.normal;
|
|
o.worldNormal = normalize(mul((float3x3)unity_ObjectToWorld, v.normal));
|
|
return o;
|
|
}
|
|
|
|
fixed4 frag (v2f i, fixed facing : VFACE) : SV_Target
|
|
{
|
|
UNITY_SETUP_INSTANCE_ID(i);
|
|
|
|
bool isFrontFace = facing > 0;
|
|
|
|
// Access instanced properties
|
|
float wobbleX = UNITY_ACCESS_INSTANCED_PROP(Props, _WobbleX);
|
|
float wobbleZ = UNITY_ACCESS_INSTANCED_PROP(Props, _WobbleZ);
|
|
float amplitude = UNITY_ACCESS_INSTANCED_PROP(Props, _Amplitude);
|
|
float freq = UNITY_ACCESS_INSTANCED_PROP(Props, _Freq);
|
|
float gradientIndex = UNITY_ACCESS_INSTANCED_PROP(Props, _GradientIndex);
|
|
float gradientCount = UNITY_ACCESS_INSTANCED_PROP(Props, _GradientCount);
|
|
float4 topColor = UNITY_ACCESS_INSTANCED_PROP(Props, _TopColor);
|
|
float4 tint = UNITY_ACCESS_INSTANCED_PROP(Props, _Tint);
|
|
float4 foamColor = UNITY_ACCESS_INSTANCED_PROP(Props, _FoamColor);
|
|
float4 rimColor = UNITY_ACCESS_INSTANCED_PROP(Props, _RimColor);
|
|
float lineWidth = UNITY_ACCESS_INSTANCED_PROP(Props, _Line);
|
|
float lineSmooth = UNITY_ACCESS_INSTANCED_PROP(Props, _LineSmooth);
|
|
float rimPower = UNITY_ACCESS_INSTANCED_PROP(Props, _RimPower);
|
|
|
|
// Wobble intensity calculation
|
|
float wobbleIntensity = abs(wobbleX) + abs(wobbleZ);
|
|
|
|
// Sine wave wobble effect
|
|
float wobble = sin((i.fillPosition.x * freq) + (i.fillPosition.z * freq) + (_Time.y)) * (amplitude * wobbleIntensity);
|
|
|
|
// Moving fill position with wobble
|
|
float movingfillPosition = i.fillPosition.y + wobble;
|
|
|
|
// Sample textures and apply LUT with URP triple multiplication
|
|
fixed4 mainTex = tex2D(_MainTex, movingfillPosition.xx);
|
|
fixed4 lutColor = SampleLUTFromGrayscale(i.uv, gradientIndex, gradientCount);
|
|
|
|
// URP color system: MainTex * LUT * Tint
|
|
fixed4 col = mainTex * lutColor * tint;
|
|
|
|
UNITY_APPLY_FOG(i.fogCoord, col);
|
|
|
|
// Cutoff logic - step(movingfillPosition, 0.5)
|
|
float cutoffTop = step(movingfillPosition, 0.5);
|
|
|
|
// Foam calculation
|
|
float foamEdge1 = 0.5 - lineWidth - lineSmooth;
|
|
float foamEdge2 = 0.5 - lineWidth;
|
|
float foamSmooth = smoothstep(foamEdge1, foamEdge2, movingfillPosition);
|
|
float mainFoam = foamSmooth * cutoffTop;
|
|
|
|
// FRONT FACES
|
|
if (isFrontFace)
|
|
{
|
|
// Apply foam to front faces
|
|
float4 foamColored = mainFoam * foamColor;
|
|
float liquidMask = (1.0 - mainFoam);
|
|
float4 liquidColored = col * liquidMask;
|
|
|
|
// Rim light calculation (URP system)
|
|
float4 RimResult = float4(0,0,0,0);
|
|
if (rimPower > 0.001)
|
|
{
|
|
// URP: inverts power (5 - rimPower) for fresnel, then multiplies by original rimPower
|
|
float invertedPower = 5.0 - rimPower;
|
|
float fresnel = pow(1 - saturate(dot(i.worldNormal, i.viewDir)), invertedPower);
|
|
RimResult = fresnel * rimColor * rimPower;
|
|
}
|
|
|
|
float4 finalResult = liquidColored + foamColored;
|
|
finalResult.rgb += RimResult.rgb;
|
|
|
|
// Clip pixels above the fill line
|
|
clip(cutoffTop - 0.01);
|
|
return finalResult;
|
|
}
|
|
// BACK FACES - No foam on backfaces
|
|
else
|
|
{
|
|
clip(cutoffTop - 0.01);
|
|
|
|
// Solid top color on backfaces
|
|
return topColor;
|
|
}
|
|
}
|
|
ENDCG
|
|
}
|
|
}
|
|
} |