すみません、美少女の体内に異世界を作りたいです【Unityシェーダー物語】

はじめまして。こんにちは。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2722480/776cbc7b-d31c-e10c-63f3-6778e37da92a.png)
てみずと申します。普段はゲームをしたり漫画を読んだりしています。
さて、今回は―――
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2722480/9c69f063-1107-94f1-26e1-7b3d29f0188b.png)
あ～！美少女だ～！
グググッ…。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2722480/a338b7a5-82fd-6ed7-9d8c-7516a896b605.png) 
### ズボッ！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2722480/2d4f0f36-c048-57e0-9573-b10967e312c6.png)
ああ…。美少女の体内（異世界）に入ってしまった…。<br>
<br>
そういう話です。
<details><summary>注意</summary>

当記事は<b>「読みやすさ100%」</b>です。細かいことは最後の「参考資料」を参照してください。
また、本内容は全く違うローカルな場所に寄稿したことがあります。今回はその<b>リニューアル版</b>となっています。「この記事、どこかで…」と思ったとしても何も言わないでいただければ幸いです！（個人情報モロバレしてしまうため！）
じゃあ、行きましょう！
</details>

# 1. VRChatというのがあります【動機】
VRChatというのがあります。無料。
![VRC_Logo_TrademarkWhite.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2722480/365d70e3-bf73-eac3-6a5c-472a77bfd208.png)
SNSの1つです。無料。
“VR“という名前なのにVR機器は不要です。無料。
参考となる紹介記事を置いておくので、ぜひとも読んでみてください。
「アニメの美少女になったら、[えちえち相撲](https://omocoro.jp/kiji/171201/ "【漫画】VR空間でメチャクチャになった")を仕掛けられた」という体験が読めます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2722480/98384ff1-9357-8dc1-65fd-18726311b0cc.png)
本題はこれからです。このVRChatではアバターを自分で変えることができます。そのためにゲームエンジン「Unity」を利用します。
私もUnityで作業をしていました。そんなある日…。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2722480/e7af2fdb-efd8-848f-1072-57e7fdacdc36.png)
てみず「むへへ…。美少女は今日もかわいいなあ」
てみず「せや！中身ってどうなってるんや！？」
グググッ…
ズボッ！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2722480/1f8389f7-6f18-6f65-4845-e5a8fc80c3b3.png)
# ？
不思議な光景です。説明します。
一般的な人物の3Dモデルでは、外面だけしか見ることがありません。それなのに中まで作り込むと、余計な処理が必要となります。したがって中は空洞。見えるのはめり込んだ服や装飾品だけです。

てみず「………！…？…<b>！</b>？！？？…<b>？？？</b>…！？！？？<b>！</b>？<b>！</b>？<b>！？</b>」

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2722480/1d938a61-4b9d-2aa6-6db1-63368ff7b4ed.png)

ということでやっていきます。

# 2. この記事の読み方【態度】
雰囲気で読んで下さい。というのも、新しいことが多いので難しいです。
末尾に参考資料を用意しています。詳しく知りたければ、そちらを参照してください。
また、[完成品](https://ts-ms.booth.pm/items/3959699 "【VRChat向け】体内\"異界\"シェーダー")を配布しています。
このコードの詳しい理解をしたければ本記事と読み比べることを推奨します。

# 3. 異世界の準備【前提】
・Unity [2019.4.31f1]（バージョンはある程度最新なら不問）
・コードエディタ（Visual Studio Codeなど）
・任意の3Dモデル（Unity上で追加できるただの立方体でも、無料の人物3Dモデルでも）
・VRChat（動作確認に使える）

# 4. 異世界の知識【理論】
Unity上で表面や裏面の描画をするにはHLSL言語を使います。
文法はC++に似ています。
## (1-1) レイトレーシング
異世界を描く方法です。光の挙動をトレースすることで描画する技法です。「レイトレーシング」と呼びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2722480/5aff9497-4bc1-dae6-5363-a0de31a71d78.png)
(1) 始点から一番近い物体までの距離を算出します。
(2) レイ（視線）に沿って(1)の距離だけ進行します。
(3) その点から一番近い物体までの距離を算出します。
(4) レイに沿って(3)の距離だけ進行します。(3)に戻ります。

必要なのは<b>物体の位置関係</b>です。そこで「距離関数」があります。

## (1-2) 距離関数
これはオブジェクトまでの最短距離を返す関数です。すなわち、オブジェクトの形を決定する関数です。この設計が非常に重要です。
以下は距離関数の一例です。球を表します。
```HLSL
const float sphereSize = 1.0;	// 球の半径を1.0と定義する

float distanceFunction(float3 p){ 	//以下は距離関数
    return length(p) - sphereSize; 	//”pのベクトルの長さ - sphereSize”を返す
}
```
現在の位置が三次元ベクトルpとして与えられています。
仮に、カメラが(0,0,3)にあると仮定しましょう。すなわちベクトルpは(0,0,3)です。長さは3です。ここで距離関数を呼び出すと、返り値は2です。これは確かにカメラと球面の最短距離です。
このようにして距離関数があります。

## (2) 裏面判定
この世にはカリングがあります。これは物体の裏面を透明にする機能です。余計な処理を省き、負荷を削減します。
では、裏面を”別の処理”をしたいときどうすればいいでしょうか。答えは単純で、法線を用います。
facingという引数を追加することで、ポリゴンの向きを判定することが可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2722480/527b7639-15fb-6266-bc86-be0ef8ee7890.png)
<small>([https://nn-hokuson.hatenablog.com/entry/2018/02/20/203511](https://nn-hokuson.hatenablog.com/entry/2018/02/20/203511)より引用)</small>
これで裏表が判定できます。

## (3) ランバート反射
月が太陽に照らされて初めて見えるように、光が物体で反射しないとUnity上では物体が見えません。単色で塗りつぶせば、のっぺりと見えます。そのため、今回は「ランバート反射」という反射モデルを用います。
これは「ランベルトの余弦則」に裏付けられています。
<details><summary>ランベルトの余弦則</summary>

『光学におけるランベルトの余弦則（ランベルトのよげんそく）は、理想的な拡散反射面や拡散放射体で観測される放射強度あるいは光度が、入射光と面の法線との間の角度θの余弦と正比例することを示す法則である』（フリー百科事典『ウィキペディア（Wikipedia）』より引用）

</details>

難しそうですが、直感的です。要はこうです。
<b>「正面から光があたってたらめっちゃ明るい！！」</b>。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2722480/a143cadb-6062-c5d5-15af-7c7be3384502.png)
([https://yttm-work.jp/computer_graphics/computer_graphics_0004.html](https://yttm-work.jp/computer_graphics/computer_graphics_0004.html)より引用)

# 5. 終わりに【最後】
ということで美少女の体内に異世界を生成することに成功しました。ありがとうございます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2722480/3682a651-b790-2a15-26a7-8d05953217de.png)
私はこの夏をすべて費やしました。私はただ一つ。このためだけに。
私の甘酸っぱい青春はこれで終わりです。終わってしまったのです。すべて。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2722480/0dcccb05-c070-ba73-0e6e-c9cc90d84b69.png)
画面の向こう側の美少女の体内を想像していたら。
ずっとディスプレイばかり見て、手を伸ばすことさえせず、浅い睡眠にすがっていた。
何も無く。
漫然と過ごしていたら、
すべてが終わってしまったのです。
本当に、すべてが。
何もかもが、終わったんだ。
………。
……………。
………………………………………。
………………………………………………………………………………。
……………………………………………………………………………………………………………………。
………………………………………………………………………………………………………………………………………………………。
…………………………………………………………………………………………………………………………………………………………………………………………………………………。
………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2722480/e5cbf248-eab6-2483-b335-459b2702a6b7.png)
悔いはありません。それではみなさん、さようなら。

# 6. 詳しい説明【参考資料】
より詳しいことを知りたければ、以下を参照してください。
・[【Unity】【レイトレ】Unityでレイトレーシング入門① 球を表示してライティングする](https://light11.hatenadiary.com/entry/2019/09/19/221933)
	レイトレーシングの理論と実装の解説です。実際のコードと併せて解説しています。
・[【Unityシェーダ入門】ポリゴンの表面と裏面に別テクスチャを貼る](https://nn-hokuson.hatenablog.com/entry/2018/02/20/203511)
	4-(2)の裏面処理をより詳細に解説しています。
・[VRChatでどうしてもレイマーチングをしたいあなたへ贈る本](https://booth.pm/ja/items/1829988)
	VRChat特化。新たな発見があります。
・[レイマーチングのための複雑な距離関数](https://qiita.com/aa_debdeb/items/bffe5b7a33f5bf65d25b)
	図形を決定する距離関数のリストです。GLSL言語なので、読み替えてください。
・[マッハで学ぶ VRChat Shader LV5 習得 までのLV別 技術情報まとめ](https://qiita.com/7CIT/items/bb81f73e0402c693a147)
	レイマーチングに限らずシェーダーを学ぶリンクのリストです。
・[Unityシェーダープログラミングの教科書 ShaderLab言語解説編](https://booth.pm/ja/items/660001)
	基礎の理論が徹底的にわかります。難しいですが、シェーダーの全景が見えます。
・[リアルタイムグラフィックスの数学 ― GLSLではじめるシェーダプログラミング（技術評論社、巴山 竜来、2022）](https://www.amazon.co.jp/dp/4297130343/ref=cm_sw_r_tw_dp_S8K3SYSWH5M8EMWNHWYK)
	非常におすすめです。GLSL言語なので、読み替えてください。
・[CyberCat – 仮店舗](https://booth.pm/ja/items/1333754)
	美少女です。出版物・電子出版物への利用が許可されています。
・[3Dモデル『トラスとウェッジ』 - nylonheart](https://booth.pm/ja/items/3472207)
	美少女②です。出版物・電子出版物への利用が許可されています。