Aqoole_Hateenaの技術日記

vulkan+raytraceで色々描いてます

オブジェクトが途中から描画されない場合

概要

オブジェクトが途中から描画されない場合があった。

原因

Top Level ASの更新漏れ

詳細

Khronos Blog - The Khronos Group Inc

the triangles or axis-aligned bounding boxes (AABBs)

とある通り、ray tracingのオブジェクトの範囲はboxで指定されている。

The upper level, the top-level acceleration structure, contains references to a set of bottom-level acceleration structures, each reference including shading and transform information for that reference.

とあり、TLASはBLASの参照をもっているので、BLAS全体を統合し、描画するAABBを決めるものと思われる。
なので、TLASを更新しなければ、最初のAABBの範囲内しか描画されず、上動画のような挙動になってしまう。

Acceleration Structure Hierarchy

引用:
https://www.khronos.org/blog/ray-tracing-in-vulkan

上記絵の物体は、AABBも更新されることを表しているものと思われる。

3Dオブジェクトをタッチしているかの判定方法

結論

カメラーオブジェクトのベクトルとカメラータッチ位置をワールド座標に変換したベクトルの内積を計算し、1に近ければタッチしていると判定

補足

点と平面の距離を計算して、その距離が0に近ければ、なども考えたが、内積を考えるのが速そう。
Unityであれば、Rayを飛ばすという方法があるらしい。
クリック(スマホではタップ)したゲームオブジェクトを判定する方法 | ソフトライム
3D空間でタッチした位置というのは、1点に定まらないので、カメラータッチ位置の直線上にオブジェクトがあるかどうかを判断するしかないと思う。
レイトレーシングの構造体(AS)を準備しているのであれば、判定するだけのパイプラインを作成してもよいかもしれない。
オブジェクトが重なったときに前面のものだけタッチしているかどうかを判定したければ、空間上のオブジェクトをすべて認識している必要があるので、
レイトレーシングアーキテクチャーを使用するのがよさそうか。

水面の表現に挑戦

水面の反射

水面に反射する草を描画してみました

課題

  1. 反射の計算が重すぎて驚異の2fpsしか出ていない
  2. 水面の頂点をすべて保持しているので、コピーで済む部分はそのようにしたい offsetをもつようにするとか
  3. 水面の頂点の計算はCPUで行っているので、GPUで行うようにcompute shaderを書いた方がよいかも
  4. オブジェクト追加するたびにshader内のオブジェクトidを書き換えなければならないのが面倒 オブジェクトのグループごとのshaderをつくっても良いかも
  5. sbtの設計やvertex bufferの設計をまとめた方がよいかもしれない

glTFモーフィング描画(アルファテストあり)

glTFモーフィング(アルファテストあり)

アルファテストを用いて透明 or notを判定することにより、必要な部分だけを取り出してモーフィングアニメーションすることができた。

モデルの権利表記
https://sketchfab.com/3d-models/yard-grass-3a67e76decc849c694c228eb590a9902
ライセンス:CC Atribution
https://creativecommons.org/licenses/by/4.0/legalcode

レイトレーシングでのアルファテスト

Googleで調べてみると色々な人が書いているが、レイトレーシングでのアルファテストはanyhit shaderを用いることで達成できる。
anyhit shader内でアルファテストを行い、もし透明な部分にヒットしている場合には

ignoreIntersectionEXT

を用いて交差判定を無視する。
これを用いると、その判定は無視してrayは直進し直し、次の判定に進む。

注意点としては
Khronos Blog - The Khronos Group Inc
にある通り、ignoreIntersectionEXT()ではなくignoreIntersectionEXTを用いる。

instead of appearing as ignoreIntersectionEXT(); it is now simply ignoreIntersectionEXT; when used in a shader.

その他、any hit shaderの実装方法についてはnvidia様が作成しているvulkan raytracing tutorialが参考になる。
github.com

morphing animation glTF

morphing

glTFのモーフィングアニメーションを読み込み、androidで描画することができた。

モデルの権利表記
https://sketchfab.com/3d-models/yard-grass-3a67e76decc849c694c228eb590a9902
ライセンス:CC Atribution
https://creativecommons.org/licenses/by/4.0/legalcode

苦労した点

なぜか、compute shader内のバッファーで、vec3で読み取ろうとすると正確な値がとってこれなかった。
バッファーがfloatであるとして読み取るとうまくいったが、なぜなのだろう。
この手のような、用意しているデータや計算方法は間違ってないけど、glslの構造上エラーとなるみたいな場合、調査が難航する。

課題

ようやくレイトレーシングの本題に入ってこれるのだが、今はrayが到達しきれない部分を白色にして誤魔化しているので、この部分まで綺麗にレンダリングできるように工夫する。

glTFでmorphing (alpha処理後)

glTFモデルのmorphing

前回の記事
aqoole-hateena.hatenablog.com
からalphaがglTFファイルにあるalpha cutoffよりも小さい場合に、描画しない処理を追加したものがこちら。

モデルの権利表記
https://sketchfab.com/3d-models/yard-grass-3a67e76decc849c694c228eb590a9902
ライセンス:CC Atribution
https://creativecommons.org/licenses/by/4.0/legalcode

課題

  • レイトレーシングでオブジェクトが重なった場合の処理が難しく、草の中心部が白くなっているのはオブジェクトが重なってレイが到達しない場合に、一律に白色にしているから。

 ここの部分をより自然な表現にしたい。

  • 邪魔な部分を省いて分かったが、アニメーションが不自然なので、blenderで再生したときと同じアニメーションにする

glTFでmorphing (マテリアル処理なし)

Morphing

morphingのアニメーションに挑戦してみた。
それっぽくはなっているが、、、合ってるのか?

モデル
https://sketchfab.com/3d-models/yard-grass-3a67e76decc849c694c228eb590a9902
ライセンス:CC Atribution
https://creativecommons.org/licenses/by/4.0/legalcode

alpha value

glTFのモデルは(それ以外もそうかもしれないが)meterialの属性の中にalpha valueの情報がありそうなので、マテリアルの処理も追加して動画のモデルから黒抜きをしたい。
(アニメーションの動きの処理を優先したので、マテリアルを読み込むところはまだ実装してなかった)