3d游戲開發(fā)特性名詞_法線貼圖疊加的動態(tài)水波紋動畫

水波紋

在 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 端可以考慮三層(底層大浪 + 中層波紋 + 頂層微波)。
    你想嘗試把這個效果應用在特定場景(比如湖面還是大海)嗎?我可以幫你針對性地調整參數設置。
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容