C++
Rendering
CG
Embree2
Embree3

Embree Renderer Ver. 2からVer. 3への移行(.patch適用)

Embree Renderer

Embreeレンダラは,Intel社が開発したレイトレーシング用のオープンソースライブラリ.
githubから最新版をダウンロード/クローンすることができて,CMakeを使ってコンパイルが可能.
バイナリ形式でも配布しているため,コンパイルとは何ぞやって方にも優しい.

※GitHubへの直リンクすると,本記事が更新されない場合にバージョン情報とかがわかりづらくなるので,ダウンロードする場合は本家ページ「Download」を経由したほうが良いです.導入方法は要望などあればまた.(あるのか?)

特徴

〇最小限の機能

基本的にEmbreeが行う内部処理は,(1)使用するオブジェクトの登録(2)BVHの構築(3)レイと物体の衝突判定です.
もちろん,インスタンス生成,フィルタ設定,複数レイの効率的な投射など便利機能はあるのですが,大前提としては上の三つに集約できるのではないかと思います.
自分で(GPUじゃなくてCPUで)レイトレーシングしてみたいけど,まずレイを飛ばす部分だけ実装したいっていう人には好都合じゃないかと思います.

〇SSE・AVX・AVX2・AVX-512が使える

この記事を書いている本人も勉強中なので正確な説明は割愛しますが,ライブラリ内部で並列演算をしやすいように設計されているようです.
ソースコードを読むと,例えば配列作成時にメモリを連続的に確保していたり,CMakeコンパイル時に使用する拡張命令を選択できるようになっていたりします.

×資料が少ない

主な資料は以下になります.

  • 公式ページの「Tutorial」およびライブラリ内にある同名のソースコード群
  • 公式ページの「Overview」の「Embree Resources」

個人的には,Embree Resourcesの「Embree Presentation at SIGGRAPH 2017」か,「Embree Presentation at SIGGRAPH 2016」がおすすめです.といっても,どちらもEmbree Ver. 2を使っているので,Ver. 3では使えないんですけどね.

本題

さて,この記事はチュートリアルではないので,本題に入ります.
2018年1月22日に,github上でEmbree Ver. 3がβ公開されました.
この際,多くの関数が削除されたり,名前が変更になったりしています.
そして,Ver. 2への後方互換性は担保されていません

この違いを吸収するために,Embree3にはpythonを使用した自動変換スクリプトが用意されています.
構文は以下.原文はGitHub内「Upgrading from Embree 2 to Embree 3」を参照
※変更される可能性があるので,最新情報は本ページ上部に載せた本家ページから.

command.txt
./scripts/cpp-patch.py --patch embree2_to_embree3.patch --in infile.cpp --out outfile.cpp
コマンド・オプション名 説明 ファイルの場所
./scripts/cpp-patch.py - C++にパッチを適用するためのpythonスクリプト ソースコードに含まれている
--patch embree2_to_embree3.patch 使用するパッチ ソースコードに含まれている
--in infile.cpp 処理の対象ファイル 自分のファイルを指定
--out outfile.cpp 処理が適用されたコードの出力ファイル 自分のファイルを指定

※注意:公式の説明でも上記のコマンドを使っていますが,パスは自身の環境に合わせたものにする必要があります.

このパッチを適用することで,関数の名称が違うことによるエラーは大部分が解決されます.
ただし,一部の関数(rtcSetBuffer2)とかは挙動が怪しいのでGitHubの方で質問してみたんですが,「patchのプログラムは正しく動くように見える」とのことです.この部分に関しては研究中です.

パッチで処理しきれない関数の一例

ちなみに,rtcSetBuffer2()の正式な変換先はrtcSetSharedGeometryBuffer()になります.

rtcSetBuffer2(RTCScene scene, unsigned geomID, RTCBufferType type, void* ptr, size_t offset, size_t stride, size_t size);
rtcSetSharedGeometryBuffer(RTCGeometry geometry, enum RTCBufferType type, unsigned int slot, enum RTCFormat format, const void* ptr, size_t byteOffset, size_t byteStride, size_t itemCount);

引数を比較するとこんな感じですね.変更点としては以下のような感じです.

  1. geomIDがRTCGeometryに統合
  2. RTCBufferTypeの命名規則,enumの使用法が大きく変更
  3. 2番の変更に伴い,新たにslot変数が追加
  4. データフォーマットformat変数が追加

特に重要なのが2, 3番のセットです.
これまでバッファ名はenum型で連続定義されていて,RTC_VERTEX_BUFFER + 1みたいな指定で動作していたのですが,Ver. 3からは+ 1の部分は'slot'という変数に分離しました.
これによって,(1)バッファ名の見通しが改善され,(2)保存されているバッファの位置の保存が容易になりました.

個人的にはVer. 3をまだまだ理解しきれていないので,引き続き対応していこうと思います.