
オーディオ信号の処理を研究したとき、私の脳は手続き型カード生成との類似性を引き出し始めました。 この記事では、信号処理とカード生成をリンクする原理の概要を説明します。 何か新しいことを発見したとは思いませんが、結論のいくつかは私にとって新しいものだったので、書き留めて読者と共有することにしました。 単純なトピック(周波数、振幅、ノイズの色、ノイズの使用)のみを考慮し、他のトピック(離散および連続関数、FIR / IIRフィルター、高速フーリエ変換、複素数)には触れません。 この記事の数学は主に正弦波に関連しています。
この記事では 、最も単純なものからより複雑なものまでの概念に焦点を当てています 。 ノイズ関数を使用して地形を直接生成する場合は、 他の記事をご覧ください。
乱数を使用する基本から始めて、次に1次元の風景の動作を説明します。 同じ概念が2D( デモを参照)と3Dでも機能します。 [ 元の記事]のスライダーを動かして、単一のパラメーターがさまざまな種類のノイズをどのように表現できるかを確認してください。
GIF

この記事から次のことを学びます。
- わずか15行のコードで同様のランドスケープを生成する方法
- 赤、ピンク、白、青、紫のノイズとは
- 手続き関数の生成にノイズ関数を使用する方法
- 中点オフセット、パーリンノイズ、およびフラクタルブラウン運動がどのように適用されるか
さらに、2次元の高さマップの3D視覚化の作成など、2Dノイズの実験を行います。
1.ランダム性が役立つのはなぜですか?
共通点と異なる点を持つ出力データのセットを取得するには、マップの手順生成が必要です。 たとえば、すべてのMinecraftマップには、バイオーム領域、グリッドサイズ、平均バイオームサイズ、高さ、平均洞窟サイズ、各タイプの石の割合など、多くの共通点があります。 しかし、バイオームの場所、洞窟の場所と形状、金の配置などにも違いがあります。 設計者は、どの側面を同じままにし、どの側面を異なるようにするかを決定し、この違いの程度を取る必要があります。
さまざまな側面については、通常、乱数ジェネレーターを使用します。 超シンプルなカードジェネレーターを作成しましょう。20ブロックの行を生成し、ブロックの1つに金の宝箱が含まれます。 必要なカードをいくつか説明しましょう(宝物には「x」のマークが付いています):
1 ........x........... 2 ...............x.... 3 .x.................. 4 ......x............. 5 ..............x.....
これらのカードの共通点に注意してください。それらはすべてブロックで構成され、ブロックは同じライン上にあり、ラインは20ブロックの長さを持ち、2種類のブロックとちょうど1つの宝箱があります。
しかし、1つの異なる側面があります-ブロックの場所です。 0(左)から19(右)までの任意の位置に配置できます。
乱数を使用して、このブロックの位置を選択できます。 最も簡単な方法は、0〜19の範囲の乱数を一様に選択することです。これは、0〜19の位置を選択する確率が同じであることを意味します。 ほとんどのプログラミング言語には、乱数を均一に生成する機能があります。 Pythonでは、これは関数
random.randint(0,19)
ですが、この記事では
random(0,19)
という表記を使用します。 Pythonコードのサンプルは次のとおりです。
def gen(): map = [0] * 20 # pos = random.randint(0, 19) # map[pos] = 1 # return map for i in range(5): # 5 print_chart(i, gen())
しかし、チェストをカードの左側に配置する必要があるとします。 これを行うには、乱数の異種選択が必要です。 それを実装するには多くの方法があります。 それらの1つは、一様な方法で乱数を選択し、それを左にシフトすることです。 たとえば、
random(0,19)/2
試すことができます。 これはPythonコードです:
def gen(): map = [0] * 20 pos = random.randint(0, 19) // 2 map[pos] = 1 return map for i in range(5): print_chart(i, gen())
しかし、実際にはこれはまったく必要ありませんでした。 私は時々右に宝物が欲しかったが、より頻繁に左に宝物を欲した。 宝物を左に移動する別の方法は、
sqr(random(0,19))/19
ようなことをして数字を二乗することです。 ゼロの場合、20を20で割った値は0です。19である場合、19を19で割った値は19になります。 19で5に等しい。0から19までの範囲を維持したが、中間の数値を左に移動した。 この再配布自体は非常に有用な手法であり、以前のプロジェクトでは平方、平方根、その他の関数を使用していました。 ( このサイトには、アニメーションで使用される標準のフォーム変更関数があります。関数にカーソルを合わせると、デモが表示されます。)二乗を使用するPythonコードは次のとおりです。
def gen(): map = [0] * 20 pos = random.randint(0, 19) pos = int(pos * pos / 19) map[pos] = 1 return map for i in range(1, 6): print_chart(i, gen())
オブジェクトを左に移動する別の方法は、最初にランダムに乱数の範囲の制限を選択し、次に0から範囲の制限までの番号をランダムに選択することです。 範囲の制限が19の場合、番号はどこにでも置けます。 範囲の制限が10の場合、数値は左側にのみ配置できます。 Pythonコードは次のとおりです。
def gen(): map = [0] * 20 limit = random.randint(0, 19) pos = random.randint(0, limit) map[pos] = 1 return map for i in range(5): print_chart(i, gen())
均一な乱数を取得し、それらを希望する特性を持つ異種に変換する多くの方法があります。 ゲームデザイナーとして、乱数の分布を選択できます。 乱数を使用してロールプレイングゲームの損害を判断する方法に関する記事を書きました。 トリックにはさまざまな例があります。
要約すると:
- 手続き型生成では、何が同じままで何が変わるかを決定する必要があります。
- 乱数は、変化する部分を埋めるのに役立ちます。
- ほとんどのプログラミング言語では、均一に選択可能な乱数を取得できますが、多くの場合、異種の選択可能な乱数が必要です。 それらを取得するさまざまな方法があります。
2.ノイズとは何ですか?
ノイズは、通常、ライン上またはグリッド内にある一連の乱数です。
古いテレビで信号のないチャンネルに切り替えると、画面にランダムな黒と白のドットが見えました。 これはノイズです(それらの宇宙空間!)。 ステーションなしでラジオチャンネルにチューニングすると、ノイズも聞こえます(宇宙から聞こえるか、他の場所から聞こえるかはわかりません)。
信号処理では、通常、ノイズは望ましくない側面です。 騒がしい部屋では、静かな部屋よりも話し相手の声が聞こえにくいです。 オーディオノイズは、一列に並んだ乱数です(1D)。 ノイズの多い画像では、鮮明な画像よりも写真を見にくくなります。 グラフィックノイズは、グリッド(2D)にある乱数です。 3D、4Dなどでノイズを作成できます。
ほとんどの場合、ノイズを除去しようとしますが、多くの自然なシステムはノイズが多いように見えるため、自然に見えるものを生成するには、ノイズを追加する必要があります。 実際のシステムはノイズが多いように見えますが、通常は構造に基づいています。 追加するノイズは同じ構造ではありませんが、シミュレーションをプログラミングするよりもはるかに単純なので、ノイズを使用します。エンドユーザーがこれに気付かないことを願っています。 この妥協については後で説明します。
ノイズの有用性の簡単な例を見てみましょう。 上記で作成した1次元の地図があると仮定しますが、宝箱の代わりに、谷、丘、山のある風景を作成する必要があります。 各ポイントで乱数の均一な選択を使用することから始めましょう。
random(1,3)
が1の場合、2-丘、3-山の場合、谷と見なされます。 乱数を使用して高さマップを作成しました。配列内の各ポイントについて、地形の高さを保存しました。 ランドスケープを作成するためのPythonコードは次のとおりです。
for i in range(5): random.seed(i) # print_chart(i, [random.randint(1, 3) for i in range(mapsize)]) # : Python: # output = [abc for x in def] # : # output = [] # for x in def: # output.append(abc)
うーん、これらのカードは、私たちの目的にとって「ランダムすぎる」ように見えます。 おそらく、谷や丘の広い領域が必要であり、山は谷ほど頻繁にあるべきではありません。 先ほど、一様な乱数の選択は適切ではない場合があり、場合によっては異種の選択が必要になることがありました。 この問題を解決するには? 谷が山よりも頻繁に表示されるランダムな選択を使用できます。
for i in range(5): random.seed(i) print_chart(i, [random.randint(1, random.randint(1, 3)) for i in range(mapsize)])
これにより山の数は減りますが、面白い絵は作成されません。 このような不均一なランダム選択の問題は、変更が各ポイントで個別に発生することであり、あるポイントでのランダム選択が何らかの方法で隣接ポイントでのランダム選択に関連する必要があるということです。 これは一貫性と呼ばれます。
そして、ここでノイズ関数は便利です。 一度に1つの数字ではなく、一連の乱数を提供します。 ここでは、シーケンスを作成するために1Dノイズ関数が必要です。 同次乱数のシーケンスを変更するノイズ関数を使用してみましょう。 これを行うにはさまざまな方法がありますが、少なくとも2つの隣接する番号を使用します。 初期ノイズが1、5、2の場合、最小値(1、5)は1、最小値(5、2)は2です。したがって、最終ノイズは1、2になります。高点(5)を削除したことに注意してください。 また、結果のノイズでは、1つの値が元の値よりも小さいことに注意してください。 つまり、60個の乱数を生成すると、出力は59個になります。この関数を最初のカードセットに適用してみましょう。
def adjacent_min(noise): output = [] for i in range(len(noise) - 1): output.append(min(noise[i], noise[i+1])) return output for i in range(5): random.seed(i) noise = [random.randint(1, 3) for i in range(mapsize)] print_chart(i, adjacent_min(noise))
以前のマップと比較すると、谷、丘、または山のエリアがここにあります。 山は丘の近くに多く見られます。 また、ノイズを変更する方法(最小値を選択)のおかげで、谷は山よりも一般的です。 最大値を取得した場合、画像は逆になります。 谷も山も頻繁にしたくない場合、最小値または最大値の代わりに平均値を選択します。
これで、入力でノイズを受け取り、より滑らかな新しいノイズを作成するノイズ修正手順ができました。
そして、もう一度実行してみましょう!
def adjacent_min(noise): # output = [] for i in range(len(noise) - 1): output.append(min(noise[i], noise[i+1])) return output for i in range(5): random.seed(i) noise = [random.randint(1, 3) for i in range(mapsize)] print_chart(i, adjacent_min(adjacent_min(noise)))
現在、マップはさらに滑らかになり、山はさらに少なくなっています。 山はあまり頻繁に丘に現れないので、私たちはあまりにも滑らかにしたと思います。 したがって、この例では、スムージングのレベルを1つ戻すことをお勧めします。
これは手続き型生成の標準プロセスです。何かを試してみて、見栄えが良いかどうかを確認し、そうでない場合は戻って別のことを試してください。
注:信号処理のアンチエイリアスは、 ローパスフィルターと呼ばれます 。 不要なノイズを除去するために使用される場合があります。
要約すると:
- ノイズは一連の乱数で、通常はラインまたはグリッドに並んでいます。
- プロシージャ生成では、多くの場合、ノイズを追加してバリエーションを作成する必要があります。
- 乱数を単純に選択すると(同種か異種かを問わず)、各数値が周囲に関係しないノイズが発生します。
- 多くの場合、特定の特性を備えたノイズが必要です。たとえば、山を丘に近づけるなどです。
- ノイズを発生させる方法はたくさんあります。
- ノイズ関数には、ノイズを直接作成するものと、既存のノイズを取得して修正するものがあります。
ノイズ関数の選択は、多くの場合試行錯誤プロセスです。 ノイズの本質とその修正方法を理解することで、より意味のある選択をすることができます。
3.音を立てる
前のセクションでは、出力として乱数を使用してノイズを選択し、それらを平滑化しました。 これは標準パターンです。 パラメータとして乱数を使用するノイズ関数から始めます 。 乱数が宝の位置を選択したときに使用し、次に乱数が谷/丘/山を選択した別の場所を使用しました。 既存のノイズを変更して、要件に応じてその形状を変更できます。 谷/丘/山のノイズ関数を平滑化して修正しました。 ノイズ関数を変更するにはさまざまな方法があります。
単純な1D / 2Dノイズジェネレーターの例:
- 出力に乱数を直接使用します。 だから私たちは谷/丘/山のためにやった。
- 出力に使用される正弦および余弦のパラメーターとして乱数を使用します。
- 出力に使用されるグラデーションのパラメーターとして乱数を使用します。 この原則は、Perlinのノイズで使用されます。
ノイズを修正する一般的な方法は次のとおりです。
- フィルタを適用して、特定の特性を低減または強化します。 谷/丘/山については、スムージングを使用してジャンプを減らし、谷の面積を増やし、丘の近くに山を作成しました。
- 最終結果に対する各ノイズ関数の効果を制御できるように、通常は加重和で、複数のノイズ関数を同時に追加します。
- ノイズ関数によって取得されたノイズ値の間を補間して、平滑化された領域を生成します。
音を立てる方法はたくさんあります !
ある程度、ノイズがどのように生成されたかは関係ありません。 これは興味深いですが、ゲームで使用する場合は、次の2つの側面に注目する必要があります。
- どのようにノイズを使用しますか?
- それぞれの場合、ノイズ関数からどのようなプロパティが必要ですか?
4.ノイズの使用方法
ノイズ関数を使用する最も簡単な方法は、高さとして直接使用することです。 上記の例では、マップの各ポイントで
random(1,3)
を呼び出して、谷/丘/山を生成しました。 ノイズ値は、高さとして直接使用されます。
中点変位ノイズまたはパーリンノイズの使用も、直接使用の例です。
ノイズを使用する別の方法は、前の値からのオフセットとして使用することです。 たとえば、ノイズ関数が
[2, -1, 5]
返す場合、最初の位置は2、2番目は2 + -1 = 1、3番目は1 + 5 = 6であると想定できます。 「ランダムウォーク」も参照してください。 。 反対のことを行い、ノイズ値の差を使用できます。 これは、ノイズ関数の修正と考えることもできます。
ノイズを使用して高さを設定する代わりに、オーディオに使用できます。
またはフォームを作成します。 たとえば、極座標のグラフの半径としてノイズを使用できます。 出力を高さではなく半径として使用して、 このような1Dノイズ関数を極形式に変換できます。 同じ関数が極形式でどのように見えるかを示しています。
または、ノイズをグラフィックテクスチャとして使用できます。 この目的のために、Perlinノイズがよく使用されます。
ノイズを適用して、木、金鉱、火山、地震の亀裂などのオブジェクトの場所を選択できます。 上記の例では、宝箱の場所を選択するために乱数を使用しました。
ノイズをしきい値関数として使用することもできます。 たとえば、値が3を超えるといつでも1つのイベントが発生し、それ以外の場合は何かが発生すると想定できます。 この一例は、Perlinの3Dノイズを使用して洞窟を生成することです。 すべてが特定の密度のしきい値を超えており、このしきい値を下回るすべてが屋外(洞窟)であると想定できます。
ポリゴンマップジェネレーターでは、さまざまな方法でノイズを使用しましたが、ノイズを直接使用して高さを決定する方法はありませんでした。
- 正方形または六角形のグリッドを使用すると、グラフ構造が最も簡単になります(実際、六角形のグリッドから始めました)。 各メッシュ要素はポリゴンです。 グリッドにランダム性を追加したかった。 これは、ポイントをランダムに移動することで実行できます。 しかし、もっとランダムなものが必要でした。 ブルーノイズジェネレーターを使用してポリゴンを配置し、ボロノイ図を使用して再構成しました。 もっと時間がかかりますが、幸いなことに、私のためにすべてをしてくれるライブラリ(
as3delaunay
)がありました。 しかし、私はグリッドから始めましたが、これははるかに簡単であり、それから、あなたから始めることをお勧めします。 - 海岸線は、土地を水から分離する方法です。 このノイズを使用して2つの異なる方法で生成しましたが、デザイナーに形状を自分で描くように依頼することもでき、正方形と円形の形状を使用してデモンストレーションしました。 海岸線の放射状の形状は、サインとコサインを使用したノイズ関数であり、極形式でレンダリングします。 パーリンの海岸線形状は、パーリンノイズと放射状のリターンをしきい値として使用するノイズジェネレーターです。 ここでは、任意の数のノイズ関数を使用できます。
- 川の水源はランダムに配置されています。
- ポリゴン間の境界は、直線からノイズの多い線に変わります。 これは中点の変位に似ていますが、ポリゴンの境界内に収まるようにスケーリングしました。 これは純粋にグラフィック効果なので、コードは基本的なアルゴリズム(
Map.as
)ではなくGUI(mapgen.as
)にあります。
ほとんどのマニュアルはノイズをかなり簡単に使用していますが、それを使用する方法は他にもたくさんあります。
5.ノイズ周波数
頻度は、私たちが興味を持っている最も重要な特性です。 それを理解する最も簡単な方法は、正弦波を見ることです。 これは、平均周波数の正弦波になった後の低周波数の正弦波であり、最後に高周波数の正弦波があります。
print_chart(0, [math.sin(i*0.293) for i in range(mapsize)])
print_chart(0, [math.sin(i*0.511) for i in range(mapsize)])
print_chart(0, [math.sin(i*1.57) for i in range(mapsize)])
ご覧のように、低周波数は広い丘を作成し、高周波数は狭い丘を作成します。 頻度は、グラフの水平サイズを表します。 振幅は垂直サイズを表します。 先ほど、谷/丘/山の地図が「ランダムすぎる」ように見え、谷または山のより広い領域を作成したいと言ったことを思い出してください。 実際、 低頻度の変動が必要でした。
たとえば、ノイズを発生させる
sin
などの連続関数がある場合、周波数を上げることは、 入力データに何らかの係数を掛けることを意味します
sin(2*x)
は、周波数
sin(x)
を2倍にします。 振幅を大きくするということは、 出力に係数を掛けることを意味します
2*sin(x)
は、
sin(x)
振幅を2倍にします。 上記のコードは、入力に異なる数を掛けることで周波数を変更したことを示しています。 次のセクションでは、複数の正弦波を合計するときに振幅を使用します。
周波数変化

振幅変化

上記はすべて1Dに適用されますが、2Dでも同じことが起こります。 このページの図1をご覧ください 。 長波長(低周波数)と短波長(高周波数)の2Dノイズの例がありますが、周波数が高くなると個々のフラグメントが小さくなることに注意してください。
ノイズ関数の周波数、波長、またはオクターブについて話すとき、正弦波が使用されていなくても、これはまさに意味されています。
正弦波といえば、奇妙な方法でそれらを組み合わせることで面白いことをすることができます。 たとえば、左が低周波数、右が高周波数です。
print_chart(0, [math.sin(0.2 + (i * 0.08) * math.cos(0.4 + i*0.3)) for i in range(mapsize)])
通常、同時に多くの周波数を持つことになり、必要な周波数を選択することに関して誰も正しい答えを与えません。 自問してください:どの周波数が必要ですか? もちろん、答えはそれらの使用方法によって異なります。
6.ノイズの色
ノイズの「色」によって、含まれる周波数の種類が決まります。
すべての周波数が等しくホワイトノイズに影響します 。 谷、丘、山を指定するために1、2、3から選択するときに、すでにホワイトノイズを使用しました。 8つのホワイトノイズシーケンスを次に示します。
for i in range(8): random.seed(i) print_chart(i, [random.uniform(-1, +1) for i in range(mapsize)])
レッドノイズ (ブラウンノイズとも呼ばれます)では、 低周波数がより顕著になります(振幅が大きくなります)。 これは、出力の丘と谷が長くなることを意味します。 レッドノイズは、隣接するホワイトノイズ値を平均することで生成できます。 ホワイトノイズの同じ8つの例がありますが、平均化プロセスが行われます。
def smoother(noise): output = [] for i in range(len(noise) - 1): output.append(0.5 * (noise[i] + noise[i+1])) return output for i in range(8): random.seed(i) noise = [random.uniform(-1, +1) for i in range(mapsize)] print_chart(i, smoother(noise))
これらの8つの例のいずれかをよく見ると、対応するホワイトノイズよりも滑らかであることがわかります。 大きな値または小さな値の間隔は長くなります。
ピンクノイズは白と赤の間です。自然界でしばしば発生し、通常、風景に適しています。大きな丘と谷に加えて、小さな風景の起伏があります。
スペクトルの反対側にはパープルノイズがあります。それより可視で高頻度。パープルノイズは、隣接するホワイトノイズ値の差を取ることで生成できます。以下に、減算処理の対象となるホワイトノイズの同じ8つの例を示します。
def rougher(noise): output = [] for i in range(len(noise) - 1): output.append(0.5 * (noise[i] - noise[i+1])) return output for i in range(8): random.seed(i) noise = [random.uniform(-1, +1) for i in range(mapsize)] print_chart(i, rougher(noise))
8つの例のいずれかをよく見ると、対応するホワイトノイズよりも粗いことがわかります。大きな/小さな値の長い間隔が短く、バリエーションが短い。
ブルーノイズは紫と白の間です。多くの場合、オブジェクトの配置に適しています。密度が高すぎず、密度が低すぎず、ランドスケープ全体にほぼ均一に分布しています。私たちの目の中のロッドとコーンの位置には、ブルーノイズの特性があります。ブルーノイズは、街の素晴らしい景色にも適しています。ウィキペディアには、さまざまな色のノイズを聞くことができるページがあります。
白、赤、紫のノイズを生成する方法を学びました。しかし、私たちにとって最も便利なノイズ機能は、白、ピンク、青です。後でピンクとブルーのノイズを生成しようとします。
要約すると:
- 周波数は、正弦波などの繰り返し信号のプロパティですが、ノイズに使用できます。
- ホワイトノイズが最も簡単です。すべての周波数が含まれています。これらは一様に選択可能な乱数です。
- 赤、ピンク、青、紫は、手続き型生成に使用できる他のノイズ色です。
- ホワイトノイズは赤の平均化に変換できます。
- ホワイトノイズは、減算により紫色に変わります。
7.周波数の組み合わせ
前のセクションでは、ノイズの「周波数」とノイズのさまざまな「色」を調べました。ホワイトノイズは、すべての周波数が存在することを意味します。ピンクと赤のノイズでは、低周波数は高周波数よりも強くなります。青と紫では、高周波数は低周波数よりも強くなります。
適切な周波数応答でノイズを生成する1つの方法は、特定の周波数でノイズを生成する方法を見つけ、それらを結合することです。たとえば
noise
、特定の周波数でノイズを生成するノイズ関数があるとします
freq
。次に、1000 Hzの周波数を2000 Hzの周波数の2倍にしたい場合、他の周波数が存在しない場合は、を使用できます
noise(1000) + 0.5 * noise(2000)
。
私は今それを認めなければなりません
sine
かなりうるさいように見えますが、周波数を指定するのは簡単ですので、それから始めて、どこまで行けるか見てみましょう。
def noise(freq): phase = random.uniform(0, 2*math.pi) return [math.sin(2*math.pi * freq*x/mapsize + phase) for x in range(mapsize)] for i in range(3): random.seed(i) print_chart(i, noise(1))
以上です。基本的な建物のレンガは正弦波で、ランダムな値(位相と呼ばれる)だけ横にシフトします。ここでの唯一の事故は、どれだけ私たちがそれを追放したかです。
いくつかのノイズ関数を組み合わせてみましょう。周波数1、2、4、8、16、32の8つのノイズ関数を組み合わせたい(ノイズ関数によっては、2の累乗はオクターブと呼ばれる)。これらの各ノイズ関数に特定の係数を掛けて(配列を参照
amplitudes
)、それらを合計します。加重合計を計算する方法が必要です。
def weighted_sum(amplitudes, noises): output = [0.0] * mapsize # make an array of length mapsize for k in range(len(noises)): for x in range(mapsize): output[x] += amplitudes[k] * noises[k][x] return output
これで、関数
noise
と新しい関数を使用できます
weighted_sum
:
amplitudes = [0.2, 0.5, 1.0, 0.7, 0.5, 0.4] frequencies = [1, 2, 4, 8, 16, 32] for i in range(10): random.seed(i) noises = [noise(f) for f in frequencies] sum_of_noises = weighted_sum(amplitudes, noises) print_chart(i, sum_of_noises)
ノイズがまったくないように見える正弦波から始めましたが、それらの組み合わせはかなりノイズが多いように見えます。
そして、
[1.0, 0.7, 0.5, 0.3, 0.2, 0.1]
スケールとして使用する場合は?非常に多くの低周波数が使用され、高周波数はまったくありません:

重みとして使用した場合はどうなります
[0.1, 0.1, 0.2, 0.3, 0.5, 1.0]
か?低周波数は非常に軽く、高周波数ではさらに大きくなります。

ここで行ったのは、異なる周波数でのノイズ関数の重み付き合計であり、これは15行未満のコードで済みました。さまざまなノイズスタイルを生成できます。
要約すると:
- 乱数の配列を選択する代わりに、単一の乱数を選択し、それを使用して正弦波を左または右にシフトします。
- 異なる周波数を持つ他のノイズ関数の加重和を取ることにより、ノイズを作成できます。
- 加重合計の重みを選択することにより、ノイズ特性を選択できます。
8.レインボージェネレーション
異なる周波数でノイズを混合してノイズを生成できるようになったので、ノイズの色をもう一度見てみましょう。ノイズカラーに関するウィキペディアのページに
戻りましょう。周波数スペクトルがそこに示されていることに注意してください。彼はノイズに存在する各周波数の振幅について教えてくれます。ホワイトノイズ-フラット、ピンク、赤が下に傾き、青、紫が上がります。周波数スペクトルは、我々の配列と相関していると、前のセクションから。
frequencies
amplitudes
以前は、2のべき乗である周波数を使用していました。さまざまなタイプのカラーノイズにはより多くの周波数があるため、より大きな配列が必要です。このコードでは、2のべき乗(1、2、4、8、16、32)の代わりに、1から30までのすべての整数周波数を使用します。振幅を手動で書き込む代わり
amplitude(f)
に、特定の周波数の振幅を返し、これらのデータから配列を作成する関数を記述します
amplitudes
。
再び関数
weighted_sum
とを使用できます
noise
が、小さな周波数のセットの代わりに、より長い配列になります:
frequencies = range(1, 31) # [1, 2, ..., 30] def random_ift(rows, amplitude): for i in range(rows): random.seed(i) amplitudes = [amplitude(f) for f in frequencies] noises = [noise(f) for f in frequencies] sum_of_noises = weighted_sum(amplitudes, noises) print_chart(i, sum_of_noises) random_ift(10, lambda f: 1)
このコードでは、関数
amplitude
はフォームを定義します。常に1が返される場合、ホワイトノイズが発生しています。他の色のノイズを生成する方法は?同じランダムシードを使用しますが、異なる振幅関数を使用します。
8.1。 レッドノイズ
random_ift(5, lambda f: 1/f/f)
8.2。 ピンクノイズ
random_ift(5, lambda f: 1/f)
8.3。ホワイトノイズ
random_ift(5, lambda f: 1)
8.4。ブルーノイズ
random_ift(5, lambda f: f)
8.5。パープルノイズ
random_ift(5, lambda f: f*f)
8.6。ノイズ色
したがって、これは非常に便利です。単純な形状を得るために、振幅関数の指数を変更できます。
- レッドノイズはf ^ -2
- ピンクノイズはf ^ -1
- ホワイトノイズはf ^ 0
- ブルーノイズはf ^ + 1
- パープルノイズはf ^ + 2
[元の記事] の指数を変更して、セクション8.1〜8.5のノイズが1つの基本関数からどのように生成されるかを確認してください。
要約すると:
- ノイズは、異なる周波数の正弦波の加重和によって生成される可能性があります。
- 異なる色のノイズには、関数f ^ cに対応する重み(振幅)があります。
- 指数を変更することにより、1組の乱数から異なる色のノイズを取得できます。
9.その他の形態のノイズ
異なる色のノイズを生成するために、異なる指数を持つ単純なべき関数に従うように振幅を強制しました。しかし、これらの形式だけに限定されません。これは、対数チャート上に直線で表示される最も単純なパターンです。おそらく、私たちのニーズに合った興味深いパターンを作成する他の周波数のセットがあります。単一の関数を使用する代わりに、振幅の配列を使用し、必要に応じて調整できます。探索する価値はありますが、私はまだやっていません。
前のセクションで行ったことは、フーリエ級数として認識できます。主な考え方は、任意の連続関数を正弦波と余弦の加重和として表すことができるということです。選択した重みに応じて、最終的な関数の外観が変わります。フーリエ変換は、元の関数をその周波数に接続します。通常、ソースデータから開始し、それらから周波数/振幅を取得します。これは、ノイズの「スペクトル」を示す音楽プレーヤーで見ることができます。
直接指示により、データを分析し、頻度を取得できます。逆方向では、周波数からデータを合成できます。ノイズでは、通常合成を行います。実際、すでにこれを行っています。前のセクションでは、周波数と振幅を選択し、ノイズを生成しました。
フーリエ変換には多くの用途があります。
オンこのページフーリエ変換の仕組みの説明があります。このページの図はインタラクティブです-各周波数の強さを入力でき、ページはそれらがどのように結合するかを示します。正弦波を組み合わせることにより、多くの興味深い形状を得ることができます。たとえば、ボックスにCycles inputと入力し
0 -1 0.5 -0.3 0.25 -0.2 0.16 -0.14
、Partsチェックボックスをオフにしてみてください。確かに、山のように見えますか?このページの付録(付録)には、正弦波が極座標でどのように見えるかを示すバージョンがあります。
フーリエ変換を使用してマップを生成する例については、周波数合成によるランドスケープの生成手法を参照してください。Paul Bourkeは、最初に2次元のホワイトノイズを生成し、次にフーリエ変換を使用して周波数に変換し、ピンクノイズの形状を与え、逆フーリエ変換を使用して元に戻します。
2D実験の私の小さな経験は、その中のすべてが1Dほど単純ではないことを示しています。未完成の実験をご覧になりたい場合は、このページの最後までスクロールして、スライダーを動かしてください。
10.その他のノイズ関数
この記事では、正弦波を使用してノイズを生成しました。 とても簡単です。いくつかの関数を取り、それらを要約します。元の関数がノイズを含んでいないように見えても、特に15行のコードしか記述していないことを考えると、結果は十分に見えます。
私は他のノイズ関数を詳細に研究していませんが、私のプロジェクトでそれらを使用しています。それらの多くはピンクノイズを生成すると思います:
- 中点変位では、正弦波の代わりにのこぎり波信号が使用され、振幅が大きくなる周波数と高くなる周波数が合計されます。ピンクノイズに変わると思います。その結果、のこぎり波信号(正弦波ほど滑らかではない)、または2のべき乗である周波数のみの使用により生じる顕著な顔が見られます。よく分かりません。
- Diamond square — midpoint displacement, , midpoint displacement.
- /- . , .
- , () .
- - midpoint displacement. .
- 直接ピンクノイズは、目的の周波数の逆フーリエ変換を計算することで生成できます。これは、前のセクションの例とまったく同じです。ポール・バークはそれを周波数合成と説明し、 3D高さマップを生成する2Dノイズを探す方法を示しています。
Voss-McCartneyアルゴリズムに関するいくつかの情報から、異なる周波数でのノイズの合計はピンクノイズではなく、マップを生成するのに十分近いと考えるようになります。中点変位で受信されたジョイントは、それが原因である可能性が高いか、または補間機能が原因である可能性があります。
ブルーノイズを生成する多くの方法を見つけませんでした。
カードに適切なブルーノイズが必要かどうかさえわかりませんが、これは文献ではブルーノイズとして説明されています。正弦波を使用して生成するブルーノイズは必要なものと似ていますが、上記の手法はゲームに適していると思われます。
11.追加の読み物
この記事は元々自分自身のためのメモでした。私が公開したとき、図を改善し、いくつかのインタラクティブな図を追加しました。他の記事よりもはるかに少ない時間で過ごしましたが、より多くの情報をカバーできるように、いくつかのトピックの説明を試みました。
また、この記事のデータほど洗練されていない2Dの実験もあります。特に、ある二次元高さマップの三次元可視化。
私があまり触れなかった他のトピック:
- 上のページlibnoise補間関数が滑らかデリバティブでなければならない理由の説明を含め、幻想的なノイズの説明、および補間機能を持っています
- , ,
- ,
- green_meklar reddit
- Math/StackExchange
- (Stefan Gustavson) , , , , -
- ,
- (Julius Smith) ,
- Notch' Minecraft — , , ,
- 3D-
- 2D- — 2D- 2D- 4D-