Cycles render をデバッグする準備

BSDF やシェーダの振る舞いを調べるために Cycles を standalone でビルドしデバッグできるようにします.

![cycles-ui.png](https://qiita-image-store.s3.amazonaws.com/0/36275/03fc98e8-7164-dcae-65bd-365da8400d58.png)


## ソースコード

git://git.blender.org/cycles.git

## ビルド　

cmake が用意されています.

Standalone でも GUI 周りが必須のようで, OpenGL required などになっていますので注意ください.
純粋に CLI 実行には対応していません. 

Ubuntu 16.04 では, 依存ライブラリは apt でだいたい入ります.
(e.g. libpugixml-dev)

`WITH_CYCLES_LOGGING` を On にしてログ出力ができるようにしておきます.
(`WITH_CYCLES_DEBUG` も On がおすすめかも)

### 最小依存 Cycles

aarch64 対応もかねて OpenGL や OpenImageIO などの依存ライブラリを決して最小 CLI ビルドできるようにしたブランチを作りました. OpenGL インストールがうまくいかないとか, サーバーで動かしたいなどのときに利用ください.

https://github.com/syoyo/cycles/tree/android

cmake 設定は

https://github.com/syoyo/cycles/blob/android/scripts/bootstrap-mindep-linux.sh

を参考ください.

```
$ ./cycles --output bora.png --samples 32 input.xml
```

のように使います. 現状 8bit PNG 出力のみ対応しています. デフォルトでは無限に progressive path tracing するので, `--samples` で回数を指定しましょう.

## シーンファイル

入力シーンとして xml を用意する必要があります.
`examples` にサンプルがいくつかあります.
形状データを xml に変換は面倒かもしれませんね(Blender から cycles 用の xml をエクスポートする機能はないっぽい?)

https://github.com/fabiosantoscode/cycles-xml-exporter

などありますが開発は止まっています.

## BSDF closure 定義

OpenShadingLanguage や Blender での node editor によるシェーダ定義の知識があるとします.

```
<diffuse_bsdf> ... </diffuse_bsdf>
```

のように tag で定義します.
使える closure の名前とパラメータは

`src/render/nodes.cpp`  

にあります. 

`subsurface_scattering` の場合は `BSDF` のカテゴリではなく `BSSRDF` のカテゴリに所属するため, ノードの接続を記述するときは `bssrdf` を使います. e.g. 

```
<connect from="monkey_closure BSSRDF" to="output surface" />
```

## 光源定義

shader tag で定義します.

`src/render/light.cpp`  

で定義がわかります.

## 実行する.

```
$ ./cycles input.xml
```

で動きます. CUDA など有効になってビルドされている場合, `--device CPU` などとして明示的に利用するデバイスを指定できます.

レンダリングをすると画面表示用に UI が出ます.
あまり機能はありませんが, `i` キーで interactive モードになり, 視点をちょこっと変えることができます

`h` キーでヘルプが出ます.

## サンプルシーン

頂上からの平行光源 + subsurface scattering です.
`examples/scene_monkey.xml` を参考にしています.

```
<cycles>
<!-- Camera -->
<camera width="800" height="500" />

<transform translate="0 0 -4" scale="1 1 1">
        <camera type="perspective" />
</transform>

<shader name="dirlight_shader">
        <emission name="emission" color="1.0 1.0 1.0" strength="1" />
        <connect from="emission emission" to="output surface" />
</shader>

<state shader="dirlight_shader">
        <light type="distant" dir="0 -1 0" size="0.0" />
</state>


<!-- Monkey Shader -->
<shader name="monkey">
        <subsurface_scattering name="monkey_closure" falloff="random_walk" radius="1.0, 0.2, 0.1" scale="1.0"/>
        <connect from="monkey_closure BSSRDF" to="output surface" />
</shader>

<!-- Objects -->
<transform rotate="180 0 1 1">
        <state interpolation="smooth" shader="monkey">
                <include src="./objects/suzanne.xml" />
        </state>
</transform>

</cycles>
```


## ログを仕込む

LOG, VLOG などの glog っぽいマクロが使えます.

`util/util_logging.h` をインクルードして

```
  VLOG(1) << "color = " << color;
```

などとします.

kernel あたりに仕込むと再コンパイルがたくさん発生するので注意.

このログを表示するには `--debug` オプションを起動時に指定します.

`--verbose` でレベルを指定します. たとえば上の `VLOG(1)` ですと,

```
--debug --verbose 0
```

ではログが出力されないようになります.

## Fresnel について

Cycles では OpenShadingLanguage と一緒にするためか, Fresnel は mix シェーダなど BSDF の外部で定義するのが基本となります.

## 注目すべきソースコード

* kernel/ BSDF や シェーダの実装があります. CPU/GPU 共通で書かれているようです.
* kernel/svm/svm_closure.h シェーダ設定(shader graph など)の入力を個別の BSDF(closure) カーネルに変換したりします. たとえば Principle BSDF の場合は diffuse, specular(microfacet), subsurface などに分解します.
* kernel/closure 各 closure(BSDF)や補助ユーティリティ関数の実装があります. 


## Subsurface について

### random walk 

ランダムウォークでは経路としては分岐せずに一つだけ追跡します.
また, sss したあとの経路で再度 sss 物体に入ると計算が複雑になって noise が出やすいので, 一度 sss した経路では残りは BSDF 反射(diffuse や specular など)だけを考慮するようにしています.
(PATH_RAY_DIFFUSE_ANSCESTOR フラグが立つ)
 
### diffusion(Chiristensen-Burley)など

cubic, gaussian, burley(Christensen-Burley) は diffusion ベースのアルゴリズムを使います.

https://www.arnoldrenderer.com/research/s2013_bssrdf_slides.pdf

PBRT-v3 などと違い, 交差するシェーディングポイント全てで経路追跡をする模様(なのでふるまいを追うのが大変そう)