9 海をつくる
7 ノイズをつくろう と 8 フレネル反射をつくる を組み合わせる。
パーリンノイズをハイトマップ(高さを定義したマップ)としてつかう。ddx
と ddy
という、部分微分(隣のピクセルとの差分)を取得できる関数をつかう。この外積(ベクトルとベクトルをあわせてつくったひし形に垂直なベクトル)を法線としてつかうことで、波立たせることができる。
normal = cross (
float3(0,ddy(height),1),
float3(1,ddx(height),0)
)
4 スクロールする水面を作る のように uv スクロールさせて波を動かす。
i.uv.x += 0.1 * _Time;
i.uv.y += 0.2 * _Time;
これで波そのものはできたが、エイリアシング(遠景の波が細かく表示され見た目が悪くなる現象)が発生する。
そこで、カメラと法線のベクトルの内積が 0 に近いほど急速に出力も 0 に近づいていく関数を導入する。今回はシグモイド関数をつかう。
好きな形に近づけていく。
フレネル反射で既に内積を求めているため、変数を拝借する。
//フレネル反射
half vdotn = saturate(dot(viewDir, i.normal));
...
//エイリアシングを防ぐための重みづけ
float weight = 1.0 / (1.0 + exp(-60.0 * vdotn + 5.0));
//パーリンノイズを生成
float height = noise(i.uv * 64) * weight;
これで、見た目の良い波ができた。