2017年12月2日土曜日

CyclesのDenoise

この記事は Blender Advent Calendar 2017 2日目の記事です。
(注意)この記事は急いで調べながら書いているので、間違いを含んでいる可能性があります。違ったらすみません



Blenderも気づけばバージョン2.79!
CyclesにDenoiseも載りました
今回はCyclesのDenoiseがどうなっているか、掘り下げていこうかと思います。

以下最初のシーンに適当なスザンヌとエリアライト追加してレンダーした結果です。
左がdenoise無し、右がdenoise有りです。

1spp


2spp


4spp


8spp


16spp


32spp



フルHDで、denoiseに16~17秒掛かっていますが、低サンプル数でもかなり綺麗になっています。
速度については、OpenCLを使用してレンダーするようにすると、denoiseについても半分くらいの速度でレンダーできました。

設定方法は簡単で、ここにチェックを入れるだけです。


実際の使用例や説明については公式ヘルプをご参照ください
Blender 2.79: Cycles: Denoising(デノイズ)
また、インタラクティブに確認できるサンプルがこちらにあります





それでは、Blenderのdenoiseがどうなっているのか、実装面見ていきます。

まずリポジトリをcloneしてきて、denois とかで検索すると
それらしきファイルが出てきました。


これでしょうか?
中をみると
bool DenoisingTask::run_denoising()
{
 /* Allocate denoising buffer. */
        なんか前処理っぽいコード

 /* Prefilter shadow feature. */
 {
        なんかコード
 }

 /* Prefilter general features. */
 {
        なんかコード
 }

 /* Copy color passes. */
 {
        なんかコード
 }

        なんか後処理っぽいコード
}

となっており、それっぽいですね。
影と、それ以外の部分について、別々にフィルターをかけて、
最後にカラーパスにコピーしているようなコメントが見えます。

また変数としてnlm_temporary_1 などといったものが定義されており、
Non-local Means Filter が使用されているであろうことがわかります。

Blenderは各種バッファが個別に(ノードとかで)とれると思いますが、
それらのために、いっぱいNLMの計算をしているように見えます。
最後に、denoising_reconstructとかいう関数で、レンダリング結果を再構成(上書き)しているようです。

それらしい文字で検索してみると、
https://developer.blender.org/D2592
こちらのコミットでdenoise用のフィルター関数が追加されたようです。

      REGISTER_KERNEL(filter_divide_shadow),
      REGISTER_KERNEL(filter_get_feature),
      REGISTER_KERNEL(filter_combine_halves),
      REGISTER_KERNEL(filter_nlm_calc_difference),
      REGISTER_KERNEL(filter_nlm_blur),
      REGISTER_KERNEL(filter_nlm_calc_weight),
      REGISTER_KERNEL(filter_nlm_update_output),
      REGISTER_KERNEL(filter_nlm_normalize),
      REGISTER_KERNEL(filter_construct_transform),
      REGISTER_KERNEL(filter_nlm_construct_gramian),
      REGISTER_KERNEL(filter_finalize),

とか追加されていて、やはり主にNLMを使用しているようですが、
CPU用とCUDA用とOpenCL用が同時に追加されていますね。
さらにAVX用のファイルも中は空っぽいですが追加されていて、気合いを感じます。
いやー大変ですね。

CPU版の関数らしきものは
blender/intern/cycles/device/device_cpu.cpp にあり、
bool denoising_non_local_means(device_ptr image_ptr, device_ptr guide_ptr, device_ptr variance_ptr, device_ptr out_ptr, DenoisingTask *task)
こんな感じの関数が実際のフィルタ処理しているところのようです。

https://developer.blender.org/D2592

さて、実際に入ってるコードは上記チケットのコードですが、

以前のチケットを見たところ、最初に入れたいって言ってた人は別の人のようで、
上記チケットのレビューもしているようです。
最初は、この論文を実装したいと言っていたようです。
Adaptive Rendering based on Weighted Local Regression
http://sglab.kaist.ac.kr/WLR/

現在のdenoiseはGoogle SoCのプロジェクト
https://wiki.blender.org/index.php/User:Lukasstockner97/GSoC_2016/Proposal
によって、無事、上記論文の手法が実装されたっぽいです。
この手法は pbrt2 にも実装されているそうです。
実装した人、2016年当時、18歳です。すごいですね。
Blenderは優秀な若人によって日々成長しています。



すみません、で結局なんなの?というところの詳細まで終えてませんが、

・kernelはNLMを使用している
・Weighted Local Regression(局所重み付き回帰)を使用している
 たぶん http://sglab.kaist.ac.kr/WLR/ の論文相当が実装されている。

ということでした。

いつも通りBlender Artistsのスレッド読めば楽勝だぜ!と思っていましたが、
長すぎて挫折しました…(現在89ページも伸びている)。すみません



Blender Advent Calendar 2017 3日目は
 yuinore さんによる レンダーファームとか です。





0 件のコメント: