Shader "IndianOcean/WaterReflection" { // 水面倒影 Shader // 上方 (1-R) 正常显示原图,下方 R 区域为原图整体垂直翻转 + 扰动 + 淡出, // 分界线处绘制一条水面亮线。 Properties { _MainTex ("主贴图", 2D) = "white" {} _Waterline ("水面线位置(UV.y)", Range(0.05, 0.95)) = 0.7 _DistortStrength("水平扰动强度", Range(0, 0.08)) = 0.015 _DistortSpeed ("扰动速度", Range(0, 5)) = 1.5 _DistortFreq ("扰动频率", Range(1, 20)) = 8.0 _ReflDarken ("倒影变暗系数", Range(0, 1)) = 0.5 _ReflFadeLen ("倒影向下淡出长度", Range(0, 0.5)) = 0.25 _LineBrightness ("水面线亮度", Range(0, 3)) = 1.5 _LineThickness ("水面线粗细", Range(0, 0.02)) = 0.004 _WaveAmplitude ("水面线波浪振幅", Range(0, 0.05)) = 0.012 _WaveFreq ("水面线波浪频率", Range(1, 15)) = 4.0 _WaveSpeed ("水面线波浪速度", Range(0, 5)) = 1.0 } SubShader { Tags { "RenderType" = "Transparent" "Queue" = "Transparent" "RenderPipeline" = "UniversalPipeline" "IgnoreProjector" = "True" "CanUseSpriteAtlas" = "True" } Blend SrcAlpha OneMinusSrcAlpha ZWrite Off Cull Off Pass { Name "WaterReflection" HLSLPROGRAM #pragma vertex vert #pragma fragment frag #pragma multi_compile_instancing #pragma multi_compile __ UNITY_UI_CLIP_RECT #pragma multi_compile __ UNITY_UI_ALPHACLIP #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" struct Attributes { float4 positionOS : POSITION; float2 uv : TEXCOORD0; float4 color : COLOR; UNITY_VERTEX_INPUT_INSTANCE_ID }; struct Varyings { float4 positionCS : SV_POSITION; float2 uv : TEXCOORD0; float4 color : COLOR; UNITY_VERTEX_INPUT_INSTANCE_ID }; CBUFFER_START(UnityPerMaterial) float4 _MainTex_ST; float _Waterline; float _DistortStrength; float _DistortSpeed; float _DistortFreq; float _ReflDarken; float _ReflFadeLen; float _LineBrightness; float _LineThickness; float _WaveAmplitude; float _WaveFreq; float _WaveSpeed; CBUFFER_END // UI ClipRect float4 _ClipRect; TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex); /* ---------- noise ---------- */ float hash(float n) { return frac(sin(n) * 43758.5453); } float noise1D(float x) { float i = floor(x); float f = frac(x); f = f * f * (3.0 - 2.0 * f); return lerp(hash(i), hash(i + 1.0), f); } // 多层叠加 → 类随机水面波纹,返回 [-1, 1] float waterNoise(float x, float t) { float n = 0.0; n += noise1D(x * _DistortFreq + t * _DistortSpeed) * 0.50; n += noise1D(x * _DistortFreq * 2.3 - t * _DistortSpeed * 1.7) * 0.25; n += noise1D(x * _DistortFreq * 4.7 + t * _DistortSpeed * 0.8) * 0.125; return n * 2.0 - 1.0; } // 计算某 uv.x 处的局部水面线 Y 坐标(波浪起伏) // 多层正弦叠加 + noise,产生自然的不规则波形 float localWaterline(float x, float t) { float wave = 0.0; wave += sin(x * _WaveFreq * 6.2832 + t * _WaveSpeed) * 0.50; wave += sin(x * _WaveFreq * 6.2832 * 2.3 - t * _WaveSpeed * 1.4) * 0.25; wave += sin(x * _WaveFreq * 6.2832 * 4.1 + t * _WaveSpeed * 0.7) * 0.15; wave += noise1D(x * _WaveFreq * 3.0 + t * _WaveSpeed * 0.5) * 0.10; return _Waterline + wave * _WaveAmplitude; } Varyings vert(Attributes input) { Varyings output; UNITY_SETUP_INSTANCE_ID(input); UNITY_TRANSFER_INSTANCE_ID(input, output); output.positionCS = TransformObjectToHClip(input.positionOS.xyz); output.uv = TRANSFORM_TEX(input.uv, _MainTex); output.color = input.color; return output; } half4 frag(Varyings input) : SV_Target { float2 uv = input.uv; float time = _Time.y; // ========== 1. 原图采样(上方区域直接使用) ========== half4 baseColor = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv); // ========== 2. 局部水面线(波浪起伏) ========== float wl = localWaterline(uv.x, time); // ========== 3. 判断是否在倒影区 ========== float inRefl = 1.0 - step(wl, uv.y); // ========== 4. 倒影 UV:整体垂直翻转 ========== float2 reflUV = uv; reflUV.y = 2.0 * wl - uv.y; // 以局部水面线为轴镜像 // 水平扰动 float distort = waterNoise(uv.x, time) * _DistortStrength; // 越远离水面线(越往下)扰动越大 float depthRatio = 1.0 - uv.y / wl; // 0=水面, 1=最底 depthRatio = clamp(depthRatio, 0.0, 1.0); distort *= (0.3 + 0.7 * depthRatio); reflUV.x += distort; // 夹紧,防止越界 reflUV = clamp(reflUV, 0.0, 1.0); half4 reflColor = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, reflUV); // ========== 5. 倒影衰减 ========== // 5a. 整体变暗 reflColor.rgb *= (1.0 - _ReflDarken); // 5b. 从水面线往下逐渐淡出(消散) float fadeStart = wl - _ReflFadeLen; float fadeFactor = smoothstep(fadeStart, wl, uv.y); reflColor.a *= fadeFactor; // ========== 6. 水面亮线(沿波浪曲线绘制) ========== float distToLine = abs(uv.y - wl); float lineFactor = 1.0 - smoothstep(0.0, _LineThickness, distToLine); // ========== 7. 合成 ========== half3 finalRGB = baseColor.rgb; // 倒影区:用倒影色替换 finalRGB = lerp(finalRGB, reflColor.rgb, inRefl); // 水面线:叠加高亮 finalRGB += lineFactor * _LineBrightness * half3(0.7, 0.85, 1.0); float finalA = baseColor.a; // 倒影区 alpha 也跟随淡出 finalA = lerp(finalA, reflColor.a, inRefl); half4 finalColor = half4(finalRGB, finalA); finalColor *= input.color; // UI 裁剪矩形裁剪 #ifdef UNITY_UI_CLIP_RECT float2 clipPos = input.positionCS.xy; float clip = 1.0; clip *= step(0.0, clipPos.x - _ClipRect.x); clip *= step(0.0, clipPos.y - _ClipRect.y); clip *= step(clipPos.x, _ClipRect.z); clip *= step(clipPos.y, _ClipRect.w); finalColor.a *= clip; #endif #ifdef UNITY_UI_ALPHACLIP clip(finalColor.a - 0.001); #endif return finalColor; } ENDHLSL } } FallBack Off }