Embree のソースコードを読解して, Embree でビルドした BVH データを自作のレイトレーサーで使いたいとか, 独自機能をつけくわえたいとかしたい人向けです.
手前味噌ですが, NanoRT https://github.com/lighttransport/nanort のコードを読んでいくと Embree のコードの理解も早いかと思います
(あとは PBRTv3 book http://www.pbr-book.org/ の 2 Geometry and Transformations から 4 Primitives and Intersection Acceleration まで).
hair, subd 周りが後ほど追加されたロシアンな香りただようソースコードで, 実装パートのコードがかなりトリッキーかつコメントがないので読むのに苦労します.
(昔のコードや, API はそれなりにコメントが書かれています)
ソースコードの主なレイアウトは以下です.
include/ : ヘッダーファイル. ユーザが見る public Embree API
common/ : 共通コード
algorithms : `parallel_for` などの実装
cmake : コンパイラやアーキテクチャごとの cmake 設定
tasking : タスクスケジューラ. tbb などを使っています.
math, simd : SIMD 型ライブラリ, vec4 の定義などがあります.
kernels/ : レイトレカーネル(BVH 構築と, traverse, intersection)
builders : BVH 構築のアルゴリズム実装があります.
bvh : BVH traversal, intersector があります.
common :
geometry : 形状
subdiv : Subdivision surface 周り
概要
Embree: A Kernel Framework for Efficient CPU Ray Tracing
https://www.embree.org/papers/2014-Siggraph-Embree.pdf
を読みましょう.
以外と結構昔からあるのと, 性能重視なので, ソースコードは C++03 + C++11 を少々, みたいな感じです.
用語
- primitive : 形状を構成するプリミティブ. 三角形形状の場合は面(
face
)に対応. - geometry : 形状(shape, mesh)に対応. primitive から成る.
- instance : geometry のインスタンシング. instance 自体がジオメトリタイプとなる(一旦 scene を作って, それを instancing して新しく scene を作るという段取りになっておりややわかりずらい)
instanceID については, 交点(RTCHit
)では複数持つことができる
Multi-level instancing に使える
(大規模シーン向けかな?)
- intersection filter : ヒットするかもしれない交点が見つかったときに, ユーザ定義のコールバック関数(filter)を呼ぶことができる. 一見これでなんでもできそうだと思ってしまうが, 制約がいろいろあり, 万能ではない.
common/math
vec4 などの型を定義しています.
SSE, NEON 命令(embree-aarch)などを wrap しています.
したがって基本的には SSE 命令などはこの math
フォルダ以外では出てきません.
新しいアーキテクチャに対応するときはここと, common/sys
あたりと, cmake の設定をいじればよいことになります.
common/sys
atomic や thread の実装, ISA の情報などがあります.
builders(BVH build アルゴリズム)
- primrefgen : PrimRef 生成
- hair 専用
- heuristic
- SAH builder
- motion blur 用(MB hair)
bvh
データ構造は
- BVH4(四分岐)
- BVH8(8分岐). AVX が有効の場合のみ.
の二つがあります. 普通の BVH(二分岐)は無いようです.
builder, intersector
builder, intersector はいろいろあります.
- node_intersector : two-level BVH traverse 用?
geometry
curve primitive は結構特殊です.
- curve
- curveNi : 複数の Curve をまとめて処理
- curveNv
- disc
- grid
- instance
- line
- quad
- sphere
- subdivpatch
- triangle
- moeller
- pluecker
- woop
- motion blur 対応
ファイル名命名規則?
-
***i.h
: index で primitive にアクセスする場合に利用される- fill : プリミティブ情報を格納する
- update : bounding box アップデート
-
***v.h
: プリミティブの直接の配列(array of structure. index 無し)バージョン -
***_intersector.h
: プリミティブの交差判定コード
curveNi
Curve prim の情報(primID, geomID, bounds, etc) を fill
メソッドでメモリにパックしていますが, メモリレイアウトはハードコードされているので注意ください.
bounds_vx_x()
などの取得関数は, ハードコードされたメモリレイアウトから, reinterpret cast してデータを返すようになっています.
ロードやストアのアラインメントに制約があるハードではここは移植が面倒かもしれません.
curveNi_intersector.h が実際に交差判定を行う関数が書かれています.
subdivision surface
subdivision surface は, OpenSubdiv を使わずに自前(!)で処理しています.