Help us understand the problem. What is going on with this article?

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

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

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ライセンスとします。
ぜひ、自由に改変して遊んでみてください。

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

Gaccho
人は死ぬ。しかし、その人の行為は生き続ける。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away