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

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

![PN512](https://kasugaccho.github.io/DungeonPicture/Picture/Sky/cloud_move20.gif)

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

# ☁パーリンノイズとは☁

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

![mcp](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213065/77c3394b-40e5-5bb4-c800-d4f1f6f68c5a.png)
**ゲームで使用されるパーリンノイズの例**

# [☁以前紹介した生成の応用☁](https://qiita.com/Gaccho/items/ba7d715901a0e572b0e9)

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

[![pib](https://Kasugaccho.github.io/DungeonPicture/Picture/Terrain/PIB256.gif)](https://github.com/Kasugaccho/DungeonTemplateLibrary/wiki/dtl::shape::PerlinIsland-(%E5%BD%A2%E7%8A%B6%E3%82%AF%E3%83%A9%E3%82%B9))

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

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

![PN512](https://kasugaccho.github.io/DungeonPicture/Picture/Sky/cloud0_512.png)
**"雲の厚さ"**は0から512までの値を取り、
厚さごとに色を変えます。

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

# ☁雲変数を定義☁

```cpp: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](https://kasugaccho.github.io/DungeonPicture/Picture/Sky/cloud0_512_256.png)
**"雲の厚さを変化させていきます。**
次はこのグラデーションをパーリンノイズに適応していきましょう。

# ☁雲を生成☁

```cpp: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](https://kasugaccho.github.io/DungeonPicture/Picture/Sky/cloud512.png)
**"雲の厚さ"を用いて作成した空。**

# ☁完成☁

無事に実装できました。

![PN512](https://kasugaccho.github.io/DungeonPicture/Picture/Sky/cloud_move20.gif)

# [☁実装ライブラリ(ソースコード)☁](https://github.com/Kasugaccho/DungeonTemplateLibrary)

今回解説した雲の生成は**["Dungeon Template Library"](https://github.com/Kasugaccho/DungeonTemplateLibrary)**に**["PerlinIsland"](https://github.com/Kasugaccho/DungeonTemplateLibrary/blob/master/include/DTL/Shape/PerlinIsland.hpp)**として実装されています。
ぜひ、活用してみてください！

[![logo640.gif](https://kasugaccho.github.io/DungeonPicture/Picture/Logo/logo_color640_3.gif)](https://github.com/Kasugaccho/DungeonTemplateLibrary)

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

These codes are licensed under CC0.
[![CC0](https://mirrors.creativecommons.org/presskit/buttons/88x31/svg/cc-zero.svg "CC0")](http://creativecommons.org/publicdomain/zero/1.0/deed.ja)

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

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