GPU Gems1-Effective Water Simulation from Physical Models
Chapter 1. Effective Water Simulation from Physical Models | NVIDIA Developer
Game-Programmer-Study-Notes/Content/《GPU Gems 1》全书提炼总结/README.md at master · QianMo/Game-Programmer-Study-Notes · GitHub
这里主要是看上面的内容,我主要写一下我的疑惑点:
首先是下面的方程3,我认为这就是说多个正弦函数叠加近似得到的高度场函数。
UE实现
我们主要关注,法线和位置的偏移
普通的正弦波
普通的正弦波,也就是高度上z的偏移以及法线的变换
WaveLength
Speed
time
direction
aPos_xy
amplitudestruct MyFunction
{float3 calculateNormal(float amplitude,float WaveLength,float Speed,float time,float2 direction,float2 aPos_xy){float3 normal = float3(0, 0, 1);float w = 2 / WaveLength;float phi = Speed * w;float x = -1.0f * amplitude * w * direction.x * cos(dot(direction, aPos_xy) * w +time * phi);float y = -1.0f * amplitude * w * direction.y * cos(dot(direction, aPos_xy) * w +time * phi);normal.x = x;normal.y = y;return normal;}float3 calculateGerstner(float amplitude,float WaveLength,float Speed,float time,float2 direction,float2 aPos_xy,float Q){float3 res = float3(0, 0, 0);float w = 2 / WaveLength;float phi = Speed * w;float x = Q * amplitude * direction.x * cos(w * dot(direction, aPos_xy) + time * phi);float y = Q * amplitude * direction.y * cos(w * dot(direction, aPos_xy) + time * phi);float z = amplitude * sin(w * dot(direction, aPos_xy) + time * phi);res.x = x;res.y = y;res.z = z;return res;}float calculateHeight(float amplitude,float WaveLength,float Speed,float time,float2 direction,float2 aPos_xy){float w = 2 / WaveLength;float phi = Speed * w;float z = amplitude * sin(w * dot(direction, aPos_xy) + time * phi);return z;}
} myFun;
float3 loc = float3(0, 0, 0);
float2 seed = float2(123.456, 789.012);
normal = float3(0, 0, 1);
for(int i = 0; i < 3; i++)
{seed = frac(seed * 123.456);float amplitude = A_min + (A_max - A_min) * seed.x;float WaveLength = WaveLength_min + (WaveLength_max - WaveLength_min) * seed.x;float Speed = Speed_min + (Speed_max - Speed_min) * seed.x;float2 direction = normalize(float2(seed.x, seed.y));normal += myFun.calculateNormal(amplitude, WaveLength, Speed, time, direction, aPos_xy);normal.z = 1.0;loc.z += myFun.calculateHeight(amplitude, WaveLength, Speed, time, direction, aPos_xy);
}
normal = normalize(normal);
return loc;
Geometric Waves
Directional or Circular
WaveLength
Speed
time
direction
aPos_xy
amplitudestruct MyFunction
{float3 calculateNormal(float amplitude,float WaveLength,float Speed,float time,float2 direction,float2 aPos_xy){float3 normal = float3(0, 0, 1);float w = 2 / WaveLength;float phi = Speed * w;float x = -1.0f * amplitude * w * direction.x * cos(dot(direction, aPos_xy) * w +time * phi);float y = -1.0f * amplitude * w * direction.y * cos(dot(direction, aPos_xy) * w +time * phi);normal.x = x;normal.y = y;return normal;}float3 calculateGerstner(float amplitude,float WaveLength,float Speed,float time,float2 direction,float2 aPos_xy,float Q){float3 res = float3(0, 0, 0);float w = 2 / WaveLength;float phi = Speed * w;float x = Q * amplitude * direction.x * cos(w * dot(direction, aPos_xy) + time * phi);float y = Q * amplitude * direction.y * cos(w * dot(direction, aPos_xy) + time * phi);float z = amplitude * sin(w * dot(direction, aPos_xy) + time * phi);res.x = x;res.y = y;res.z = z;return res;}float calculateHeight(float amplitude,float WaveLength,float Speed,float time,float2 direction,float2 aPos_xy){float w = 2 / WaveLength;float phi = Speed * w;float z = amplitude * sin(w * dot(direction, aPos_xy) + time * phi);return z;}
} myFun;
float3 loc = float3(0, 0, 0);
float2 seed = float2(123.456, 789.012);
normal = float3(0, 0, 1);
for(int i = 0; i < 3; i++)
{seed = frac(seed * 123.456);float amplitude = A_min + (A_max - A_min) * seed.x;float WaveLength = WaveLength_min + (WaveLength_max - WaveLength_min) * seed.x;float Speed = Speed_min + (Speed_max - Speed_min) * seed.x;float2 direction = normalize(aPos_xy);normal += myFun.calculateNormal(amplitude, WaveLength, Speed, time, direction, aPos_xy);normal.z = 1.0;loc.z += myFun.calculateHeight(amplitude, WaveLength, Speed, time, direction, aPos_xy);
}
normal = normalize(normal);
return loc;
Gerstner Waves
struct MyFunction
{float3 calculateNormal(float amplitude,float WaveLength,float Speed,float time,float2 direction,float2 aPos_xy,float Q){float3 normal = float3(0, 0, 1);float w = 2 / WaveLength;float WA = w * amplitude;float phi = Speed * w;float S = sin(w * dot(direction, aPos_xy) + time * phi);float C = cos(w * dot(direction, aPos_xy) + time * phi);float x = - WA * direction.x * C;float y = - WA * direction.y * C;float z = - WA * S * Q;normal.x = x;normal.x = x;normal.y = y;return normal;}float3 calculateGerstner(float amplitude,float WaveLength,float Speed,float time,float2 direction,float2 aPos_xy,float Q){float3 res = float3(0, 0, 0);float w = 2 / WaveLength;float phi = Speed * w;float x = Q * amplitude * direction.x * cos(w * dot(direction, aPos_xy) + time * phi);float y = Q * amplitude * direction.y * cos(w * dot(direction, aPos_xy) + time * phi);float z = amplitude * sin(w * dot(direction, aPos_xy) + time * phi);res.x = x;res.y = y;res.z = z;return res;}
} myFun;
float3 loc = float3(0, 0, 0);
float2 seed = float2(123.456, 789.012);
normal = float3(0, 0, 1);
for(int i = 0; i < 3; i++)
{seed = frac(seed * 123.456);float amplitude = A_min + (A_max - A_min) * seed.x;float WaveLength = WaveLength_min + (WaveLength_max - WaveLength_min) * seed.x;float Speed = Speed_min + (Speed_max - Speed_min) * seed.x;float2 direction = normalize(float2(seed.x, seed.y));float Q = Q_min + (Q_max - Q_min) * seed.x;normal += myFun.calculateNormal(amplitude, WaveLength, Speed, time, direction, aPos_xy, Q);loc += myFun.calculateGerstner(amplitude, WaveLength, Speed, time, direction, aPos_xy, Q);
}
normal = normalize(normal);
return loc;