LoginSignup
210
92

More than 3 years have passed since last update.

雲のプロシージャル生成 - パーリンノイズアルゴリズム

Last updated at Posted at 2019-07-29

☁母なる大空を創造する☁

PN512

今回はパーリンノイズ法を用いた雲の生成について簡単に解説します。

☁パーリンノイズとは☁

"パーリンノイズ"はオブジェクトの生成に適した"ノイズアルゴリズム"です。
あの超有名なゲームである"マインクラフト"でも使われています。

mcp
ゲームで使用されるパーリンノイズの例

☁以前紹介した生成の応用☁

[DTL]地形生成(パーリンノイズ法)🌏
で紹介したパーリンノイズ法による地形自動生成を応用して雲を作っていきます。

pib

☁雲を作るために必要なモノ☁

雲の生成には
"雲の厚さ"といった単純な変数を使います。

PN512
"雲の厚さ"は0から512までの値を取り、
厚さごとに色を変えます。

0の時は青色、256の時は白色、512の時は灰色に近い色に変化させます。

☁雲変数を定義☁

main関数
constexpr float cloud_p{ 0.75f };
constexpr float sky_p{ 0.25f };
using shape_t = std::uint_fast16_t;
std::unique_ptr<shape_t[][512]> matrix(new(std::nothrow) shape_t[512][512]);

for (std::size_t row{}; row < 512; ++row)
 for (std::size_t col{}; col < 512; ++col)
  matrix[row][col] = (shape_t)row;

dtl::storage::FilePNG<shape_t>("file_cloud.png", 3).write(matrix,512,512, [](const shape_t value, unsigned char* const color) {
 if (value > 255) {
  color[0] = static_cast<char>((230 + ((39 - 244) * (value - 256.0f) / 523.0f)) * cloud_p + 16 * sky_p);
  color[1] = static_cast<char>((235 + ((45 - 244) * (value - 256.0f) / 523.0f)) * cloud_p + 123 * sky_p);
  color[2] = static_cast<char>((245 + ((57 - 244) * (value - 256.0f) / 523.0f)) * cloud_p + 219 * sky_p);
 }
 else {
  color[0] = static_cast<char>((16 + ((255 - 16) * value / 255.0f)) * (1.0f - value / (255.0f * 12)) * cloud_p + 16 * sky_p);
  color[1] = static_cast<char>((123 + ((255 - 123) * value / 255.0f)) * (1.0f - value / (255.0f * 12)) * cloud_p + 123 * sky_p);
  color[2] = static_cast<char>((219 + ((255 - 219) * value / 255.0f)) * (1.0f - value / (255.0f * 12)) * cloud_p + 219 * sky_p);
 }
 });

PN512
"雲の厚さを変化させていきます。
次はこのグラデーションをパーリンノイズに適応していきましょう。

☁雲を生成☁

main関数
constexpr std::size_t size_x{ 512 };
constexpr std::size_t size_y{ 512 };
constexpr float cloud_p{ 0.75f };
constexpr float sky_p{ 0.25f };

constexpr double frequency{ 500 };
constexpr std::size_t octaves{ 8 };
constexpr std::uint_fast32_t seed{ 4 };

constexpr double frequency_x{ frequency };
constexpr double frequency_y{ frequency };

std::unique_ptr<float[][size_x] > elevation(new(std::nothrow) float[size_y][size_x]);
const dtl::utility::PerlinNoise perlin3(seed);

for (std::size_t row{}; row < size_y; ++row)
 for (std::size_t col{}; col < size_x; ++col)
  elevation[row][col] = static_cast<float>(1000.0 * perlin3.octaveNoise(octaves, (col) / frequency_x, (row) / frequency_y)) - 500.0f;

dtl::storage::FilePNG<float>("cloud.png", 3).write(elevation, 512, 512, [](float value, unsigned char* const color) {
 if (value < 0) value = 0;
 if (value > 255) {
  color[0] = static_cast<char>((230 + ((39 - 244) * (value - 256.0f) / 523.0f)) * cloud_p + 16 * sky_p);
  color[1] = static_cast<char>((235 + ((45 - 244) * (value - 256.0f) / 523.0f)) * cloud_p + 123 * sky_p);
  color[2] = static_cast<char>((245 + ((57 - 244) * (value - 256.0f) / 523.0f)) * cloud_p + 219 * sky_p);
 }
 else {
  color[0] = static_cast<char>((16 + ((255 - 16) * value / 255.0f)) * (1.0f - value / (255.0f * 12)) * cloud_p + 16 * sky_p);
  color[1] = static_cast<char>((123 + ((255 - 123) * value / 255.0f)) * (1.0f - value / (255.0f * 12)) * cloud_p + 123 * sky_p);
  color[2] = static_cast<char>((219 + ((255 - 219) * value / 255.0f)) * (1.0f - value / (255.0f * 12)) * cloud_p + 219 * sky_p);
 }
 });

数値通りに雲の厚さを変えます。

PN512
"雲の厚さ"を用いて作成した空。

☁完成☁

無事に実装できました。

PN512

☁実装ライブラリ(ソースコード)☁

今回解説した雲の生成は"Dungeon Template Library""PerlinIsland"として実装されています。
ぜひ、活用してみてください!

logo640.gif

☁ソースコードのライセンス☁

These codes are licensed under CC0.
CC0

この記事のソースコードはCC0ライセンスとします。
ぜひ、自由に改変して遊んでみてください。

"いいね"をつけてくださると大変励みになります。
最後までお読みいただきありがとうございました!

210
92
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
210
92