atwiki-logo
  • 新規作成
    • 新規ページ作成
    • 新規ページ作成(その他)
      • このページをコピーして新規ページ作成
      • このウィキ内の別ページをコピーして新規ページ作成
      • このページの子ページを作成
    • 新規ウィキ作成
  • 編集
    • ページ編集
    • ページ編集(簡易版)
    • ページ名変更
    • メニュー非表示でページ編集
    • ページの閲覧/編集権限変更
    • ページの編集モード変更
    • このページにファイルをアップロード
    • メニューを編集
    • 右メニューを編集
  • バージョン管理
    • 最新版変更点(差分)
    • 編集履歴(バックアップ)
    • アップロードファイル履歴
    • ページ操作履歴
  • ページ一覧
    • ページ一覧
    • このウィキのタグ一覧
    • このウィキのタグ(更新順)
    • おまかせページ移動
  • RSS
    • このウィキの更新情報RSS
    • このウィキ新着ページRSS
  • ヘルプ
    • ご利用ガイド
    • Wiki初心者向けガイド(基本操作)
    • このウィキの管理者に連絡
    • 運営会社に連絡(不具合、障害など)
ページ検索 メニュー
ゲームプログラミングというゲームを攻略するWIKI
  • ウィキ募集バナー
  • 目安箱バナー
  • 操作ガイド
  • 新規作成
  • 編集する
  • 全ページ一覧
  • 登録/ログイン
ページ一覧
ゲームプログラミングというゲームを攻略するWIKI
  • ウィキ募集バナー
  • 目安箱バナー
  • 操作ガイド
  • 新規作成
  • 編集する
  • 全ページ一覧
  • 登録/ログイン
ページ一覧
ゲームプログラミングというゲームを攻略するWIKI
ページ検索 メニュー
  • 新規作成
  • 編集する
  • 登録/ログイン
  • 管理メニュー
管理メニュー
  • 新規作成
    • 新規ページ作成
    • 新規ページ作成(その他)
      • このページをコピーして新規ページ作成
      • このウィキ内の別ページをコピーして新規ページ作成
      • このページの子ページを作成
    • 新規ウィキ作成
  • 編集
    • ページ編集
    • ページ編集(簡易版)
    • ページ名変更
    • メニュー非表示でページ編集
    • ページの閲覧/編集権限変更
    • ページの編集モード変更
    • このページにファイルをアップロード
    • メニューを編集
    • 右メニューを編集
  • バージョン管理
    • 最新版変更点(差分)
    • 編集履歴(バックアップ)
    • アップロードファイル履歴
    • ページ操作履歴
  • ページ一覧
    • このウィキの全ページ一覧
    • このウィキのタグ一覧
    • このウィキのタグ一覧(更新順)
    • このページの全コメント一覧
    • このウィキの全コメント一覧
    • おまかせページ移動
  • RSS
    • このwikiの更新情報RSS
    • このwikiの新着ページRSS
  • ヘルプ
    • ご利用ガイド
    • Wiki初心者向けガイド(基本操作)
    • このウィキの管理者に連絡
    • 運営会社に連絡する(不具合、障害など)
  • atwiki
  • ゲームプログラミングというゲームを攻略するWIKI
  • パーリンノイズ

ゲームプログラミングというゲームを攻略するWIKI

パーリンノイズ

最終更新:2021年03月26日 19:59

from0

- view
メンバー限定 登録/ログイン

パーリンノイズってのはゲーム画面で「もくもく」してるアレだ。 雲とか霧とか。 実はちょっと加工すれば地形とかにも使えるスグレモノだ。

イカしたソースを紹介するぜ!

  • ケン・パーリン先生によるリファレンス実装 https://mrl.cs.nyu.edu/~perlin/noise/
  • 英語版Wikipediaの解説つき実装 https://en.wikipedia.org/wiki/Perlin_noise

問題はこの2つが、書き方の違いのせいで大きく違って見えることだ。重要な違いはそれほど無い。 解りやすくなるように、パーリン先生のロジックをWikipediaスタイルで書いてみる。

#include <math.h>
 
static int p[] = {
	151,160,137,91,90,15,
	131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
	190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
	88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
	77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
	102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
	135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
	5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
	223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
	129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
	251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
	49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
	138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180
};
 
double interpolate(double a0, double a1, double w) {
    return (a1 - a0) * w + a0;
}
 
double fade(double t) {
	return t * t * t * (t * (t * 6 - 15) + 10);
}
 
typedef struct {
    double x, y, z;
} vector3;
 
vector3 randomGradient(int ix, int iy, int iz) {
	switch (p[(p[(p[ix & 255] + iy) & 255] + iz) & 255] & 15) {
	case 0: return (vector3) { .x = +1, .y = +1, .z = 0 };
	case 1: return (vector3) { .x = -1, .y = +1, .z = 0 };
	case 2: return (vector3) { .x = +1, .y = -1, .z = 0 };
	case 3: return (vector3) { .x = -1, .y = -1, .z = 0 };
	case 4: return (vector3) { .x = +1, .y = 0, .z = +1 };
	case 5: return (vector3) { .x = -1, .y = 0, .z = +1 };
	case 6: return (vector3) { .x = +1, .y = 0, .z = -1 };
	case 7: return (vector3) { .x = -1, .y = 0, .z = -1 };
	case 8: return (vector3) { .x = 0, .y = +1, .z = +1 };
	case 9: return (vector3) { .x = 0, .y = -1, .z = +1 };
	case 10: return (vector3) { .x = 0, .y = +1, .z = -1 };
	case 11: return (vector3) { .x = 0, .y = -1, .z = -1 };
	case 12: return (vector3) { .x = +1, .y = +1, .z = 0 };
	case 13: return (vector3) { .x = 0, .y = -1, .z = +1 };
	case 14: return (vector3) { .x = -1, .y = +1, .z = 0 };
	default: return (vector3) { .x = 0, .y = -1, .z = -1 };
	}
}
 
double dotGridGradient(int ix, int iy, int iz, double x, double y, double z) {
	vector3 gradient = randomGradient(ix, iy, iz);
 
    double dx = x - (double)ix;
    double dy = y - (double)iy;
    double dz = z - (double)iz;
 
	return (dx*gradient.x + dy*gradient.y + dz*gradient.z);
}
 
double perlin(double x, double y, double z) {
	int x0 = (int)x;
	int x1 = x0 + 1;
	int y0 = (int)y;
	int y1 = y0 + 1;
	int z0 = (int)z;
	int z1 = z0 + 1;
 
	double sx = fade(x - x0);
	double sy = fade(y - y0);
	double sz = fade(z - z0);
 
    double n0, n1, ix0, ix1, iy0, iy1, value;
 
	n0 = dotGridGradient(x0, y0, z0, x, y, z);
	n1 = dotGridGradient(x1, y0, z0, x, y, z);
	ix0 = interpolate(n0, n1, sx);
 
	n0 = dotGridGradient(x0, y1, z0, x, y, z);
	n1 = dotGridGradient(x1, y1, z0, x, y, z);
	ix1 = interpolate(n0, n1, sx);
 
	iy0 = interpolate(ix0, ix1, sy);
 
	n0 = dotGridGradient(x0, y0, z1, x, y, z);
	n1 = dotGridGradient(x1, y0, z1, x, y, z);
	ix0 = interpolate(n0, n1, sx);
 
	n0 = dotGridGradient(x0, y1, z1, x, y, z);
	n1 = dotGridGradient(x1, y1, z1, x, y, z);
	ix1 = interpolate(n0, n1, sx);
 
	iy1 = interpolate(ix0, ix1, sy);
 
	value = interpolate(iy0, iy1, sz);
	return value;
}

要するにパーリンノイズは

  1. キリ番の座標毎に単位ベクトル(gx, gy,...)をランダムな向きで生成する。これは勾配ベクトルと呼ばれる。
  2. 各座標の最寄りのキリ番座標4つに対して、勾配ベクトルと相対座標(dx, dy,...)のドット積(dx*gx + dy*gy +...)を求める。
  3. 4つのドット積を補間して値を求める。

というのが基本で、アルゴリズムの違いは

  • 先生のは値がdouble、Wikipediaのは値がfloat。
  • 先生のは3次元、Wikipediaのは2次元。
  • 疑似乱数の作り方が違う。
  • 先生のはfade()とかいう関数を用意して補間に使ってるけど、Wikipediaのはリニアに補間。

パーリン先生のは擬似乱数下位4bitを12方向に変換してるから、ちょっと偏りがある。そんなんでいいのか。

Wikipediaのはプログラマブルシェーダにパーリンノイズを生成させることを意識してるのかもしれない。特に疑似乱数の作り方とか。

「パーリンノイズ」をウィキ内検索
LINE
シェア
Tweet
ゲームプログラミングというゲームを攻略するWIKI
記事メニュー

メニュー

  • トップページ
  • プラグイン紹介
  • メニュー
  • 右メニュー



リンク

  • @wiki
  • @wikiご利用ガイド




ここを編集
記事メニュー2
最近更新されたページ
  • 1466日前

    点と移動する線分の交点
  • 1525日前

    凸体と線分の交差
  • 1527日前

    平面と点の距離
  • 1527日前

    平面と線分の交点
  • 1533日前

    線分と線分の距離
  • 1561日前

    動的に読み込まれたSharedObjectからC++を利用する
  • 1561日前

    C++から動的に読み込まれたSharedObjectを利用する
  • 1570日前

    C++でほぼほぼプロパティ
  • 1570日前

    線分と点の距離
  • 1571日前

    点と点の距離
もっと見る
最近更新されたページ
  • 1466日前

    点と移動する線分の交点
  • 1525日前

    凸体と線分の交差
  • 1527日前

    平面と点の距離
  • 1527日前

    平面と線分の交点
  • 1533日前

    線分と線分の距離
  • 1561日前

    動的に読み込まれたSharedObjectからC++を利用する
  • 1561日前

    C++から動的に読み込まれたSharedObjectを利用する
  • 1570日前

    C++でほぼほぼプロパティ
  • 1570日前

    線分と点の距離
  • 1571日前

    点と点の距離
もっと見る
ウィキ募集バナー
新規Wikiランキング

最近作成されたWikiのアクセスランキングです。見るだけでなく加筆してみよう!

  1. 鹿乃つの氏 周辺注意喚起@ウィキ
  2. 機動戦士ガンダム EXTREME VS.2 INFINITEBOOST wiki
  3. MadTown GTA (Beta) まとめウィキ
  4. R.E.P.O. 日本語解説Wiki
  5. AviUtl2のWiki
  6. シュガードール情報まとめウィキ
  7. ソードランページ @ 非公式wiki
  8. ドラゴンボール Sparking! ZERO 攻略Wiki
  9. シミュグラ2Wiki(Simulation Of Grand2)GTARP
  10. Dark War Survival攻略
もっと見る
人気Wikiランキング

atwikiでよく見られているWikiのランキングです。新しい情報を発見してみよう!

  1. アニヲタWiki(仮)
  2. ストグラ まとめ @ウィキ
  3. ゲームカタログ@Wiki ~名作からクソゲーまで~
  4. 初音ミク Wiki
  5. 機動戦士ガンダム バトルオペレーション2攻略Wiki 3rd Season
  6. 検索してはいけない言葉 @ ウィキ
  7. 発車メロディーwiki
  8. オレカバトル アプリ版 @ ウィキ
  9. Grand Theft Auto V(グランドセフトオート5)GTA5 & GTAオンライン 情報・攻略wiki
  10. ニコニコMUGENwiki
もっと見る
全体ページランキング

最近アクセスの多かったページランキングです。話題のページを見に行こう!

  1. 参加者一覧 - ストグラ まとめ @ウィキ
  2. コメント/雑談・質問 - マージマンション@wiki
  3. マイティーストライクフリーダムガンダム - 機動戦士ガンダム EXTREME VS.2 INFINITEBOOST wiki
  4. ブラック ジャックス - ストグラ まとめ @ウィキ
  5. マリオカート ワールド - アニヲタWiki(仮)
  6. 過去の行動&発言まとめ - 鹿乃つの氏 周辺注意喚起@ウィキ
  7. 前作からの変更点 - 機動戦士ガンダム EXTREME VS.2 INFINITEBOOST wiki
  8. 魔獣トゲイラ - バトルロイヤルR+α ファンフィクション(二次創作など)総合wiki
  9. ギャルがアップした動画 - 検索してはいけない言葉 @ ウィキ
  10. 猗窩座(鬼滅の刃) - アニヲタWiki(仮)
もっと見る

  • このWikiのTOPへ
  • 全ページ一覧
  • アットウィキTOP
  • 利用規約
  • プライバシーポリシー

2019 AtWiki, Inc.