
水波紋
在 Unity URP 中實現多層法線貼圖疊加的動態(tài)水面,是讓水體看起來“靈動”且具有層次感的關鍵。如果只用一張法線貼圖,水面看起來就像是在傳送帶上移動的塑料片。(TODO 沒有試)
以下是實現這一效果的原理分析與具體實操指南。
1. 核心原理:波紋的干涉與疊加
實現自然水波紋的核心在于:利用物理上的干涉現象,打破單一紋理的周期性。
A. 疊加原理 (Blending)
我們通常使用兩層(甚至更多)法線貼圖。如果只是簡單地將兩個法線的 RGB 相加,會導致結果超出 [-1, 1] 范圍,使光影畸變。
- 線性疊加 (Linear Blending): 將法線從 [0, 1] 重映射到 [-1, 1],相加后再歸一化。效果一般,容易丟失細節(jié)。
- RNM 疊加 (Reoriented Normal Mapping): 這是目前主流的高級算法,它能旋轉第二層法線使其貼合在第一層法線的表面上,完美保留兩者的細節(jié)。
B. 動畫原理 (Panner)
通過改變 UV 坐標的偏移值(Offset),讓兩張紋理以不同的方向、不同的速度和不同的縮放(Tiling)進行平移。
- 方向差異: 比如一層向西北,一層向正東,交匯處會產生錯落感。
- 頻率差異: 一層大波紋(低 Tiling),一層小碎波(高 Tiling)。
2. Unity URP 實現步驟 (Shader Graph 方案)
在 URP 中,使用 Shader Graph 是最直觀、高效的方式。
第一步:基礎屬性定義
創(chuàng)建以下變量以便在材質球上調節(jié):
- Main Normal & Second Normal (Texture2D)
- Normal Strength (Float)
- Wave Speed A & Wave Speed B (Vector2)
- Tiling A & Tiling B (Vector2)
第二步:讓法線“動起來”
- 使用 Time 節(jié)點。
- 將 Time 乘以 Wave Speed A。
- 接入 Tiling And Offset 節(jié)點的 Offset 槽位。
- 將對應的 Tiling A 接入 Tiling 槽位。
- 使用 Sample Texture 2D 采樣法線貼圖(記得 Type 選為 Normal)。
- 對第二層法線重復上述步驟,但使用不同的速度和縮放。
第三步:法線混合 (The Magic)
在 Shader Graph 中,不需要自己寫復雜的數學公式:
- 搜索并添加 Normal Blend 節(jié)點。
- 將第一層法線連入 In,第二層法線連入 Detail。
- 注意: 模式通常選 Default(即 RNM 算法)。
- 如果你想控制整體強度,在輸出前加一個 Normal Strength 節(jié)點。
第四步:結合光照與 Fresnel (菲涅爾)
水面不僅僅有波紋,還需要反射和透明度:
- 將混合后的法線連入 Fragment 階段的 Normal (Tangent Space)。
- Fresnel Effect: 使用 Fresnel 節(jié)點控制邊緣反射。由于法線在動,菲涅爾效果也會隨之抖動,產生波光粼粼的真實感。
- Smoothness: 調高平滑度(如 0.95 以上)。
3. 進階 HLSL 代碼實現 (可選)
如果你更喜歡寫代碼(Custom Function),核心的疊加代碼如下:
// 1. UDN Blending (最簡單)
float3 BlendNormals_UDN(float3 n1, float3 n2) {
return normalize(n1 + n2);
}
// 2. Whiteout Blending
float3 BlendNormals_Whiteout(float3 n1, float3 n2) {
n1 = n1 * 2.0 - 1.0;
n2 = n2 * 2.0 - 1.0;
return normalize(float3(n1.xy + n2.xy, n1.z * n2.z));
}
// 3. RNM (需要更多數據)
float3 BlendNormals_RNM(float3 n1, float3 n2, float3 tangent, float3 bitangent) {
n1 = n1 * 2.0 - 1.0;
n2 = n2 * 2.0 - 1.0;
// 構建旋轉矩陣 [tangent, bitangent, n1]
float3x3 rotation = float3x3(tangent, bitangent, n1);
// 旋轉n2到n1的坐標系
return normalize(mul(n2, rotation)); // 注意矩陣乘法順序取決于坐標系定義
}
4. 優(yōu)化小技巧
- UV 旋轉: 除了平移,給其中一層增加微小的旋轉,可以徹底消除紋理重復感。
- 深度衰減: 結合 Scene Depth,讓淺水區(qū)透明,深水區(qū)深邃,配合動起來的法線,效果直接翻倍。
- 計算開銷: 移動端建議只用兩層法線;PC 端可以考慮三層(底層大浪 + 中層波紋 + 頂層微波)。
你想嘗試把這個效果應用在特定場景(比如湖面還是大海)嗎?我可以幫你針對性地調整參數設置。