
1. 項目概述從“調參”到“造浪”的思維躍遷每次看到《絕地求生》里那片隨著時間緩緩起伏、波光粼粼的海面你是不是也和我一樣第一反應是去網上找個現成的Shader然后一頭扎進材質面板里對著十幾個滑塊瘋狂調試試圖“蒙”出那個感覺我曾經也這么干過結果往往是調了半天水面要么像果凍一樣僵硬要么像沸騰的開水一樣詭異離“以假亂真”差了十萬八千里。后來我意識到問題不在于參數本身而在于我們根本不知道這些參數背后連接的是什么它們如何相互作用最終驅動了那片虛擬的海洋。這就是今天我想和你聊的核心別再只會當個“參數調試員”了。我們要用Unity的ShaderGraph從最底層的原理出發親手“搭建”出那片海。這個過程本質上是在用節點“編程”水的行為邏輯。我將為你拆解實現“吃雞”級海面效果的五個最關鍵的ShaderGraph節點它們就像搭建樂高積木的五個核心零件。掌握了它們你不僅能復刻出這個效果更能舉一反三創造出任何你想象中的水面——無論是寧靜的湖泊、湍急的河流還是風暴中的怒濤。這篇文章適合所有對Shader感興趣但又被代碼嚇退的Unity開發者我們將完全在可視化界面中完成這場造浪之旅。2. 核心思路拆解如何用節點“模擬”一片海在動手連接節點之前我們必須先想清楚一片看起來“真實”的海面在Shader里究竟是由哪些視覺元素構成的。這決定了我們整個節點網絡的架構方向。2.1 視覺元素分解海面不止是藍色首先我們得拋棄“一個顏色貼圖走天下”的簡單思維。一片生動的海面是多種視覺信息疊加的結果基礎顏色與深度近處的海水清澈透亮顏色較淺遠處的海水深邃呈現出更濃郁的藍色甚至墨綠色。這不僅僅是顏色變化還包含了光線在水體中散射和吸收的物理現象。波浪起伏頂點動畫海面不是平的它由無數大小、方向、速度各異的波浪疊加而成。這是讓海面“活”起來的第一步需要通過動態地改變模型頂點的位置來實現。表面細節法線即使是一個平滑的波浪曲面在微觀上也是粗糙不平的有細碎的波紋、漣漪和泡沫。這些細節決定了光線如何反射是產生“波光粼粼”質感的關鍵通常由法線貼圖來表現。高光與反射陽光或月光照射在海面上會形成明亮的高光點Specular和周圍環境的反射Reflection。高光的形狀、強度和銳利度直接傳達了海面的“粗糙度”或“風速”信息。菲涅爾效應這是一個關鍵的物理現象——視線與表面法線夾角越小即掠射角觀察水面反射越強夾角越大垂直向下看越容易看到水下的折射內容。這解釋了為什么我們總是看到海天交界處有一條亮線而腳邊的海水則相對透明。2.2 節點化實現路徑基于以上分解我們的ShaderGraph構建路徑就清晰了頂點動畫層使用Time和Position節點驅動數學運算生成波浪的位移信息。表面細節層使用Texture 2D Asset和Tiling Offset節點采樣并動態滾動法線貼圖模擬細碎波紋。視覺融合層使用Normal Blend等節點將多層細節如基礎波浪和細節漣漪平滑地混合在一起。光學響應層使用Fresnel Effect節點和PBR Master節點的輸入如Smoothness來模擬海面對光線的復雜反應。整個思路就是從“驅動頂點運動”開始逐步疊加“表面細節”最后賦予其“正確的光學屬性”。下面我們就深入這五個決定成敗的關鍵節點。3. 五大關鍵節點深度解析與實戰連接這五個節點是構建海面Shader的骨架理解它們每一個的作用和連接邏輯比記住一百個參數組合更有用。3.1 發動機Time節點——讓一切動起來為什么是它靜態的海面是死海。所有動態效果——波浪的起伏、波紋的流動、光斑的移動——都依賴于一個持續變化的時間信號。Time節點就是ShaderGraph里的時鐘它輸出一個隨著游戲時間不斷增大的浮點數默認是自場景加載以來的秒數。關鍵操作與原理僅僅輸出時間值還不夠我們需要用它來驅動周期性的運動比如正弦波。這里就會引入一個經典組合Time-Multiply乘以一個控制速度的系數-Sine正弦函數。Multiply的作用乘以一個系數比如0.5本質是控制頻率。系數越大正弦波振蕩越快波浪就顯得更“急促”或“細密”。Sine的作用將線性增長的時間轉換為在[-1, 1]之間平滑、周期性振蕩的值。這個振蕩值可以直接用來偏移頂點的Y坐標形成基礎的波浪形狀。實操心得直接使用Time節點的輸出變化會非常快。我通常會先連接一個Multiply節點乘以一個0.1到1之間的小數例如0.3得到一個“慢速時間”再用這個慢速時間去驅動主要波浪這樣動畫會更自然易于控制。對于需要不同速度的次級波紋則可以使用另一個乘以不同系數如0.7的“快速時間”分支。3.2 空間坐標讀取器Position節點——知道“我在哪”為什么是它波浪不可能在所有位置都一樣高。我們需要根據頂點在世界空間或物體空間中的水平位置X和Z坐標來計算其應有的高度Y坐標偏移。Position節點提供了頂點的位置信息。關鍵操作與原理默認的Position節點輸出是一個三維向量 (X, Y, Z)。對于海面我們通常關心的是水平面即X和Z分量。拆分與重組使用Split節點將Position的XYZ分開取出X和Z。然后我們可能會用經過Time驅動的數學函數如Sine去處理X和Z得到兩個方向的偏移量再用Combine節點將新的Y值原始Y偏移量與X、Z重新組合成一個新的三維向量??臻g選擇Position節點有World、Object、View等空間選項。對于海面這種可能移動的物體比如一艘船上的海面使用Object空間位置來計算波浪可以保證波浪形狀跟隨物體移動更合理。如果是無限大的遠景海面使用World空間則更簡單。一個基礎波浪的節點鏈示例Position (Object Space) - Split - (取出X) \ Time - Multiply(Speed) - Add - Sine - Multiply(Amplitude) - Combine (作為新的Y) / Position (Object Space) - Split - (取出Z) - Multiply(WaveDirection) - Add這個流程的意思是用Time經過速度縮放后加上由位置X和Z按一定方向混合的值作為正弦函數的輸入從而得到一個隨時間和空間位置變化的波浪高度。3.3 紋理動畫控制器Tiling And Offset節點——制造流動的細節為什么是它單靠頂點動畫生成的波浪往往過于規則和光滑缺乏真實海面那種復雜的、多尺度的細節。這時就需要法線貼圖。但一張靜態的法線貼圖貼上去還是死的我們需要讓貼圖上的波紋“流動”起來模擬風驅動力作用下水面的運動。Tiling And Offset節點的Offset輸入端口正是實現紋理滾動的關鍵。關鍵操作與原理這個節點有兩個主要輸入Tiling縮放和Offset偏移。Tiling控制紋理的重復度。值越大同一區域內重復的紋理次數越多意味著波紋越細密。對于海面我們可能需要兩層不同尺度的法線貼圖一層Tiling較大模擬大的波浪走向一層Tiling很大模擬細碎的漣漪。Offset這是一個二維向量輸入代表紋理在UV空間內的偏移量。核心技巧來了我們將一個由Time驅動的二維向量例如(Time * Speed, 0)連接到Offset紋理就會沿著U方向水平持續滾動。如果向量是(Time * Speed1, Time * Speed2)紋理就會沿對角線方向滾動。實現雙層流動細節為了打破單調性幾乎所有的海面Shader都會使用至少兩層法線貼圖。第一層主波紋使用一張方向性較強的法線貼圖Tiling較小如0.05Offset速度較慢模擬主要波浪的走向和光影。第二層細節漣漪使用另一張或同一張法線貼圖Tiling較大如0.15Offset速度較快且方向與第一層略有不同例如一個向左一個向右上。這能疊加出非常豐富的細節避免出現明顯的重復圖案。3.4 細節混合器Normal Strength 與 Normal Blend節點——合成真實質感為什么是它們當我們有了兩層或更多滾動的法線貼圖后不能簡單地把它們疊加在一起那樣會導致信息混亂。我們需要有控制地混合它們。Normal Strength節點這個節點經常被忽略但它至關重要。它允許我們在混合前單獨調整某一張法線貼圖的“強度”或“影響力”。輸入一個法線向量來自Sample Texture 2D一個強度系數Float。作用當強度系數為1時輸出原法線大于1時增強法線細節使凹凸感更強在0到1之間時減弱細節為0時相當于一個平坦的藍色法線(0,0,1)。實戰應用我們可以為“主波紋”和“細節漣漪”分別設置不同的Normal Strength。比如讓主波紋強度為0.8細節漣漪強度為0.4。這樣細節層就不會喧賓奪主而是在主波紋的基礎上增加一些微妙的擾動。Normal Blend節點這是將多張法線貼圖安全、正確混合的標準節點。它采用一種特殊的算法能避免直接加法混合導致的向量長度變化即法線信息失真。操作它有兩個輸入口Base基礎法線和Blend混合法線。我們將調整好強度的主波紋法線連入Base將細節漣漪法線連入Blend。輸出就是一個融合了兩者信息的、新的法線向量。進階技巧你可以進行多次混合。例如Normal Blend的輸出可以作為新的Base再與第三層泡沫或特殊效果的法線進行第二次Normal Blend。避坑指南千萬不要用普通的Add或Lerp節點去混合法線法線是歸一化向量長度為1直接相加會破壞其長度導致光照計算錯誤出現奇怪的黑斑或過度明亮區域。Normal Blend節點是為此場景量身定做的。3.5 光學特性塑造器Fresnel Effect節點——模擬水岸交界為什么是它這是實現“海水為什么越遠越亮越近越透”這一視覺特性的物理鑰匙。菲涅爾效應描述了反射率隨觀察角度變化的規律。關鍵操作與原理在ShaderGraph中Fresnel Effect節點根據表面法線Normal和觀察方向View Direction計算出一個漸變系數。這個系數在視線與表面平行時掠射角接近1在垂直時接近0。連接將我們混合好的最終法線向量連接到Normal輸入口View Direction通常使用默認的攝像機視圖方向。輸出應用這個0到1之間的系數有兩個最主要的用途控制顏色混合創建一個Lerp線性插值節點。將深水顏色連到A淺水或高光顏色連到B將Fresnel的輸出連到T。這樣在視線掠射的海平面遠處將顯示更多的B亮色在垂直視角的近處顯示更多的A深色??刂品瓷?高光強度可以將Fresnel輸出連接到PBR Master節點的Smoothness或Environment Reflections的強度上讓邊緣的反射更強。參數調整 節點上的Power參數控制著菲涅爾效應的過渡銳利度。Power值越小過渡越平緩、范圍越大值越大過渡越尖銳亮暗分界線越明顯。對于海面一個中等偏大的Power值如3-5可以模擬出比較清晰的水天線效果。4. 完整節點網絡搭建與參數調試實錄理解了核心節點后讓我們把它們像拼圖一樣組裝起來并看看每個旋鈕該怎么調。4.1 節點網絡架構圖文字描述版由于無法使用圖表我用層級結構描述整個網絡的數據流時間與空間輸入層Time節點輸出經過兩個不同的Multiply節點生成SlowTime系數~0.3和FastTime系數~0.7。Position節點Object Space提供頂點原始坐標。頂點位移生成層使用SlowTime和Position的XZ分量通過一系列Add、Multiply、Sine運算生成一個低頻、大振幅的波浪高度偏移量WaveOffsetA。用同樣的邏輯但使用不同的方向和頻率參數生成另一個波浪高度偏移量WaveOffsetB。將WaveOffsetA和WaveOffsetB用Add節點相加得到總的頂點Y軸偏移。再與原始的X、Z通過Combine節點組合輸出到PBR Master的Vertex Position端口。法線細節生成層主波紋法線Texture 2D Asset法線貼圖 -Sample Texture 2D。其UV輸入來自UV節點 -Tiling And OffsetTiling0.05, Offset(SlowTime*0.1, 0)-Normal StrengthStrength0.8。細節漣漪法線同一張或另一張Texture 2D Asset-Sample Texture 2D。其UV輸入來自UV節點 -Tiling And OffsetTiling0.15, Offset(FastTime0.2, FastTime0.1)-Normal StrengthStrength0.4。法線混合Normal Blend節點將主波紋法線連入Base細節漣漪法線連入Blend。輸出為Final Normal。顏色與光學計算層Fresnel Effect節點輸入Final Normal和默認View DirectionPower設為4。Color節點創建深藍色DeepColor如#006994FF和淺藍綠色ShallowColor如#00FFE5FF。Lerp節點A連DeepColorB連ShallowColorT連Fresnel Effect輸出。結果輸出到PBR Master的Albedo。Final Normal輸出到PBR Master的Normal。一個Vector1節點設為公開參數Smoothness默認值0.9輸出到PBR Master的Smoothness。你也可以用Fresnel輸出來進一步調制Smoothness增加邊緣反射。4.2 關鍵參數調試心法參數沒有絕對的正確值只有適合你場景的“感覺”。以下是調試順序和邏輯先調“形”再調“色”首先關閉顏色和法線貼圖只保留頂點動畫。調整波浪的Speed頻率和Amplitude振幅直到得到一個你覺得自然的基礎起伏節奏。太大像海嘯太小像水塘。法線貼圖強度打開法線貼圖先將Normal Strength都設為0然后慢慢調高。主波紋的強度如0.5-0.8決定了波浪的“形體感”細節漣漪的強度如0.2-0.4決定了表面的“粗糙度”。兩者強度差不宜過小否則層次不清。Tiling與Offset速度Tiling決定波紋的尺度。遠景海面主波紋Tiling要小如0.02-0.05近景或特寫可以大一些。Offset的速度要與頂點動畫的Speed相匹配。通常紋理滾動的視覺速度應略慢于或等于頂點起伏的速度否則會產生“滑移”的失真感。菲涅爾與顏色調整Fresnel的Power改變深水區與淺水區亮部的過渡范圍。然后調整Lerp兩端的顏色。DeepColor影響海水主體的顏色ShallowColor影響邊緣高光和水面反光的色調。晴天用明亮的藍綠色陰天用灰藍色。光滑度與金屬度海水的Metallic通常為0非金屬Smoothness較高0.85-0.95。提高Smoothness能增強鏡面反射高光的銳利度和環境反射的清晰度。你可以嘗試將Fresnel輸出連接到Smoothness實現“邊緣更光滑中心更粗糙”的物理效果。4.3 性能優化小貼士貼圖尺寸用于海面的法線貼圖512x512分辨率通常足夠甚至可以嘗試256x256。因為Tiling通常很小貼圖會被拉伸高分辨率收益不大。節點簡化復雜的數學運算如多個Sine、Fraction會帶來性能成本。在滿足效果的前提下盡量簡化頂點位移部分的計算。有時用一張高度圖Height Map驅動頂點位移性能可能更好。LOD支持為海面材質配置多級LODLevel of Detail。在遠處可以使用更簡單的Shader變體例如減少一層法線混合甚至關閉頂點動畫只用紋理動畫。5. 常見問題排查與效果進階即使按照步驟搭建也可能會遇到一些奇怪的問題。這里記錄了幾個我踩過的坑和對應的解決方案。5.1 水面閃爍或抖動Z-fighting現象海面與海底或其他物體交界處出現閃爍的像素。原因海面網格與海底網格在深度Z值上過于接近深度緩沖精度不足以區分誰在前誰在后。解決方案輕微抬高海面在頂點著色器中將海面整體向上Y軸偏移一個微小值如0.001單位。可以在頂點位移計算完成后在最終的Y值上加一個很小的常數。調整渲染隊列確保海面材質的渲染隊列Render Queue在透明物體之前但在不透明物體之后。通常設置為Geometry1即2501。使用深度偏移在ShaderGraph的PBR Master節點或材質的Inspector面板中調整Depth Offset參數。這是一個非常有效的解決方案。5.2 波浪邊緣出現鋸齒Aliasing現象波浪的輪廓特別是由頂點動畫形成的尖銳波峰在移動時出現閃爍的鋸齒。原因頂點位移幅度過大導致三角形在屏幕空間的變化速率超過采樣頻率。解決方案開啟抗鋸齒在項目質量設置或攝像機中確保MSAA或后處理抗鋸齒如SMAA、FXAA是開啟的。柔化波浪降低頂點動畫的振幅或者讓波浪形狀更平滑例如使用Sine函數而不是更尖銳的函數。增加曲面細分如果使用支持曲面細分Tessellation的渲染管線如HDRP可以通過增加網格細分程度來提供更多的頂點細節從而平滑波浪曲線。但這會顯著增加性能開銷。5.3 法線貼圖接縫明顯現象流動的法線貼圖在UV邊界通常是0和1的位置出現明顯的、不連續的接縫。原因法線貼圖沒有設置為Wrap模式或者Tiling不是整數導致邊緣顏色對不上。解決方案檢查導入設置在Unity Project面板中選中法線貼圖在Inspector中確保Wrap Mode設置為Repeat重復而不是Clamp鉗制。使用無縫貼圖確保你使用的法線貼圖本身是“無縫”的即它的左右邊緣、上下邊緣可以完美拼接。很多在線工具可以制作無縫紋理。節點技巧在ShaderGraph中可以在UV進入Tiling And Offset之前先經過一個Fraction節點確保UV值始終在[0, 1)范圍內避免因浮點數精度問題導致的接縫。5.4 效果進階增加泡沫與焦散一個頂級的海面還需要泡沫和海底焦散Caustics效果。泡沫可以基于波浪的“陡度”生成。在Shader中計算頂點位移后相鄰頂點的斜率或高度差當差值超過某個閾值時使用一張泡沫貼圖進行混合。簡單實現可以采樣一張泡沫噪聲圖用波浪的Y方向導數通過DDX/DDY節點近似來驅動其顯示。焦散這是光線透過水面在海底形成的光影圖案。實現方法是在海底或水下物體的材質上投影一張動態的、扭曲的焦散貼圖。貼圖的UV偏移可以用與海面頂點動畫相似的Time和Sine函數驅動但速度更慢以模擬光線的緩慢移動。掌握了這五個核心節點和背后的原理你就從被參數支配的“調試者”變成了創造視覺規律的“設計師”。下一次當你想實現某種特定的水面效果時不妨先停下來思考我需要驅動哪些屬性用什么節點來生成這種變化如何混合多層信息這個過程本身就是Shader藝術最迷人的地方。