You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确计算Gertner波法线?Godot代码异常求助

Gerstner波法线计算错误排查与修正

问题根源分析

你的代码存在以下几个关键错误,导致法线计算异常:

  1. 波数计算错误:Gerstner波的波数k应为2π/波长,你写成了2/波长,缺失了π,直接导致波的频率和相位完全偏离预期。
  2. 相位计算不一致且符号错误:get_wave与get_normal的相位公式不统一,且波的传播相位应该是k*(方向点积原始坐标 - 速度*时间)(减号表示波沿方向移动),你使用了加号,相位方向完全错误。
  3. 法线公式推导错误:当前get_normal的计算式不符合Gerstner波的法线数学推导,且未对法线向量进行归一化。
  4. 顶点位移处理错误:直接赋值VERTEX.y = res.y会丢失原始顶点的基础高度,叠加多个波时问题更明显。
  5. 法线后处理错误:NORMAL.y = 1.0 - NORMAL.y属于无意义操作,破坏了法线的方向正确性。

修正后的代码

vec3 get_wave(vec4 wave, vec2 direction, vec3 vtx)
{
    // x = SPEED, y = WAVELENGTH, z = AMPLITUDE, w = STEEPNESS
    float lambda = wave.y;
    float amplitude = wave.z;
    float steepness = wave.w;
    float speed = wave.x;
    
    float k = 2.0 * PI / lambda; // 正确的波数计算
    float theta = k * (dot(direction, vtx.xz) - speed * TIME); // 正确的传播相位
    
    vec3 displacement = vec3(0.0);
    displacement.x = steepness * amplitude * direction.x * cos(theta);
    displacement.z = steepness * amplitude * direction.y * cos(theta);
    displacement.y = amplitude * sin(theta);
    return displacement;
}

vec3 get_normal(vec4 wave, vec2 direction, vec3 vtx)
{
    float lambda = wave.y;
    float amplitude = wave.z;
    float steepness = wave.w;
    float speed = wave.x;
    
    float k = 2.0 * PI / lambda;
    float theta = k * (dot(direction, vtx.xz) - speed * TIME);
    
    float kA = k * amplitude;
    vec3 normal;
    // 遵循GPU Gems中Gerstner波的法线公式
    normal.x = -steepness * kA * direction.x * cos(theta);
    normal.z = -steepness * kA * direction.y * cos(theta);
    normal.y = 1.0 - steepness * kA * sin(theta);
    
    return normalize(normal); // 必须归一化得到正确的单位法线
}

void vertex() {
    vec3 original_vtx = VERTEX;
    vec3 wave_displacement = get_wave(wave_1, wave_1_dir, original_vtx);
    
    // 正确叠加波位移,保留原始顶点高度
    VERTEX.x += wave_displacement.x;
    VERTEX.y += wave_displacement.y;
    VERTEX.z += wave_displacement.z;
    
    // 使用原始顶点计算法线,避免位移后的坐标干扰
    NORMAL = get_normal(wave_1, wave_1_dir, original_vtx);
}

额外注意事项

  • 确保wave_1_dir是归一化的单位向量,否则会导致波的传播方向和幅度计算错误。
  • 如果需要叠加多个Gerstner波,需将每个波的位移相加,法线分量相加后再统一归一化。

内容的提问来源于stack exchange,提问作者E F

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 09:49:55