358 lines
15 KiB
GLSL
358 lines
15 KiB
GLSL
Shader "Custom/UniversalLiquidSurface"
|
|
{
|
|
Properties
|
|
{
|
|
// Common
|
|
_MainTex ("Main Texture", 2D) = "white" {}
|
|
_BaseColor("Base Color", Color) = (1,1,1,1)
|
|
[Enum(Water,0,Lava,1,Ice,2,River,3)] _SurfaceType ("Surface Type", Float) = 0
|
|
|
|
// Water
|
|
_WaterTint ("Water Tint", Color) = (0.1, 0.55, 0.7, 1.0)
|
|
_DepthStrength ("Depth Strength", Range(0,1)) = 0.6
|
|
|
|
_WaveAmplitude ("Wave Amplitude", Float) = 0.12
|
|
_WaveLength ("Wave Length", Float) = 12.0
|
|
_WaveSpeed ("Wave Speed", Float) = 1.0
|
|
_WaveDirection ("Wave Direction X,Y", Vector) = (1, 0.2, 0, 0)
|
|
|
|
[Normal]_NormalMap ("Normal Map", 2D) = "bump" {}
|
|
_NormalStrength ("Normal Strength", Range(0,1)) = 0.6
|
|
_SurfaceDetail ("Surface Detail", Range(0,1)) = 0.4
|
|
|
|
_RefractionStrength ("Refraction Strength", Range(0,0.05)) = 0.015
|
|
_FresnelStrength ("Fresnel Strength", Range(0,1)) = 0.2
|
|
|
|
_FoamTex ("Foam Texture", 2D) = "white" {}
|
|
_FoamStrength ("Foam Strength", Range(0,2)) = 0.6
|
|
_FoamBias ("Foam Bias", Range(-1,1)) = 0.0
|
|
|
|
// UV scroll speeds
|
|
_WaterNormal1Speed ("Normal Map 1 Speed (X,Y)", Vector) = (0.05, 0.0, 0, 0)
|
|
_WaterNormal2Speed ("Normal Map 2 Speed (X,Y)", Vector) = (0.0, -0.03, 0, 0)
|
|
_FoamScrollSpeed ("Foam Scroll Speed (X,Y)", Vector) = (0.02, 0.01, 0, 0)
|
|
|
|
// Shoreline & absorption
|
|
_ShorelineStrength ("Shoreline Foam Strength", Range(0,2)) = 1.0
|
|
_ShorelineSharpness ("Shoreline Sharpness", Range(0.5, 12)) = 6.0
|
|
_AbsorptionStrength ("Depth Absorption Strength", Range(0,1)) = 0.6
|
|
|
|
// Lava
|
|
_EmissionColor ("Emission Color", Color) = (1,0.4,0,1)
|
|
_VoronoiScale ("Voronoi Scale", Float) = 5.0
|
|
_VoronoiThreshold ("Voronoi Threshold", Range(0,1)) = 0.3
|
|
_LavaCrackGlow ("Lava Crack Glow Strength", Float) = 0.8
|
|
_LavaEdgeGlow ("Lava Edge Glow Strength", Float) = 0.5
|
|
|
|
// Procedural bubbles - coś nie bangla
|
|
_BubbleDensity ("Bubble Density", Float) = 8.0
|
|
_BubbleFlow ("Bubble Flow Speed", Float) = 0.5
|
|
_BubbleStrength ("Bubble Strength", Float) = 1.5
|
|
_BubbleFade ("Bubble Fade Sharpness", Float) = 2.0
|
|
|
|
// Vertex distortion
|
|
_VertexDistortStrength ("Vertex Distortion Strength", Float) = 0.0
|
|
_VertexDistortSpeed ("Vertex Distortion Speed", Float) = 1.5
|
|
}
|
|
|
|
SubShader
|
|
{
|
|
Tags { "RenderPipeline"="UniversalRenderPipeline" "RenderType"="Transparent" "Queue"="Transparent" }
|
|
LOD 250
|
|
|
|
Pass
|
|
{
|
|
Name "UniversalForward"
|
|
Tags { "LightMode"="UniversalForward" }
|
|
|
|
Blend SrcAlpha OneMinusSrcAlpha
|
|
ZWrite Off
|
|
|
|
HLSLPROGRAM
|
|
#pragma vertex vert
|
|
#pragma fragment frag
|
|
|
|
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
|
|
|
|
#ifndef UNITY_PI
|
|
#define UNITY_PI 3.14159265359
|
|
#endif
|
|
|
|
struct Attributes {
|
|
float4 positionOS : POSITION;
|
|
float2 uv : TEXCOORD0;
|
|
float3 normalOS : NORMAL;
|
|
};
|
|
struct Varyings {
|
|
float4 positionHCS : SV_POSITION;
|
|
float2 uv : TEXCOORD0;
|
|
float3 worldPos : TEXCOORD1;
|
|
float3 normalWS : TEXCOORD2;
|
|
float3 viewDirWS : TEXCOORD3;
|
|
float4 screenPos : TEXCOORD4;
|
|
};
|
|
|
|
// Textures
|
|
TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex);
|
|
TEXTURE2D(_NormalMap); SAMPLER(sampler_NormalMap);
|
|
TEXTURE2D(_FoamTex); SAMPLER(sampler_FoamTex);
|
|
TEXTURE2D(_CameraDepthTexture); SAMPLER(sampler_CameraDepthTexture);
|
|
TEXTURE2D(_CameraColorTexture); SAMPLER(sampler_CameraColorTexture);
|
|
|
|
// ST
|
|
float4 _MainTex_ST;
|
|
float4 _NormalMap_ST;
|
|
float4 _FoamTex_ST;
|
|
|
|
// Parameters
|
|
float4 _BaseColor;
|
|
float _SurfaceType;
|
|
|
|
float4 _WaterTint;
|
|
float _DepthStrength;
|
|
|
|
float _WaveAmplitude;
|
|
float _WaveLength;
|
|
float _WaveSpeed;
|
|
float4 _WaveDirection;
|
|
|
|
float _NormalStrength;
|
|
float _SurfaceDetail;
|
|
|
|
float _RefractionStrength;
|
|
float _FresnelStrength;
|
|
float _FoamStrength;
|
|
float _FoamBias;
|
|
|
|
float4 _WaterNormal1Speed;
|
|
float4 _WaterNormal2Speed;
|
|
float4 _FoamScrollSpeed;
|
|
|
|
float _ShorelineStrength;
|
|
float _ShorelineSharpness;
|
|
float _AbsorptionStrength;
|
|
|
|
float4 _EmissionColor;
|
|
float _VoronoiScale;
|
|
float _VoronoiThreshold;
|
|
float _LavaCrackGlow;
|
|
float _LavaEdgeGlow;
|
|
float _BubbleDensity;
|
|
float _BubbleFlow;
|
|
float _BubbleStrength;
|
|
float _BubbleFade;
|
|
|
|
float _VertexDistortStrength;
|
|
float _VertexDistortSpeed;
|
|
|
|
float2 ApplyST(float2 uv, float4 st) { return uv * st.xy + st.zw; }
|
|
|
|
// Voronoi edge noise
|
|
float voronoiEdge(float2 uv)
|
|
{
|
|
float2 g = floor(uv), f = frac(uv);
|
|
float d1=1.0, d2=1.0;
|
|
[unroll] for(int y=-1;y<=1;y++)
|
|
[unroll] for(int x=-1;x<=1;x++)
|
|
{
|
|
float2 o=float2(x,y);
|
|
float2 h=frac(sin(dot(g+o,float2(127.1,311.7))) * 43758.5453);
|
|
float2 r=o+h-f; float d=dot(r,r);
|
|
if(d<d1){d2=d1; d1=d;} else if(d<d2){d2=d;}
|
|
}
|
|
return d2-d1;
|
|
}
|
|
|
|
// Gerstner, śmieszna nazwa
|
|
void GerstnerSimple(float2 dir, float amp, float len, float spd, float2 xz, float t, out float3 disp, out float3 nContrib)
|
|
{
|
|
float2 D = normalize(dir);
|
|
float k = (2.0 * UNITY_PI) / max(len, 0.0001);
|
|
float w = sqrt(9.81 * k);
|
|
float ph = k * dot(D, xz) + (spd > 0 ? spd : w) * t;
|
|
|
|
float steep = 0.5;
|
|
float Q = steep * amp * k;
|
|
|
|
float c = cos(ph);
|
|
float s = sin(ph);
|
|
|
|
disp.x = D.x * (Q * amp * c);
|
|
disp.z = D.y * (Q * amp * c);
|
|
disp.y = amp * s;
|
|
|
|
float3 n;
|
|
n.x = -D.x * Q * s;
|
|
n.z = -D.y * Q * s;
|
|
n.y = 1.0 - Q * c;
|
|
nContrib = n;
|
|
}
|
|
|
|
void GenerateWaves(float2 baseDir, float amp, float len, float spd, float2 xz, float t, out float3 disp, out float3 nSum)
|
|
{
|
|
float angle = 0.35;
|
|
float2 d0 = baseDir;
|
|
float2 d1 = float2(baseDir.x * cos(angle) - baseDir.y * sin(angle),
|
|
baseDir.x * sin(angle) + baseDir.y * cos(angle));
|
|
float2 d2 = -baseDir.yx;
|
|
|
|
float3 dd0, nn0; GerstnerSimple(d0, amp, len, spd, xz, t, dd0, nn0);
|
|
float3 dd1, nn1; GerstnerSimple(d1, amp * 0.6, len * 0.7, spd * 1.2, xz, t, dd1, nn1);
|
|
float3 dd2, nn2; GerstnerSimple(d2, amp * 0.4, len * 0.5, spd * 0.8, xz, t, dd2, nn2);
|
|
|
|
disp = dd0 + dd1 + dd2;
|
|
nSum = normalize(nn0 + nn1 + nn2);
|
|
}
|
|
|
|
Varyings vert(Attributes IN)
|
|
{
|
|
// Global vertex distortion
|
|
if(_VertexDistortStrength > 1e-4)
|
|
{
|
|
float w1 = sin(IN.positionOS.x*2 + _Time.y*_VertexDistortSpeed) *
|
|
cos(IN.positionOS.z*2 + _Time.y*_VertexDistortSpeed*1.3);
|
|
float w2 = sin(IN.positionOS.x*3.5 + _Time.y*(_VertexDistortSpeed*1.7)) *
|
|
sin(IN.positionOS.z*2.8 + _Time.y*(_VertexDistortSpeed*2.1));
|
|
float boil = sin(_Time.y*(_VertexDistortSpeed*0.8))*0.2;
|
|
IN.positionOS.y += (w1*0.6 + w2*0.4 + boil) * _VertexDistortStrength;
|
|
}
|
|
|
|
float3 wpos = TransformObjectToWorld(IN.positionOS.xyz);
|
|
float3 nWS = TransformObjectToWorldNormal(IN.normalOS);
|
|
|
|
if (_SurfaceType == 0)
|
|
{
|
|
float2 baseDir = normalize(_WaveDirection.xy);
|
|
float3 d, nC;
|
|
GenerateWaves(baseDir, _WaveAmplitude, _WaveLength, _WaveSpeed, wpos.xz, _Time.y, d, nC);
|
|
wpos += d;
|
|
nWS = normalize(nC);
|
|
}
|
|
|
|
Varyings OUT;
|
|
OUT.worldPos = wpos;
|
|
OUT.positionHCS = TransformWorldToHClip(wpos);
|
|
OUT.uv = IN.uv;
|
|
OUT.normalWS = nWS;
|
|
OUT.viewDirWS = GetWorldSpaceViewDir(wpos);
|
|
OUT.screenPos = ComputeScreenPos(OUT.positionHCS);
|
|
return OUT;
|
|
}
|
|
|
|
half4 frag(Varyings IN):SV_Target
|
|
{
|
|
half3 finalColor=0, emission=0;
|
|
float3 N = normalize(IN.normalWS);
|
|
float3 V = normalize(IN.viewDirWS);
|
|
float2 screenUV = IN.screenPos.xy / IN.screenPos.w;
|
|
|
|
if (_SurfaceType == 0) // WATER
|
|
{
|
|
float rawD = SAMPLE_TEXTURE2D(_CameraDepthTexture, sampler_CameraDepthTexture, screenUV).r;
|
|
float sceneD = LinearEyeDepth(rawD, _ZBufferParams);
|
|
float fragD = IN.positionHCS.w;
|
|
float diff = max(sceneD - fragD, 0.0);
|
|
|
|
float darkK = lerp(0.08, 0.22, _DepthStrength);
|
|
float depthC = saturate(diff * darkK);
|
|
float3 tint = _WaterTint.rgb;
|
|
float3 deep = tint * float3(0.35, 0.5, 0.7);
|
|
float3 waterCol = lerp(tint, deep, depthC);
|
|
|
|
// Normal maps with controllable scroll
|
|
float2 uvA = ApplyST(IN.uv, _NormalMap_ST) + _WaterNormal1Speed.xy * _Time.y;
|
|
float2 uvB = ApplyST(IN.uv, _NormalMap_ST) + _WaterNormal2Speed.xy * _Time.y;
|
|
float3 nA = UnpackNormal(SAMPLE_TEXTURE2D(_NormalMap, sampler_NormalMap, uvA));
|
|
float3 nB = UnpackNormal(SAMPLE_TEXTURE2D(_NormalMap, sampler_NormalMap, uvB));
|
|
float3 wn = normalize(lerp(nA, nB, _SurfaceDetail));
|
|
wn = normalize(float3(wn.xy * _NormalStrength, wn.z));
|
|
|
|
float2 refUV = screenUV + wn.xy * _RefractionStrength;
|
|
half3 back = SAMPLE_TEXTURE2D(_CameraColorTexture, sampler_CameraColorTexture, refUV).rgb;
|
|
|
|
float fresnel = pow(1.0 - saturate(dot(V, wn)), 3.0) * _FresnelStrength;
|
|
|
|
// Foam with controllable scroll
|
|
float2 foamUV = ApplyST(IN.uv, _FoamTex_ST) + _FoamScrollSpeed.xy * _Time.y;
|
|
float foamTexV = SAMPLE_TEXTURE2D(_FoamTex, sampler_FoamTex, foamUV * 2.0).r;
|
|
float slopeFoam= saturate((1.0 - N.y) + _FoamBias);
|
|
float foamSurf = saturate(slopeFoam * foamTexV) * _FoamStrength;
|
|
|
|
float shoreMask = saturate(1.0 - diff * _ShorelineSharpness);
|
|
float shoreFoam = shoreMask * foamTexV * _ShorelineStrength;
|
|
|
|
float absorb = saturate(diff * _AbsorptionStrength);
|
|
float backMix = lerp(0.30, 0.10, absorb);
|
|
float outAlpha = saturate(lerp(0.85, 0.45, absorb) + (foamSurf + shoreFoam) * 0.1);
|
|
|
|
half3 baseTex = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, ApplyST(IN.uv,_MainTex_ST)).rgb * _BaseColor.rgb;
|
|
|
|
finalColor = lerp(waterCol, back, backMix);
|
|
finalColor = lerp(finalColor, baseTex, 0.08);
|
|
|
|
emission += foamSurf * float3(1,1,1);
|
|
emission += shoreFoam * float3(1,1,1);
|
|
emission += fresnel;
|
|
|
|
return half4(finalColor + emission, outAlpha);
|
|
}
|
|
else if (_SurfaceType == 1) // LAVA
|
|
{
|
|
float2 uvAnim = IN.uv * _VoronoiScale;
|
|
float edge = voronoiEdge(uvAnim);
|
|
float cracks = smoothstep(_VoronoiThreshold, _VoronoiThreshold + 0.02, edge);
|
|
|
|
half3 rockTex = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, ApplyST(IN.uv, _MainTex_ST)).rgb;
|
|
half3 rockColor = pow(rockTex * _BaseColor.rgb, 1.3);
|
|
|
|
half3 lavaHot = float3(1.0, 0.35, 0.05);
|
|
half3 lavaCore = float3(1.0, 0.6, 0.2);
|
|
float boilPulse = 0.5 + 0.5 * sin(_Time.y * 4.0 + uvAnim.x * 3.0 + uvAnim.y * 5.0);
|
|
half3 lavaColor = lerp(lavaHot, lavaCore, boilPulse);
|
|
|
|
finalColor = lerp(lavaColor, rockColor, cracks);
|
|
emission = lavaColor * (1.0 - cracks) * _EmissionColor.rgb * _LavaCrackGlow;
|
|
|
|
float2 uvBubbles = IN.uv * _BubbleDensity + float2(0, _Time.y * _BubbleFlow);
|
|
float bubbleMask = smoothstep(0.2, 0.2 + 0.05 * _BubbleFade, voronoiEdge(uvBubbles));
|
|
emission += bubbleMask * _BubbleStrength * (1.0 - cracks) * _EmissionColor.rgb;
|
|
|
|
float fres = pow(1.0 - saturate(dot(N, V)), 3.0);
|
|
emission += lavaColor * fres * _LavaEdgeGlow * _EmissionColor.rgb;
|
|
|
|
return half4(finalColor + emission, 1.0);
|
|
}
|
|
else if (_SurfaceType == 2) // ICE
|
|
{
|
|
half3 iceTex = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, ApplyST(IN.uv, _MainTex_ST)).rgb;
|
|
finalColor = iceTex * _BaseColor.rgb;
|
|
|
|
float fres = pow(1.0 - saturate(dot(N, V)), 4.0);
|
|
emission = fres * float3(0.6, 0.85, 1.0) * 0.6;
|
|
return half4(finalColor + emission, 1.0);
|
|
}
|
|
else if (_SurfaceType == 3) // RIVER
|
|
{
|
|
float2 uvFlow = ApplyST(IN.uv, _MainTex_ST);
|
|
uvFlow.y += _Time.y * 0.2;
|
|
|
|
half3 riverTex = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uvFlow).rgb * _BaseColor.rgb;
|
|
|
|
float2 foamUV = ApplyST(IN.uv, _FoamTex_ST) + _FoamScrollSpeed.xy * _Time.y;
|
|
float foam = SAMPLE_TEXTURE2D(_FoamTex, sampler_FoamTex, foamUV * 2.0).r;
|
|
|
|
emission = foam * _FoamStrength * riverTex;
|
|
finalColor = riverTex;
|
|
|
|
return half4(finalColor + emission, 1.0);
|
|
}
|
|
|
|
return half4(finalColor + emission, 1.0);
|
|
}
|
|
ENDHLSL
|
|
}
|
|
}
|
|
|
|
CustomEditor "LiquidSurfaceShaderGUI_Simplified"
|
|
}
|