差分
このページの2つのバージョン間の差分を表示します。
両方とも前のリビジョン 前のリビジョン 次のリビジョン | 前のリビジョン 次のリビジョン両方とも次のリビジョン | ||
lecture:design_with_prototyping:p5.js編:15.ランダムとノイズ [2021/05/13 00:04] – baba | lecture:design_with_prototyping:p5.js編:15.ランダムとノイズ [2021/05/13 01:45] – [ふにゃふにゃする丸] baba | ||
---|---|---|---|
行 5: | 行 5: | ||
以下がオフィシャルのリファレンスページです. | 以下がオフィシャルのリファレンスページです. | ||
* https:// | * https:// | ||
- | 引数にランダム出力をしたい数値や数値の範囲,配列等を渡すことでランダムを返してくれます.公式リファレンスがわかりやすいので上記リンクを参照してください. | + | 引数にランダム出力をしたい数値や数値の範囲,配列等を渡すことでランダムを返してくれます.公式リファレンスがわかりやすいので上記リンクを参照してください.別段このページで改めて説明するまでもないですよね. |
+ | |||
+ | ===== Noise ====== | ||
+ | 以下がオフィシャルのリファレンスページです. | ||
+ | * https:// | ||
+ | touchDesignerではこのnoiseを頻繁に利用してアンビエントなグラフィック表現によく利用していますよね.「なんか適当な値を入れたい」という場合はrandomで十分な場合もありますが,例えばある時系列を持つ点を適当だけど,あんまり値が飛び飛びにならないようにスムーズに動かしたい.なんて場合にNoiseはとっても便利です. | ||
noise関数の引数は浮動小数点を渡すことができます.例えば以下の画像はnoise関数の引数に順番に1, | noise関数の引数は浮動小数点を渡すことができます.例えば以下の画像はnoise関数の引数に順番に1, | ||
行 22: | 行 27: | ||
- | |||
- | ===== Noise ====== | ||
- | 以下がオフィシャルのリファレンスページです. | ||
- | * https:// | ||
- | touchDesignerではこのnoiseを頻繁に利用してアンビエントなグラフィック表現によく利用していますよね. | ||
2Dノイズは,引数に2つ用いることで平面画像のふわっとした模様を生成することができます. | 2Dノイズは,引数に2つ用いることで平面画像のふわっとした模様を生成することができます. | ||
+ | |||
+ | <WRAP group> | ||
+ | <WRAP half column> | ||
+ | < | ||
+ | function setup() { | ||
+ | createCanvas(400, | ||
+ | noLoop(); | ||
+ | } | ||
+ | |||
+ | function draw() { | ||
+ | background(255); | ||
+ | | ||
+ | beginShape(POINTS); | ||
+ | for (let x = 0; x < width; x++) { | ||
+ | for (let y = 0; y < height; y++) { | ||
+ | let noiseVal = noise(x*0.02, | ||
+ | stroke(noiseVal*255); | ||
+ | vertex(x, | ||
+ | } | ||
+ | } | ||
+ | endShape(); | ||
+ | |||
+ | } | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | <WRAP half column> | ||
+ | {{: | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | |||
===== 一本の線 ===== | ===== 一本の線 ===== | ||
このランダムとノイズの違いを表す端的な例として,一本の線を描く,ということをしてみます.線はline関数を使うことで二点間を指定して描くことができますが,ここではbeginShape()を利用して,いくつか点を打った上で,ランダムとノイズの振る舞いの違いを確認してみます.まずは以下のプログラムを実行して結果を確認してみましょう. | このランダムとノイズの違いを表す端的な例として,一本の線を描く,ということをしてみます.線はline関数を使うことで二点間を指定して描くことができますが,ここではbeginShape()を利用して,いくつか点を打った上で,ランダムとノイズの振る舞いの違いを確認してみます.まずは以下のプログラムを実行して結果を確認してみましょう. | ||
+ | <WRAP group> | ||
+ | <WRAP half column> | ||
< | < | ||
function setup(){ | function setup(){ | ||
行 50: | 行 83: | ||
} | } | ||
</ | </ | ||
+ | </ | ||
+ | |||
+ | <WRAP half column> | ||
+ | 出力結果.png{{: | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | では次に上記のコードにおいて,yの値をrandomを使って上下+20, | ||
+ | |||
+ | <WRAP group> | ||
+ | <WRAP half column> | ||
+ | < | ||
+ | function setup(){ | ||
+ | createCanvas(500, | ||
+ | } | ||
+ | |||
+ | function draw() | ||
+ | { | ||
+ | background(255); | ||
+ | | ||
+ | beginShape(); | ||
+ | for( let i = 0; i < width; i += 10){ | ||
+ | vertex(i, height/ | ||
+ | } | ||
+ | endShape(); | ||
+ | } | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | <WRAP half column> | ||
+ | 出力結果.png{{: | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | ではここで,ちょっと趣を変えます.この「ガチャガチャ〜」っていうのがうるさいので,少しなめらかに変化して「うにょにょにょ〜」みたいに変化してくんないかな〜って考えてみます.なめらかに変化していく様子に修正するには,noiseを利用すると良いです.ただしnoise関数は先程のrandomと違って,返す値は0.0-1.0と決まっていますので,その点注意してください. | ||
+ | |||
+ | <WRAP group> | ||
+ | <WRAP half column> | ||
+ | < | ||
+ | function setup(){ | ||
+ | createCanvas(500, | ||
+ | } | ||
+ | |||
+ | function draw() | ||
+ | { | ||
+ | background(255); | ||
+ | | ||
+ | beginShape(); | ||
+ | for( let i = 0; i < width; i += 10){ | ||
+ | vertex(i, height/ | ||
+ | } | ||
+ | endShape(); | ||
+ | } | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | <WRAP half column> | ||
+ | 出力結果.png{{: | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | randomと比べて値がなだらかに変化している様子がわかります.ポイントはnoise関数への引数が大きく変化しないようにすることです.例えば noise(i) としてしまうと,randomと同様にガチャガチャした描画になってしまいます.試しにやってみてください.この引数の変化量に応じて値の滑らかさが変わる点に注意してください. | ||
+ | |||
+ | randomとはことなり,一度実行するとアニメーションが描画されません.これは実行時のnoise関数における初期値が変化しないため,何度描画しても同じ線分になるためです.この値は実行するたびに変化するので,確認してみてください.せっかくなのでなだらかに変化する様子をアニメーションにしてみたいと思います. | ||
+ | |||
+ | <WRAP group> | ||
+ | <WRAP half column> | ||
+ | < | ||
+ | let offset = 0.0; | ||
+ | |||
+ | function setup(){ | ||
+ | createCanvas(500, | ||
+ | } | ||
+ | |||
+ | function draw() | ||
+ | { | ||
+ | background(255); | ||
+ | | ||
+ | beginShape(); | ||
+ | for( let i = 0; i < width; i += 10){ | ||
+ | vertex(i, height/ | ||
+ | } | ||
+ | endShape(); | ||
+ | offset += 0.01; | ||
+ | } | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | <WRAP half column> | ||
+ | {{ : | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | では最後に頂点がカクカクしているので,vertexではなく,curveVertexを利用してみると,なだらかな変化になります. | ||
+ | |||
+ | <WRAP group> | ||
+ | <WRAP half column> | ||
+ | < | ||
+ | let offset = 0.0; | ||
+ | |||
+ | function setup(){ | ||
+ | createCanvas(500, | ||
+ | } | ||
+ | |||
+ | function draw() | ||
+ | { | ||
+ | background(255); | ||
+ | | ||
+ | beginShape(); | ||
+ | for( let i = 0; i < width; i += 10){ | ||
+ | curveVertex(i, | ||
+ | } | ||
+ | endShape(); | ||
+ | offset += 0.01; | ||
+ | } | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | <WRAP half column> | ||
+ | {{ : | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | ===== ふにゃふにゃする丸 ===== | ||
+ | ではここまでの内容を踏まえて,ふにゃふにゃアニメーションする丸を描いてみます.まず最初に先程までの線を円上に並べ直してみます.極座標を使って描きなおします.極座標のrは,各角度毎にノイズのパラメータが決定すれば比較的フニャッとした円を描くことができます. | ||
+ | <WRAP center round tip 60%> | ||
+ | ちょっと見た目を可愛くするのに,drawingContextというものを利用しています.これを使うと自動で描画したグラフィックに影をつけることができます. | ||
+ | </ | ||
+ | |||
+ | <WRAP group> | ||
+ | <WRAP half column> | ||
+ | < | ||
+ | let offset = 0.0; | ||
+ | |||
+ | function setup() { | ||
+ | createCanvas(400, | ||
+ | drawingContext.shadowBlur = 10; | ||
+ | drawingContext.shadowOffsetX = 5; // | ||
+ | drawingContext.shadowOffsetY = 5; // | ||
+ | drawingContext.shadowColor = color(0, 0, 0, 150); // | ||
+ | } | ||
+ | |||
+ | function draw() { | ||
+ | background(255, | ||
+ | |||
+ | fill(140, 180, 80); | ||
+ | strokeWeight(5); | ||
+ | stroke(150); | ||
+ | |||
+ | let r; | ||
+ | |||
+ | beginShape(); | ||
+ | for (let i = 0; i < 360; i += 12) { | ||
+ | r = 100 + 100*noise(i*0.1+offset); | ||
+ | curveVertex( | ||
+ | width / 2 + r * cos(radians(i)), | ||
+ | height / 2 + r * sin(radians(i)) | ||
+ | ); | ||
+ | } | ||
+ | | ||
+ | // もう一度最初の2点を指定するのは,curveVertexを閉じるため | ||
+ | // https:// | ||
+ | for (let i = 0; i < 36; i += 12) { | ||
+ | r = 100 + 100*noise(i*0.1+offset); | ||
+ | curveVertex( | ||
+ | width / 2 + r * cos(radians(i)), | ||
+ | height / 2 + r * sin(radians(i)) | ||
+ | ); | ||
+ | } | ||
+ | |||
+ | endShape(); | ||
+ | offset += 0.01; | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | </ | ||
+ | |||
+ | <WRAP half column> | ||
+ | {{ : | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | こんなんで,それっぽく見えるんですが,描かれた円の下側をみると微妙にとんがったところが見えます.これは,始点と終点の位置が大きくずれてしまっているためです.とは言ってもこのままでも気にならない場合は全然構わないと思います. | ||
+ | |||
+ | noiseを利用すればズレをなだらかに表示できたわけですが,結局始点と終点ではnoiseへの引数が異なるため,大きく値が異なってしまっているわけです.どのようにすればよいかですが,このページではnoiseにわたす引数をsin関数を用いて最初と最後の値が同じになるようにしてみました. | ||
+ | |||