周期的パーリンノイズ
この記事は全文無料でお読みいただけます。もしお気に召しましたら投げ銭お願いしますね。😉✨
パーリンノイズを使っていて、始点と終点の値を揃えたいなという場面があります。
例えば歪な円を描きたいとき、単純に半径にパーリンノイズを施しても大体始点と終点がこんな風にずれてしまいます。
始点と終点で noise() パラメータの値を合わせればいいのなら
noise(sin(0.0 〜 TWO_PI))
などとすることで実現できます。
しかし、これだと周期的にパラメータの値が同じになり、このように対象な図形になってしまいます。
この悩みを解決できそうなアイディアを Twitter 上で見かけました。
『二次元のノイズ平面上を円形軌道で移動すると始点と終点が同じ値に収束する一次元のノイズが得られる』
これは使えそう!さっそく試してみましょう。
『二次元のノイズ平面上を円形軌道で移動』
って、なんだか難しそうですが、なんのことはありません、円を描く数式を noise() のパラメータに入れればよいだけです。
// 円を描く数式
x = r * cos(a);
y = r * sin(a);
// 円を描く数式を noise() のパラメータに
noise(r * cos(a), r * sin(a));
試しにこれで歪んだ円を描くコードの一例がこれです。
/**
* 周期的なパーリンノイズ
* 2D パーリンノイズ面上の円周上の値を取ることにより周期的にする
*
* @author @deconbatch
* @version 0.1
* Processing 3.2.1
* Creative Commons CC0
*/
void setup() {
size(800, 800);
colorMode(HSB, 360, 100, 100, 100);
smooth();
noStroke();
noLoop();
}
void draw() {
float xInit = width * 0.5;
float yInit = height * 0.5;
float rBase = width * 0.25;
float rDiv = width * 0.2;
background(0.0, 0.0, 90.0, 100.0);
fill(0.0, 0.0, 30.0, 100.0);
for (float radian = 0.0; radian < TWO_PI; radian += 0.1) {
float pN = noise(rBase * cos(radian), rBase * sin(radian));
float pR = rBase + rDiv * noise(pN);
float pX = xInit + pR * cos(radian);
float pY = yInit + pR * sin(radian);
ellipse(pX, pY, 3.0, 3.0);
}
}
なんだかできてそうですね!点の密度を上げてみましょう。
for (float radian = 0.0; radian < TWO_PI; radian += 0.01) {
ちょっと変化が激しすぎて始点と終点が繋がってるかわかりませんね。
ノイズの変化を小さくしてみましょう。
float pN = noise(rBase * cos(radian) * 0.1, rBase * sin(radian) * 0.1);
もうちょっとかな?
float pN = noise(rBase * cos(radian) * 0.01, rBase * sin(radian) * 0.01);
なめらかになりました! 始点と終点もキレイに繋がっていますね。
あれ?結局対象な図形なの?
始点と終点が同じになったのはいいですが、図形が上下左右対象になってますね?
これじゃダメなんですが…
問題はここです。
float pN = noise(rBase * cos(radian) * 0.01, rBase * sin(radian) * 0.01);
これのここ。
cos(radian)
sin(radian)
どちらも -1.0 〜 1.0 の値を取ります。
Processing の noise() はパラメータの絶対値が同じなら返り値も同じになります。
noise(+a) と noise(-a) は同じ値になるんです。
なので、+ と ー で対象の図形になってしまうわけです。
イメージ的にはこんな感じ。
じゃあどうする?
今使ってるノイズのパラメータはこの青色の円周上の値を使っています。
原点を中心に + と ー 同じ値の範囲内ですね。
そうじゃなくて、例えばこの赤色の円周上の値を使えばよいのではないでしょうか?
float pN = noise(xInit + rBase * cos(radian) * 0.01, yInit + rBase * sin(radian) * 0.01);
ほらね!?
作例
これを使って例えばこんなものとかが簡単に作れます。
/**
* 周期的なパーリンノイズ
* 作例
*
* @author @deconbatch
* @version 0.1
* Processing 3.2.1
* Creative Commons CC0
*/
void setup() {
size(800, 800);
colorMode(HSB, 360, 100, 100, 100);
smooth();
noStroke();
noLoop();
}
void draw() {
float xInit = width * 0.5;
float yInit = height * 0.5;
float rDiv = width * 0.2;
background(0.0, 0.0, 90.0, 100.0);
for (float rBase = width * 0.05; rBase < width * 0.35; rBase += width * 0.01) {
fill(rBase % 360.0, 60.0, 60.0, 100.0);
for (float radian = 0.0; radian < TWO_PI; radian += 0.005) {
float pN = noise(xInit + rBase * cos(radian) * 0.02, yInit + rBase * sin(radian) * 0.02);
float pR = rBase + rDiv * noise(pN);
float pX = xInit + pR * cos(radian);
float pY = yInit + pR * sin(radian);
ellipse(pX, pY, 2.0, 2.0);
}
}
}
あと、以前作ったこのアニメーション。
動きを周期的にすることが難しくてループアニメーションにするのを諦めていたのですが、今回の手法を使ってこんなふうにループさせることが出来ました。
これはいい!他にも応用が効きそうですね。😉
この先に作例のちょっと大きめの画像が一枚あります。もしこの記事がお気に召しましたら投げ銭お願いします。😉✨
ここから先は
¥ 100
この記事が面白かったらサポートしていただけませんか? ぜんざい好きな私に、ぜんざいをお腹いっぱい食べさせてほしい。あなたのことを想いながら食べるから、ぜんざいサポートお願いね 💕