
ループがあるのでCustomノードに書きます。発散の判定は絶対値が2を超えた時点とし、発散と判定されるまでの計算回数が多い程輝度が上がるようにしました。

探検できるように300倍に拡大した'Plane'にマテリアルを貼り付けます。
Spectator Pawnで探検します。









離れてみると分かりにくいですが、近くから輪郭部を見ると非常に輝度が高いのがわかります。集合の左側は特に輝度が高く、更に拡大しても複雑なパターンが現れてきそうです。
プロジェクトをgithubにアップしました。
struct Wave | |
{ | |
Vec2 dir; | |
float amplitude; | |
float waveLength; | |
}; | |
struct ImmutableCB | |
{ | |
float waveSteepness; | |
float waveSpeed; | |
Wave waves[20]; | |
}; | |
static Vec3 CalcGerstnerWaveOffset(const ImmutableCB& cb, Vec3 location, float time) | |
{ | |
Vec3 sum = Vec3(0, 0, 0); | |
for (int i = 0; i < dimof(cb.waves); i++) | |
{ | |
const Wave& wave = cb.waves[i]; | |
float wi = 2 / wave.waveLength; | |
float rad = (dot(wave.dir, Vec2(location.x, location.z)) + time * cb.waveSpeed) * wi; | |
float sine = std::sin(rad); | |
float cosine = std::cos(rad); | |
sum.y += sine * wave.amplitude; | |
sum.x += wave.dir.x * cosine * cb.waveSteepness / (wi * dimof(cb.waves)); | |
sum.z += wave.dir.y * cosine * cb.waveSteepness / (wi * dimof(cb.waves)); | |
} | |
return sum; | |
} |
Vec3 center = pos + CalcGerstnerWaveOffset(immutableCb, pos, terrainFrameCB.g_time); | |
Vec3 offsetXZ = pos + Vec3(1, 0, 1) + CalcGerstnerWaveOffset(immutableCb, pos + Vec3(1, 0, 1), terrainFrameCB.g_time); | |
Vec3 offsetNegX = pos + Vec3(-1, 0, 0) + CalcGerstnerWaveOffset(immutableCb, pos + Vec3(-1, 0, 0), terrainFrameCB.g_time); | |
Vec3 offsetNegZ = pos + Vec3(0, 0, -1) + CalcGerstnerWaveOffset(immutableCb, pos + Vec3(0, 0, -1), terrainFrameCB.g_time); | |
Vec3 normal = normalize(cross(offsetNegZ - offsetXZ, offsetNegX - offsetXZ)); | |
Vec3 rotAxis = normalize(cross(normal, Vec3(0, 1, 0))); | |
float rotRad = acos(dot(normal, Vec3(0, 1, 0))); | |
cube.Draw(MeshXAnimResult(), scale(5, 5, 5) * q2m(Quat(rotAxis, -rotRad)) * translate(center.x, center.y, center.z)); |