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 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" }