実践QBVH

4,675 views

Published on

2013/8/24 レイトレ合宿用に作成したQBVHの解説スライドです。

Published in: Technology

実践QBVH

  1. 1. 実践! QBVH 2013/8/24 レイトレ合宿 林 秀一 (http://d.hatena.ne.jp/shuichi_h)
  2. 2. ※スライドの一部の図について •以下の画像はwikipediaから借用しており、 ライセンスはwikipediaの表記に従います。 http://en.wikipedia.org/wiki/Bounding_volume_hierarchy http://en.wikipedia.org/wiki/K-d_tree http://en.wikipedia.org/wiki/Octree
  3. 3. アジェンダ 1. 空間構造とは 2. なぜ必要? 3. さまざまな空間構造 4. 人気の空間構造 5. 空間構造の対価 6. よい空間構造とは 7. AABB 8. BVH 1. 構造 2. 構築 3. AABBとRayの交差判定 4. トラバースの流れ 9. QBVH 1. 特長 2. 構造 3. データ構造 4. 構築 5. 交差判定 6. トラバース早期打ち切り 10. 参考文献
  4. 4. 空間構造とは •空間を何らかのルールで区切った構造 •空間中のデータを高速に探索するために使 用される事が多い
  5. 5. なぜ必要? •単純にレイトレを作ると プリミティブの数 レイの数 の交差判定が必要 •プリミティブやレイの数が増えるとすぐに非現 実的な処理時間になる ➡空間構造を使えば... •交差判定処理の大部分を省ける •計算量の増加がlogオーダーに抑えられる
  6. 6. なぜ必要? •レイが当たった領域の中にある三角形だけ判定 すればよい 空間構造あり空間構造なし
  7. 7. 空間構造の対価 •空間構造を格納するメモリ •構築時間 •動的なシーンでは、更新も必要、 部分的に再構築する等の最適化も必要
  8. 8. よい空間構造とは •交差判定が高速 •構築が高速 •メモリ使用量が少ない •インコヒーレントなレイに対しても有効 (バラバラの方向からのレイにも有効)
  9. 9. さまざまな空間構造 Uniform Grid Octree kd-tree BVH 等々...
  10. 10. Uniform Grid Octree 人気の空間構造 kd-tree BVH レイトレでは、kd-tree と BVH が人気
  11. 11. AABB •Axis-Aligned Bounding Box •XYZ軸に平行なバウンディングボックス •BVHで使用
  12. 12. BVH Bounding Volume Hierarchy
  13. 13. BVH:構造 • 外側のAABBの中に、2つのAABBを含む
  14. 14. BVH:構造 •2分木になる •葉はプリミティブ •各ノードが自身のAABBを持つ
  15. 15. BVH:構造 •AABBは重なっていることもある •あるノードの配下にあるオブジェクトはすべて、 そのノードのAABBに収まる •空間的に収まっていても、そのノード配下とは限らない
  16. 16. BVH: 構築 よりよい方法はototoiさんのセミナーで! 方法1 中央の位置で分割 方法2 同数になるように分割
  17. 17. AABBとRayの交差判定 ➡レイとBBoxが交わる範囲があるか否か判定する Ray AABB •交差する位置座標を求める必要はない •交差しているか、していないかだけ分かればOK
  18. 18. e d xmin AABBとRayの交差判定 e …レイの始点 d …レイの方向 Ray レイとAABBの交点を求める
  19. 19. AABBとRayの交差判定 txmin = (xmin - xe) / xd レイdをtxmin倍すると xminと交わる txmin倍 txmin e d xmin Ray xd xmin - xd
  20. 20. AABBとRayの交差判定 tymin tymax txmin txmax t [tymin, tymax] t [txmin, txmax] t [txmin, txmax] [tymin, tymax] 縦横で交わるtの範囲を求めて tymax>txminか判定する ※縦横両方tというパラメータ空間の値なので比較できる tymaxtxmin
  21. 21. AABBとRayの交差判定 レイの方向や、ゼロ除算によって出てくる+ , - ,を 考慮しても、最終的にシンプルなロジックになる。 詳細はRealistic Ray Tracing等を参照。
  22. 22. AABBとRayの交差判定 bool BBox::RayIntersect(const Ray &r, float tmin, float tmax) { // X軸 int sign = r.sign[0]; float t0 = (bb[sign].x - r.o.x) / r.dir.x; float t1 = (bb[1-sign].x - r.o.x) / r.dir.x; if (t0 > tmin) tmin = t0; if (t1 < tmax) tmax = t1; if (tmin > tmax) return false; // Y軸 ... // Z軸 ... return true; } ※もちろん割り算は予め1.f / r.dirを計算してRayに保存しておき、それとの掛け算にした方がいい
  23. 23. AABBとRayの交差判定 bool BBox::RayIntersect(const Ray &r, float tmin, float tmax) { // X軸 int sign = r.sign[0]; float t0 = (bb[sign].x - r.o.x) / r.dir.x; float t1 = (bb[1-sign].x - r.o.x) / r.dir.x; if (t0 > tmin) tmin = t0; if (t1 < tmax) tmax = t1; if (tmin > tmax) return false; // Y軸 sign = r.sign[1]; t0 = (bb[sign].y - r.o.y) / r.dir.x; t1 = (bb[1-sign].y - r.o.y) / r.dir.y; if (t0 > tmin) tmin = t0; if (t1 < tmax) tmax = t1; if (tmin > tmax) return false; // Z軸 sign = r.sign[2]; t0 = (bb[sign].z - r.o.z) / r.dir.z; t1 = (bb[1-sign].z - r.o.z) / r.dir.z; if (t0 > tmin) tmin = t0; if (t1 < tmax) tmax = t1; if (tmin > tmax) return false; return true; } ※もちろん割り算は予め1.f / r.dirを計算してRayに保存しておき、それとの掛け算にした方がいい
  24. 24. トラバースの流れ 1.RayとノードのBBoxを交差判定 (1)ヒットした場合 1)ノードが枝: 2つの子ノードをそれぞれ交差判定(再帰処理) 2)ノードが葉:  交点の位置、色、法線等、必要な情報を格納 (2)ヒットしなかった場合  何もせずreturn
  25. 25. QBVH: 特長 •SIMD命令を効果的に使用 •Binary BVH比 1.6∼2.0倍 高速 •kd-tree比 1.3∼1.6倍 高速 •メモリは10%∼50%削減 •インコヒーレントなレイに対しても有効 (※以上は、下記論文での主張です。) H. Dammertz and J. Hanika1 and A. Keller: Shallow Bounding Volume Hierarchies for Fast SIMD Ray Tracing of Incoherent Rays. http://www.uni-ulm.de/fileadmin/website_uni_ulm/iui.inst.100/institut/Papers/QBVH.pdf
  26. 26. インコヒーレントなレイにも有効 •SIMDを使う別の手法:「レイパケット」の場合... ‣複数のレイをまとめてSIMDで交差判定 ‣インコヒーレントなレイだとSIMDが有効に活用されず ➡一方でQBVHは、常にSIMDを有効活用する
  27. 27. QBVH:構造 •4つ(Quad)の子ノードを持つ •子ノードのAABBは親のノードが持つ •4つの子ノードのAABBをSIMDでまとめて 交差判定 Binary BVH Quad BVH
  28. 28. QBVH:構造 •ツリーが浅くなる ➡トラバース速そう 0 1 2 3 4 0 1
  29. 29. QBVH: データ構造 child0 child1 child2 child3 __m128 __m128 __m128 __m128 __m128 __m128 min x min x min x min x min y min y min y min y min z min z min z min z max x max x max x max x max y max y max y max y max z max z max z max z child0 idx child1 idx child2 idx child3 idx axis top axis left axis right fill 1ノードあたり sizeof(float) * 8 * 4 = 128
  30. 30. QBVH: データ構造 child0 child1 child2 child3 __m128 __m128 __m128 __m128 __m128 __m128 min x min x min x min x min y min y min y min y min z min z min z min z max x max x max x max x max y max y max y max y max z max z max z max z child0 idx child1 idx child2 idx child3 idx axis top axis left axis right fill min/max xyz …子ノードのAABB child idx …子ノードのインデックス axis …分割軸 0:x 1:y 2:z
  31. 31. QBVH: データ構造 child0 child1 child2 child3 __m128 __m128 __m128 __m128 __m128 __m128 min x min x min x min x min y min y min y min y min z min z min z min z max x max x max x max x max y max y max y max y max z max z max z max z child0 idx child1 idx child2 idx child3 idx axis top axis left axis right fill SIMD処理できるように SoA(Structure of Array)レイアウト
  32. 32. QBVH: データ構造 axis left axis right axis top
  33. 33. QBVH: 子ノードのindex 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 child idx: 32bit 空ならINT_MIN
  34. 34. QBVH: 子ノードのindex 枝or葉(1bit) 枝or葉のindex(31bit) △ △ △ △ △ △ NULL △ △ △ △ △ NULL 先頭のインデックスを指す 葉のデータの配列: child idx: やり方 その1
  35. 35. QBVH: 子ノードのindex 枝or葉(1bit) 枝or葉のindex(31bit) △ △ △ △ △ △ △ △ △ △ △ △ △ 先頭のインデックスを指す 葉のデータの配列: child idx: やり方 その2 子の数(4bit)
  36. 36. QBVH: 子ノードのindex 枝or葉(1bit) 枝or葉のindex(31bit) △ △ △ △ △ △ △ △ △ △ △ △ △ 葉のデータの配列: child idx: やり方 その3 葉の数 葉のindex その他情報 葉の数 葉のindex その他情報 葉の数 葉のindex その他情報
  37. 37. QBVH: 構築 •区切った領域をもう一段階、区切るだけ •Binary BVHと同じ要領でOK 0
  38. 38. QBVH: 交差判定 •4つの子ノードのAABBをSIMDでまとめて 交差判定 •次項ソースコード参照
  39. 39. inline int SIMD_QBVH::IntersectSIMD( const __m128 bboxes[2][3], // min-max[2] of xyz[3] of boxes[4] const __m128 orig[3], // ray origin, xyz[3] const __m128 idir[3], // ray inverse direction, xyz[3] const int sign[3], // ray xyz direction -> +:0,-:1 __m128 tmin, __m128 tmax // ray range tmin-tmax ) const { // x coordinate tmin = _mm_max_ps( tmin, _mm_mul_ps(_mm_sub_ps(bboxes[sign[0]][0], orig[0]), idir[0]) ); tmax = _mm_min_ps( tmax, _mm_mul_ps(_mm_sub_ps(bboxes[1 - sign[0]][0], orig[0]), idir[0]) ); // y coordinate tmin = _mm_max_ps( tmin, _mm_mul_ps(_mm_sub_ps(bboxes[sign[1]][1], orig[1]), idir[1]) ); tmax = _mm_min_ps( tmax, _mm_mul_ps(_mm_sub_ps(bboxes[1 - sign[1]][1], orig[1]), idir[1]) ); // z coordinate tmin = _mm_max_ps( tmin, _mm_mul_ps(_mm_sub_ps(bboxes[sign[2]][2], orig[2]), idir[2]) ); tmax = _mm_min_ps( tmax, _mm_mul_ps(_mm_sub_ps(bboxes[1 - sign[2]][2], orig[2]), idir[2]) ); return _mm_movemask_ps(_mm_cmpge_ps(tmax, tmin));//tmin<tmaxとなれば交差 }
  40. 40. QBVH: トラバース早期打ち切り (1) (2) (3) (4) •レイのxyzの符号と分割軸の方向から、 交差判定する順番にノードをソート •もし葉(三角形)に当たったら、次のノード 以降の交差判定を省略
  41. 41. 参考文献 H. Dammertz and J. Hanika1 and A. Keller: Shallow Bounding Volume Hierarchies for Fast SIMD Ray Tracing of Incoherent Rays. http://www.uni-ulm.de/fileadmin/website_uni_ulm/iui.inst.100/institut/Papers/QBVH.pdf QBVHの論文です。 ototoi: QBVHを実装した - 明日ではないから http://d.hatena.ne.jp/ototoi/20090925/p1 QBVHについての解説、他の空間構造とのパフォーマンス比較結果、ソースコードがあります。 Shirley P.: Realistic Ray Tracing, Second Edition. AK Peters, Ltd., 2000. http://www.amazon.com/dp/1568814615 BVHのソースコード、AABB-Ray交差判定の詳しい説明が載っています。 Kayvon F.: CMU 15-869, Graphics and Imaging Architectures. http://www.cs.cmu.edu/afs/cs.cmu.edu/academic/class/15869-f11/www/ Carnegie Mellon Universityのグラフィックスコースの資料。 Real-time ray tracingというリンクのPDFにレイパケットの説明があります。
  42. 42. ありがとうございました

×