Files
jelito/Assets/Jbl_Shaders/Jbl_UniversalShader.shader
2025-10-08 20:28:22 +02:00

358 lines
15 KiB
GLSL

Shader "Custom/UniversalLiquidSurface_Simplified"
{
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
// NEW: 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
_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;
// Params
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
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"
}