ビジュアルプログラミング的にBlenderのマテリアルを考える テラゾータイル編

## この記事の概要

`プロシージャルテクスチャ`をご存知でしょうか。
3DCGで`テクスチャ`というと、`物体の質感を再現するために、3Dデータに貼り付ける画像`と捉えることが多いです。
ですが、昨今の3DCGソフトでは計算により質感を再現する手段もあり、それが`プロシージャルテクスチャ`です。

そして、Blenderにおけるプロシージャルテクスチャ作りが実質ビジュアルプログラミングである[^3dcg-software-other-than-blender]ことに気がつきました。

[^3dcg-software-other-than-blender]: Blender以外の3DCGソフトを使ったことがないため、他のソフトがどうなのかは分かりません。Blenderのご了承ください。

というわけで、エンジニアとプロシージャルテクスチャは親和性が高いと考え、試しにQiitaにて記事にしてみました。

今回は[テラゾータイル](https://www.google.com/search?q=terrazzo)と呼ばれる人工大理石風のテクスチャを作成します。

完成形は次のような見た目です。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/26caad6b-b229-0536-9d5a-edd2e959e830.png" alt="" width="400">

## 環境

Blenderのバージョンは`3.5.0`です。

## 制作

まずはテクスチャの適用先として`Sphere`と`Plane`を配置します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/c1070398-a251-77c1-db56-6dd1cd891939.png" alt="" width="400">

次に`Shader Editor`を開き、Materialの編集に入ります。
最初はこのようになっていると思います。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/cfac54fd-045b-4100-eee9-57ca19894518.png)

`RGB`ノードを追加し、`Principled BSDF`の`Base Color`へ繋ぎます。
ここでは色を`#569D6B`にしました。

現段階ではノードを追加する意味はないのですが、この後模様を増やすときにやりやすいため、追加しています。
特定の連想配列の中身を毎回取得するのは面倒だから変数として宣言しておく、みたいなイメージで捉えてください。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/dc361ef4-dfd7-1276-6703-cdd90ea93d2a.png)

現時点ではこうなります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/e8da19fe-1e9f-f515-1c64-4d089ebf6fe5.png" alt="" width="400">

次は、以下の工程を一気に説明します。

- `Volonoi Texuture`と`Mapping`と`Texuture Coordinate`を追加し、それぞれをつなぐ
    - `Node Wrangler`を有効にしている場合、`Volonoi Texuture`を選択して`Ctrl + T`を押すだけでOK
    - このとき`Texuture Coordinate`は`Object`ソケットから引っ張るようにする
- 先ほど追加した`RGB`と`Volonoi Texuture`を`Mix`で合成する
    - `Node Wrangler`を有効にしている場合、2つのノードを`Ctrl + Shift + 右ドラッグ`でなぞるだけでOK

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/224d1de3-751c-38e4-9df5-c273602a49f8.png)

現時点ではこうなります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/044ab5bc-2ddf-a8b3-973c-f0a87c900f7d.png" alt="" width="400">

以下の2つのテクスチャを、`Mix`によって50%ずつ重ね合わせているため、このような模様ができあがります。
`Mix`は、2つの引数を合成してreturnする関数と捉えてください。

ちなみにFactorが0だとAのソケットの色、1だとBのソケットの色、0.5だと50%ずつ混ざります。
この仕組みも後に使用します。

| RGB | Volonoi Texuture |
| --- | --- |
| <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/e8da19fe-1e9f-f515-1c64-4d089ebf6fe5.png" alt="" width="400"> | <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/6f91da81-996c-d56c-98c8-17fc2d6beda5.png" alt="" width="400"> |

次に、`Volonoi Texuture`の設定を`F1`から`N-Sphere Radius`に変え、`Scale`を40とします。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/0fb71942-0039-7526-c7cd-e87ec228ece5.png)

これにより合成結果も変わります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/80ba1dc4-5880-9d41-1d14-cf6a98757cf9.png" alt="" width="400">

次に`Volonoi Texuture`と`Mix`の間に`ColorRamp`を挟みます。

- グラデーションの仕方を`Linear`から`Constant`に変える
- バーの左側の色を以下に変える
    - H:0, S:0, V:1, A:0
    - Position:0.000
- バーの右側の色を以下に変える
    - Hex:C4D9DA
    - Position:0.450
- `ColorRamp`の`Alpha`を`Mix`の`Factor`につなぐ

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/51f2e06c-a2b4-6f1c-3bd3-91abc3d91309.png)

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/aba6c05b-9eb6-8478-325f-0e1599dd7503.png" alt="" width="400">

仕組みは次のようになっています。

`ColorRamp`は、あるグラデーションを別のグラデーションに置き換えるようなものです。
配列を受け取ったら処理を加えて別な配列を返す、mapな関数に近いでしょうか。

今回は、閾値より明るいなら透明（H:0, S:0, V:1, A:0）に、暗いなら`#C4D9DA`とバッサリ分けていたためこのように2値化されました。

| 元々 | ColorRampによる変換後 |
| --- | --- |
| <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/b968213c-7c82-90ec-91ef-0216ff781b89.png" alt="" width="400"> | <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/e52ec745-64f0-0212-98b5-7c11fdf58d93.png" alt="" width="400"> |

また、`ColorRamp`の`Alpha`ソケットが出力するのは透明度の分布です。
透明が0で不透明が1のため、それが白黒に置き換わり、このような柄が生成されます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/f27a4027-3e5a-be43-6eb3-4dd8c4344ca4.png" alt="" width="400">

この白黒の分布を`Mix`の`Factor`に繋ぐことにより、以下のように合成されます。

- `Volonoi Texuture`の図柄がある場所 = 白黒の白 = `Factor`が1 = `Volonoi Texuture`につないだ`ColorRamp`で指定した色が描画される
- それ以外 = 白黒の黒 = `Factor`が0 = `RGB`で指定した色が描画される

つまり、`#569D6B`をベース色に、`#C4D9DA`の模様が描かれます。

ここから色を足すには同じ仕組みを繰り返せば良いだけです。
`Volonoi Texuture`と`ColorRamp`を複製し以下のように設定を変え、もう1つ`Mix`を繋ぎます。

- `Volonoi Texuture`
    - Scale:50.000
- `ColorRamp`
    - Hex:2C6358
    - Position:0.480

`Scale`や`Position`は実際に作るオブジェクトを見ながら触るようなパラメーターです。
載せてはいますが、参考程度に見てもらえれば問題ありません。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/12c23165-d1f2-a001-98c5-7b1b43f41dc9.png)

白っぽい柄だけでなく、少し濃い緑の柄も加わりました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/9c3eaffb-bd66-bae5-8737-4b5e6ae577f6.png" alt="" width="400">

表情を増やすため、もう1つ色を追加します。

- `Volonoi Texuture`
    - Scale:60.000
- `ColorRamp`
    - Hex:050F12
    - Position:0.510

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/b854f1b2-0e5d-38c6-758b-22d23f06d461.png)

かなり暗い色の柄が増えました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/4a6835b9-1df2-b040-b1b0-544502271d61.png" alt="" width="400">

ここで終わっても良いですが、今だと単に色を塗り分けたように見えるので、もう一手間加えてみます。
ベース色の部分と、柄の部分とでツヤツヤ感を変えて、柄の部分を少しだけ凹ませましょう。

仕組み的には先ほどまでと変わりません。

- 追加した2つの`Mix`
    - `ColorRamp`の`Alpha`を合成し、柄がある部分すべてを足し合わせた形状を取得
- `ColorRamp`
    - `Roughness`は値が小さい方がツヤツヤで、大きいとマットになる
    - `Alpha`の白黒に、それぞれ違う値を指定して材質の違いを表現する
    - `Roughness`につなげる
- `Bump`
    - 表面に凹凸をつける
    - 今のままだと柄の部分が飛び出るので、`Invert`にチェックを入れて、`Strength`を少し下げる
    - `Normal`につなげる

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/fab03b78-69a3-2229-7ef4-ff833ca11bee.png)

これで、冒頭に示したものと同じテクスチャが完成しました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/26caad6b-b229-0536-9d5a-edd2e959e830.png" alt="" width="400">

## 最後に

理屈上の正しさというより「結果論でいい感じの見た目になっている」ようなテクスチャもたまに見かけます。
もちろん問題はありませんが、コードと同じで将来のバグの危険性を含んでいると言えるでしょう。

不要なノードを減らし、入出力の理屈をシンプルにしたい……と考えている最中に「コードを書いているときと同じような脳の使い方をしている」と気づきました。
そのため、もしかしてエンジニアの皆さんの方がテクスチャ作りが上手いのかもしれない、と思い半ば実験的に投稿してみました。

あと、一連の変化を載せておきます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/c1070398-a251-77c1-db56-6dd1cd891939.png" alt="" width="400">

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/e8da19fe-1e9f-f515-1c64-4d089ebf6fe5.png" alt="" width="400">

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/044ab5bc-2ddf-a8b3-973c-f0a87c900f7d.png" alt="" width="400">

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/80ba1dc4-5880-9d41-1d14-cf6a98757cf9.png" alt="" width="400">

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/aba6c05b-9eb6-8478-325f-0e1599dd7503.png" alt="" width="400">

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/9c3eaffb-bd66-bae5-8737-4b5e6ae577f6.png" alt="" width="400">

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/4a6835b9-1df2-b040-b1b0-544502271d61.png" alt="" width="400">

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/26caad6b-b229-0536-9d5a-edd2e959e830.png" alt="" width="400">

---

最後まで読んでくださってありがとうございます！
[Twitter](https://twitter.com/xrxoxcxox)でも情報を発信しているので、良かったらフォローお願いします！

[Devトーク](https://jobs.qiita.com/employers/qiita-inc/dev_talks/489)でお話してくださる方も募集中です！