629 Views
November 30, 25
スライド概要
2025年 11月14日(金)~11月16日(日) に開催されたレイトレ合宿11で発表したセミナー資料です。
レイトレ合宿11: https://sites.google.com/view/rtcamp11
3DCGに興味があります。
OpenUSDについて & Hydraレンダラー実装 レイトレ合宿 11 セミナー資料 折登 樹
今日話すことは2つ まずは……
OpenUSD、ご存知ですか?
OpenUSDは映像業界で広く使われつつあるシーンファイル - OpenUSDはPixarが開発してOSSで公開している シーン記述用ファイルフォーマット及びライブラリ
OpenUSDは映像業界で広く使われつつあるシーンファイル - Pixarだけでなく、業界全体で採用事例も増えてきている - 例えばCGWorldのサイトでUSDで検索すると国内でも事例がいくつもヒットする
OpenUSDは映像業界で広く使われつつあるシーンファイル スクショは https://cgworld.jp/article/202504-Houdini-OpenUSD-ToeiAnimation.html より引用( 2025/11/14アクセス)
OpenUSDは映像業界で広く使われつつあるシーンファイル スクショは https://cgworld.jp/article/202508-srcw-op.html より引用( 2025/11/14アクセス)
OpenUSDは映像業界で広く使われつつあるシーンファイル スクショは https://cgworld.jp/article/202509-sonic3-1.html より引用( 2025/11/14アクセス)
OpenUSDは映像業界で広く使われつつあるシーンファイル スクショは https://cgworld.jp/article/2412-aonohako01.html より引用( 2025/11/14アクセス)
OpenUSDは映像業界で広く使われつつあるシーンファイル スクショは https://cgworld.jp/feature/202112-cgw280-megalis02.html より引用( 2025/11/14アクセス)
映像業界標準になりつつあるOpenUSD、 自作レンダラーでレンダリングして みたくないですか?
そして今日話すのは もうひとつ……
自作レンダラー、 DCCツールに組み込んでみたくないですか?
実機デモ
Houdiniで自作レンダラーが動く!
Houdiniで自作レンダラーが動く!
Houdiniで自作レンダラーが動く!
Blenderで自作レンダラーが動く!
Blenderで自作レンダラーが動く!
Blenderで自作レンダラーが動く!
もくじ - OpenUSD概要 Hydraレンダラーの実装について
おことわり - どう考えても30minに収まらないです(脅威のスライド236ページ ※) - 後日スライドは公開するので発表はかいつまんで飛ばしまくって行きます - 特に後半は全部飛ばします - 後日公開時のためにスライドに文字が多めです - 発表時は必要なところは読み上げるので、全部読む必要はありません (※公開版スライドは発表時よりページ数が増えて 270ページです)
おことわり - このスライドには多くの勘違い・間違いが含まれている可能性があります - 私は映像業界出身でもなければ OpenUSDを普段業務で使うわけでもない - 趣味でちょっとだけ一ヶ月ほど OpenUSDを触ってみただけの人 今回の発表は実装しながら適当に調べた独自調査結果を元にしている - なので大量に勘違いや間違いが含まれるかも 最終的には各自自分で情報を集めて勉強してくれ!
OpenUSD概要
OpenUSDとはなにか - 公式サイト https://openusd.org/release/index.html
OpenUSDとはなにか - GitHubにOSSとして公開されている - - https://github.com/PixarAnimationStudios/OpenUSD 最新安定版はv25.11 - v25.11は2025/10/24にリリースされたばかり
OpenUSDとはなにか - いわゆるシーンファイル DCCツール非依存
OpenUSDとはなにか - いわゆるシーンファイル DCCツール非依存 - glTFと同じ?
OpenUSDとはなにか? - glTFとOpenUSDはだいぶ趣が違う - glTF - - OpenGLでの描画に必要なものがそのままシリアライズされた感じ シンプル・単純 ゲームエンジンにメッシュを持ち込むとか、 最終的なメッシュとボーン情報だけをポータブルに持ち運ぶのには便利 OpenUSD - 大規模プロジェクトにも耐えうる仕組みを持っている - 複数人で並列にシーン編集など プロダクションの中間シーンファイルとして十分な表現力がある
業界でOpenUSDの採用が進んでいる - Pixarが開発 - - Pixarの知見が詰まったファイル形式 OSSライセンスで公開されている 各DCCツールが少しずつOpenUSDの採用を進めていこうとしている
OpenUSDはDCCツールに依存しない - OpenUSDのデータはDCCツール非依存 - - DCCツールを使わなくても単体でデータを操作できる C++ライブラリとPythonAPIが用意されている PythonでOpenUSDを編集できるのは TAの人とかが嬉しいと思う 3DCGにおいてデータは資産 - その生殺与奪の権を DCCツールに持たせて DCCツールと一蓮托生で ツールが死ぬときは一緒に爆散になるのは厳しい OpenUSDはソースコードがオープンで、データ操作の APIなども整備されているのでよい
OpenUSDの歴史 - OpenUSDの歴史については技師長さんのツイートのスレッドを是非見てほしい - https://x.com/gishicho/status/1296419840123691010 https://x.com/gishicho/status/1296420623305121792
OpenUSDを開いてみる
OpenUSDを開いてみる - OpenUSDを ただ使いたいだけならNVIDIAがビルド済みの ライブラリやバイナリ群を提供しているのでまずはこれを使ってみる - https://developer.nvidia.com/usd - 余談だがNVIDIAはOmniverseという仕組みをOpenUSDを 基盤として採用して作っている - Omniverseは建築の3DモデルをCADで保存すると UEのリアルタイムビューワーに反映されるとかのアプリ連携用の仕組み そのDCCツールのやり取りの内部形式として OpenUSDが採用されている - - ただし後述するHydraレンダラープラグインなどを作りたくなったら OpenUSDを自前ビルドすることになりそう
OpenUSDを開いてみる - 次のURLからPre-Built ライブラリをダウンロード - https://developer.nvidia.com/usd
OpenUSDを開いてみる - ダウンロードしたzipがカレントディレクトリ以下の./usd/に展開されているとする - Linuxの場合 以下のコマンドで実行権限をつける
OpenUSDを開いてみる - OpenUSDライブラリのPythonバインディングを動かしてみる - - OpenUSDはpxrというPythonのパッケージで提供される Linuxの場合以下のコマンドを実行する - 最初にダウンロードした OpenUSDに同梱されている Pythonにパスを通したり、 OpenUSDのライブラリについて PATHやPYTHONPATHを通すスクリプトを実行している あとはpxrからUsdをimportしてバージョンを表示させている - 今回ダウンロードした OpenUSDはv25.08なので(0, 25, 8)と表示される
OpenUSDを開いてみる - PythonでOpenUSDを触る前に.usdファイルをプレビューする手段を確保する OpenUSDのPre-Builtライブラリに同梱されている usdview を使ってみる - usdviewは.usdファイルのプレビューやパラメータ値が確認できる便利なツール - waylandの場合はxwayland経由でX11を使うようにフォールバックしたうえで ダウンロードした中に入っている usd/scripts/usdview_gui.sh を動かす
OpenUSDを開いてみる - usdviewが立ち上がる
OpenUSDを開いてみる - usdview_gui.sh は引数を与えずに起動すると青い球体の単純なシーンを デフォルトで読み込んでusdviewを立ち上げるようになっているので青い球がある
OpenUSDを開いてみる ここでシーンの ツリー構造が見れる ここでオブジェクトの プロパティを確認できる
OpenUSDを開いてみる - もう少し複雑なシーンを開いてみる OpenUSDのホームページからKitchen Setをダウンロードする - https://openusd.org/release/dl_downloads.html#assets
OpenUSDを開いてみる - Kitchen_setを展開すると大量のusdファイルが 含まれていることがわかる - - OpenUSDは複数ファイルで一つのシーンを構築する ことがある Kitchen_set.usdを開いてみる
OpenUSDを開いてみる
OpenUSDを開いてみる - 複雑なツリー構造のシーンが開けた
OpenUSDを書いてみる
OpenUSDを書いてみる - OpenUSDはバイナリ版の.usdcとアスキー版の.usdaがある - 拡張子が.usdだった場合は内部に含まれるのは上記のどちらか - アスキー版はテキストエディタで開ける - まずは手作業でテキストエディタを使って.usdaを作ってみよう
OpenUSDを書いてみる - Sphereを一つ表示するOpenUSDのファイル
OpenUSDを書いてみる - Sphereを一つ表示するOpenUSDのファイル - OpenUSDの要素は Prim という “hello”というXform型のtransform用のPrimの子要素として “world”というSphere型のPrimが定義されている このときこのSphereは “</hello/world>” という階層構造の パス を持っていることになる - このパスは SdfPath という表現形式で表現される イメージとしては こういうツリー構造
OpenUSDを書いてみる - usdviewで開いてみると確かに球が一つのシーンが見える - $ usd/scripts/usdview_gui.sh test.usd
OpenUSDを書いてみる - Primにプロパティを持たせてみよう
OpenUSDを書いてみる - 色や(分かりにくいが)大きさも変わっている
OpenUSDを書いてみる - プロパティはキーフレームを持つことができる - 次は1フレーム目で translateが原点、100フレーム目で y座標が5に移動する例 メタデータでアニメーションの time codeの範囲を指定している
OpenUSDを書いてみる - usdviewで開いてタイムラインを動かすと動くことがわかる
OpenUSDを書いてみる - プロパティ名は自由だが、Schemaというので定められたプロパティもある(後述) 例えばスキーマにないhoge:fugaという適当なfloat型のプロパティをもたせたとしても、 ちゃんとusdviewで確認できる
OpenUSDを書いてみる - スキーマという定義されているプロパティのセットがある - いくつかのカテゴリに分けられてドキュメントされている - UsdGeom: https://openusd.org/release/api/usd_geom_page_front.html - UsdLux: https://openusd.org/release/api/usd_lux_page_front.html - UsdMedia: https://openusd.org/release/api/usd_media_page_front.html - UsdPhysics: https://openusd.org/release/api/usd_physics_page_front.html - UsdRender: https://openusd.org/release/api/usd_render_page_front.html - UsdShade: https://openusd.org/release/api/usd_shade_page_front.html - などなど
OpenUSDを書いてみる - スキーマにはIsA SchemasとAPI Schemasがある - IsAはC++クラスのUsdTyped を継承していて、その Primの型となる - 例えばXformとかSphereとかは、UsdGeomXformableやUsdGeomSphereのC++の型に対応している - API SchemasはPrimの型に追加できる HasA的なプロパティのセット - ものによって一つの Primに一つだけのものから複数つけられるものもある - 以下のあたりのドキュメントを見ると良い - https://openusd.org/release/glossary.html#isa-schema - https://openusd.org/release/glossary.html#usdglossary-apischema
OpenUSDを書いてみる - スキーマにも継承構造があったりする - ↓はレンダリングに関わる周りの継承構造 画像は https://openusd.org/dev/api/class_usd_geom_xformable.html より引用( 2025/11/14アクセス)
OpenUSDを書いてみる - スキーマは自分で追加したりもできる - - 以下のドキュメントを参照のこと https://openusd.org/release/tut_generating_new_schema.html スキーマはPythonやC++のAPIで触ることもできる - 次はPython APIで触ってみる - ここからPythonで触るのは次のチュートリアルの内容なども参考にしている https://openusd.org/release/tut_usd_tutorials.html 詳しい解説が欲しければ上記チュートリアルのページを確認すること
OpenUSDをPythonAPIで触る
OpenUSDをPythonAPIで触る - 次のPythonコードを実行する pythonを呼ぶ前に環境変数などの 設定スクリプトを 呼ぶことを忘れない
OpenUSDをPythonAPIで触る - HelloWorld.usdaが作られている
OpenUSDをPythonAPIで触る - スキーマで使えるプロパティを列挙してみる - pythonのインタプリタで対話的に実行してみる
OpenUSDをPythonAPIで触る - プロパティを次のようにして Python APIから追加できる - Python APIはOpenUSDのファイルを 簡単に操作したり確認したりできるので便利 - バリデーションツールとかをTAの方が作ったりとか 使いやすいPython APIがあるのは嬉しい
OpenUSDとレイヤー
OpenUSDとレイヤー - OpenUSDの一番の特徴は レイヤー 機能 OpenUSDのロゴもレイヤーを表しているらしい
OpenUSDとレイヤー - フォトショップの.psdみたいに3Dシーンもレイヤーにした! - などと説明されることがある
OpenUSDとレイヤー - フォトショップの.psdみたいに3Dシーンもレイヤーにした! - - などと説明されることがある 何が嬉しいの?
OpenUSDとレイヤー - フォトショップの.psdみたいに3Dシーンもレイヤーにした! - - などと説明されることがある 何が嬉しいの? この説明単体だと利点がよくわからないので詳しく説明します
OpenUSDとレイヤー - OpenUSDが解決すべき課題から見ていこう - そもそも新しいシーンファイルを作ったのは課題があったから
OpenUSDとレイヤー - 地獄のウォーターフォール - 前の工程が終わってから次の工程に渡す 背景の人が作業 / キャラモデラーが作業 アニメーションの人がキャラアニメーションを乗せる そのあとライティングの人がライティングする というのが順番に行われる 背景モデル キャラモデル アニメーション カメラ・構図・ライティング
OpenUSDとレイヤー - 地獄のウォーターフォール - - 前の工程が終わってから次の工程に渡す 背景の人が作業 / キャラモデラーが作業 アニメーションの人がキャラアニメーションを乗せる そのあとライティングの人がライティングする というのが順番に行われる 順番にしか作業できない!・後戻りが大変辛い! 背景モデル キャラモデル アニメーション カメラ・構図・ライティング
OpenUSDとレイヤー - 地獄のウォーターフォール - - 前の工程が終わってから次の工程に渡す 背景の人が作業 / キャラモデラーが作業 アニメーションの人がキャラアニメーションを乗せる そのあとライティングの人がライティングする というのが順番に行われる 順番にしか作業できない!・後戻りが大変辛い! ⇒ なんとか並列に作業できるようにしたい ⇒ そこでレイヤー
OpenUSDとレイヤー - Photoshopの.psdは一つのファイルに多数のレイヤーが入っている OpenUSDは一つのファイルが一つのレイヤーを表す - フォルダレイヤーのように他のレイヤーを複数参照して含むレイヤーとかも作れる レイヤー 3 レイヤー 2 レイヤー 1 レイヤー 0
OpenUSDとレイヤー - 各レイヤーは独立した情報を持っている - .psdであるレイヤー 1を編集したらレイヤー 2のデータが勝手に書き換わることはない - レイヤーごとに人をアサインすれば同時作業してもコンフリクトしない! レイヤー 3 それぞれ 別ファイル レイヤー 2 レイヤー 1 レイヤー 0 それぞれ 別の人が 編集する
OpenUSDとレイヤー - .psdのレイヤーについてもう少し見てみよう レイヤー 3 レイヤー 2 レイヤー 1 レイヤー 0
OpenUSDとレイヤー - レイヤーは独立の情報を持っている レイヤー 3 レイヤー 2 レイヤー 1 レイヤー 0
OpenUSDとレイヤー - レイヤーは独立の情報を持っている - 例えばレイヤー 1を書き換えてもレイヤー 2のデータには影響しない レイヤー 3 レイヤー 2 レイヤー 1 レイヤー 0
OpenUSDとレイヤー - レイヤーは各ピクセル位置にどの色を置くかの情報を持っている (10, 10) に(0, 0, 1)を配置したい レイヤー 3 (10, 10) に(0, 1, 1)を配置したい レイヤー 2 レイヤー 1 (20, 20) に(0, 1, 1)を配置したい レイヤー 0 (25, 25) に(1, 0, 0)を配置したい
OpenUSDとレイヤー - レイヤーは各ピクセル位置にどの色を置くかの情報は 最終的な作品の画像に反映されないこともある - 上のレイヤーで塗りつぶされると最終的には反映されないピクセルになる (10, 10) に(0, 0, 1)を配置したい レイヤー 3 (10, 10) に(0, 1, 1)を配置したい レイヤー 2 レイヤー 1 (20, 20) に(0, 1, 1)を配置したい レイヤー 0 (25, 25) に(1, 0, 0)を配置したい 上のレイヤーで塗 りつぶされる
OpenUSDとレイヤー - レイヤーは各ピクセル位置にどの色を置くかの情報は 最終的な作品の画像に反映されないこともある - 上のレイヤーで塗りつぶされると最終的には反映されないピクセルになる - つまりレイヤーに含まれるのは最終ピクセルデータではなく、 このピクセルに色を配置したいという意向 のみ含まれている - 最終結果の画像データはそのレイヤーの意向をレイヤー合成のルールに従って 下から順に重ね合わせたりブレンドした結果となる
OpenUSDとレイヤー - レイヤーにあるのは最終データではない こういうデータを配置したいという 意見 <opinion> が含まれている 最終的な画像は合成システムを通した結果 として手に入る
OpenUSDとレイヤー - レイヤーにあるのは最終データではない こういうデータを配置したいという 意見 <opinion> が含まれている 最終的な画像は合成システムを通した結果 として手に入る - OpenUSDのレイヤーも同じ
OpenUSDとレイヤー - 各.usdファイルのレイヤーに含まれるデータは 最終的なシーンデータそのものではない - 最終的なシーンデータは各レイヤーを特定の合成ルールに従って合成した結果として手に入る - 最終的なシーンデータがそのままシリアライズされているわけではない! 最終的なシーンデータは合成しないとわからない
OpenUSDとレイヤー - ルートとなる.usdファイルから参照しているファイルを辿って構築された シーンツリーのことをOpenUSDではStageと言うらしい - 各.usdファイルに含まれるPrimの定義は、 ステージにおけるPrimと区別する場合はPrimSpecと呼ばれる - - Opinionsという用語も使われる 各レイヤーに書かれたPrimSpecをOpenUSDの合成エンジンが 合成して最終的なステージのPrimのリストが手に入る
OpenUSDとレイヤー - 簡単な例でどうやって作業分割がレイヤーで行えるかを見てみよう 例えば、最初のレイヤーでは背景を作る - この時点ではまだ作り込みをしていない簡易的なモデルだとする 背景を作るために仮のライトを置いて作業をする
OpenUSDとレイヤー - 次のレイヤーでキャラクターを追加する overはdefと同じようにPrimについて記述するが、 すでにPrimがdefされている場合にのみ意味がある 上書き用のやつ
OpenUSDとレイヤー - 最後のレイヤーで既存の仮ライトを消して最終ライトを配置する activeはPrimのメタデータなので プロパティとは書く場所が違う 非アクティブで上 書きしている
OpenUSDとレイヤー - これらの.usdのレイヤーをサブレイヤーとして レイヤースタックする.usdを作る
OpenUSDとレイヤー - このレイヤースタックの.usdファイルを開くとOpenUSDの合成を経て最終シーンが 手に入る
OpenUSDとレイヤー - 背景部門の人が背景をアップデートする → 最終合成シーンもアップデートされる
OpenUSDとレイヤー - アニメーション部門の人がアニメーションをアップデートする → 最終合成シーンもアップデートされる
OpenUSDとレイヤー - 合成は生きている! - 合成元を更新すれば最終シーンにも反映される
OpenUSDのレイヤー合成ルール
OpenUSDのレイヤー合成ルール - レイヤー合成のルールについて - .psdのルール - レイヤーはフォルダを含むリストになっている - 基本的に下より上の方が強い - フォルダーとかがある場合はフォルダーの中を合成したものを親階層で合成する - よく定義された曖昧性のないルールが存在する
OpenUSDのレイヤー合成ルール - レイヤー合成のルールについて - OpenUSDのルール - LIVRPSの原則 - Pixarの経験則で導き出された最適な合成ルール
OpenUSDのレイヤー合成ルール - LIVRPSの原則 - - Local(サブレイヤ) Inherits(継承) VariantSets(バリアントセット ) References(リファレンス) Payload(ペイロード) Specializes(特別化) あるPrimをベースにして別のPrimを作ったり、別のPrimを取り込んだり 詳しくは色々解説されているサイトがあるので各自見てほしい USDの「コンポジション」概要 | Reincarnation+#Tech
ここまでのまとめ - まとめ - OpenUSDは各ファイルが各レイヤーとなる レイヤーに書かれているのは PrimSpec(Opinion) - 最終シーンは合成エンジンを通した結果としてのみ手に入る レイヤー合成は曖昧性無くよく定義されている - LIVRPSの原則
その他 OpenUSD周りについて - ここから以下の内容をそれぞれ1ページでザクッと紹介する - OpenUSDとアニメーション OpenUSDと色空間 MaterialX プラグイン機構 OpenUSDが定義しないこと
OpenUSDとアニメーション - 基本的に頂点アニメーションがベイクされている - - UsdSkelとかを使うとボーン情報も持てるので、スキニングもできる - - 頂点データが timesampleされている UsdSkel : USD Skeleton Schema and API リグ周りはまだまだ発展途上だが、OpenExecのような データ駆動で計算が走る仕組みのプラグインとかが作れるようになりつつある - https://openusd.org/files/BOFSiggraph2024.pdf
OpenUSDと色空間 - 作業用色空間とかテクスチャの色空間などがきちんと定義できる - 詳しくは以下のドキュメントを参照 https://openusd.org/release/user_guides/color_user_guide.html
OpenUSDとMaterialX - OpenUSDのマテリアル表現としてMaterialXも追加で使える - - MaterialXはOpenUSDとは独立したオープンのマテリアルグラフの規格 - ノードベース! OpenUSDはこのMaterialXを良い感じに組み込んで取り込んでいる 詳しくは公式ドキュメント https://openusd.org/release/api/_page__material_x__in__hydra__u_s_d.html OpenPBRはこのMaterialXのノードを使って実装されている MaterialXのすべてのノードに対応すれば OpenPBRも対応できる
OpenUSDとプラグイン機構 - プラグイン機構でカスタマイズ可能 - プラグイン機構がある 独自スキーマを追加したり 独自の機能を追加したり 今回紹介する HydraプラグインもOpenUSDのプラグイン機構を利用している
OpenUSDが定義しないこと - ワークフローは定義されない - 非常に柔軟なファイル構造なのでどうやって使っていくかは自由度がある - - Pythonのスクリプトが書けるので、各人がレイヤーをサーバーにアップロードする前に 命名規則とか諸々チェックするとかそういう仕組みを作れる - - どのようにレイヤーを分割してどのようにワークフローを構築するか考える必要がある 逆に言うとそういう仕組みを作ってちゃんとしたデータの扱いをスタジオ側が構築してやる必要がある こういうのパイプラインって呼ぶんですかね?ワークフローとパイプラインは違うらしいが。。。 パイプラインで共有サーバーにデータをアップロードするのは publishというらしい publishしたアセットのバージョン管理や publishする際のバリデーションなどは必須 OSSのパイプラインツールとして AYONとか言うのがあるらしいので見てみると面白いかも Maya/Houdiniで実践的な USDワークフローを試したい バージョン管理とかもOpenUSDの範囲外なので そこらへんはスタジオ各社なにかツールを作る必要がありそう
雑感 - レイトレ合宿のシーンファイルとしてサクッと使うには結構仕様が重量級 - レイトレ合宿提出用の適当なシーン表現がほしいだけなら glTFの方が向いている気がする - - 別に複数人で並列に作業しつつ巨大なシーンを作るわけではない…… 業界標準のシーン形式がどうなっているか知りたい・自分のレンダラーを 業界標準のシーンに対応したいという熱い思いがあるなら ぜひOpenUSD対応をやってみると良いと思う
OpenUSDをDCCツールで触ってみる
OpenUSDを実際にDCCツールで触ってみる - HoudiniとMayaとBlenderについて、 それぞれのOpenUSDの扱いを紹介していく
HoudiniとOpenUSD - HoudiniがOpenUSDの扱いについて一番ちゃんとしている SolarisというコンテキストでOpenUSDのステージ構築を行える
HoudiniとOpenUSD - が、ノードはOpenUSDのAPIと対応しているわけではない - - どういう操作をするかとかをちゃんと把握する必要がある ノードを繋いでOpenUSDにテキストで書き出してどうなっているか見るとかInspect Active Layerす るとかで確認すると良い。
HoudiniとOpenUSD - HoudiniはIndie版が安い・無料でApprenticeという評価版もある - - OpenUSDの勉強には良いので触ってみるのはおすすめ 余談だけどプログラマーにとってはわりかし直感的でとっつきやすいソフトだと思う - データがきちんと見えていてデータに対して操作を行っていくというのが 非常に安心して追いかけられる 頂点データのリストとかも眺めつつ作業できる
MayaとOpenUSD - Mayaは外部のシーンをリファレンスで扱えるUFEという仕組みをつかって OpenUSDを扱うプラグインがある
MayaとOpenUSD - 次のブログ記事が良い解説なので読むと良い - https://fereria.github.io/reincarnation_tech/maya/maya_usd/01
BlenderとOpenUSD - BlenderはリリースノートでOpenUSDの対応を謳っている https://www.blender.org/download/releases/4-2/
BlenderとOpenUSD - 現状のBlenderのOpenUSD対応は最悪 - .usdファイルを全てフラット化して .blendファイルに変換して読み込む
BlenderとOpenUSD - 現状のBlenderのOpenUSD対応は最悪 - - .usdファイルを全てフラット化して .blendファイルに変換して読み込む レイヤーとかリファレンスとか全部破壊される - 「複数人でレイヤーを編集する・レイヤーの合成結果は生きた状態である」というのが 満たされていない .usdを.blendに読み込むときに全部フリーズし固定化してしまう
BlenderとOpenUSD - 公式がBlenderでのOpenUSDの開発方針を明示してはいないが…… - - https://code.blender.org/2022/02/overrides-workshop/ のブログでBlender内部のコレクションやオーバーライド表現の表現力を上げてから OpenUSDを対応していくみたいな方針が見える OpenUSDのコレクションを Blenderの内部データに完全にマッピングしようという プロジェクトとかも過去に行われていたりする BlenderはどうもOpenUSDを別コンテキストにせず扱おうとしているらしい……
BlenderとOpenUSD - BlenderはどうもOpenUSDを別コンテキストにせず扱おうとしているらしい…… - Houdiniですら別コンテキストなのにかなり無謀 - 100% OpenUSDと互換性がないとラウンドトリップしたときに情報が欠ける - OpenUSDはまだまだ開発が続いており枯れたファイル形式でもない - OpenUSDにはプラグイン機構もあり、プラグインで追加されたPrimのタイプを Blenderが対応するのはどうするつもりなのか……
BlenderとOpenUSD - MaterialX対応についても止まっている - 次のIssueがMaterialXの話をしている - https://projects.blender.org/blender/blender/issues/100569 - ここでMaterialXのシェーダーコンテキストを作ろうというアイデアに対して - BlenderのCyclesのノードエディタを使えるべきと開発者の一人が述べている - Blenderは統合3D環境であり、一貫したUIの提供がBlenderの良さ - 同じような機能を別のコンテキストで作るのはツール利用者を混乱させる - という意見…… - ノードグラフを扱うという話でなければOpenPBRとしてPrincipled BSDFを出力する機能は実装されたらしい Blender Principled BSDF と OpenPBR(MaterialX) + USD のメモ
BlenderとOpenUSD - Blenderは統合3Dソフトであることに誇りと夢を持って開発をしているみたい - これは夢があって良い - しかし、他のDCCツールのOpenUSDを使って種々のソフトウェアを やり取りする業界の流れと異なる動きをしている…… OpenUSDのエコシステムとは独立のBlender独自のエコシステムを作りつつある -
BlenderとOpenUSD - ごく最近になってミーティングノートでBlenderでOpenUSDを リファレンスとして読み込める方向にしてみようという話が出ている - - https://devtalk.blender.org/t/2025-09-25-pipeline-i-o-module-meeting/42469 https://devtalk.blender.org/t/2025-10-09-pipeline-i-o-module-meeting/42870 これが進めばBlenderのOpenUSD対応は良くなりそうではある - が、今年秋にようやく話が出てきたレベルなので対応はとても遅れている ……
OpenUSDの学習方法 - OpenUSDを勉強したい場合 - 1. usdaを手書きをしてみる 2. usdaをpythonで書き出してみる 3. HoudiniでOpenUSDを使ってシーンを作ってみる というのが良いと思う - Blenderは今のところOpenUSDの扱いはダメダメなので忘れたほうが良い。
OpenUSDをビルドする
OpenUSDをビルドする - OpenUSDのステージは合成結果 各ファイルにはPrimSpecしか書かれていない 合成エンジンを正しく動作させないとステージは手に入らない - glTFならバイナリを自分で読んで使うのも難しくなかったが、 OpenUSDを仕様どおりに自分で読むのは相当大変
OpenUSDをビルドする - OpenUSDのステージは合成結果 各ファイルにはPrimSpecしか書かれていない 合成エンジンを正しく動作させないとステージは手に入らない - glTFならバイナリを自分で読んで使うのも難しくなかったが、 OpenUSDを仕様どおりに自分で読むのは相当大変 OpenUSDのライブラリを使って合成エンジンなどを OpenUSDのライブラリに任せよう!
OpenUSDをビルドする - まずはOpenUSDをGitHubからcloneしてくる - git clone https://github.com/PixarAnimationStudios/OpenUSD.git - バージョンのtagが打たれているので必要に応じて必要なタグを checkoutする
OpenUSDをビルドする - CMakeを入れる pythonを準備し、以下の依存を入れる - PySide6 or PySide2 PyOpenGL
OpenUSDをビルドする - pythonのビルドスクリプトを実行する - python OpenUSD/build_scripts/build_usd.py /path/to/my_usd_install_dir - オプションは色々あるけど必要に応じてつける - ビルド時のログの様子→ - Python付きでビルドしたうえで ビルド後に示されるPATHとPYTHONPATHの 環境変数を設定すればビルドしたpythonのpxrなども使える
OpenUSDをビルドする - ビルド自体は非常に簡単にできる - - 依存関係のダウンロードなども pythonスクリプトが勝手にやってくれる ビルドにはそれなりの時間とディスク容量とメモリを食う - ビルド時間はビルド構成にも依るが私の構成だと - LinuxのRyzen 9 9900Xだと-jでフル並列にして 8分くらい - ちょっと古いゲーミングノート PCだと45分くらい - Circle CIのlargeインスタンスだと 1時間半くらい - GitHub Actionsはメモリが足りずビルド中に OOM
OpenUSDをビルドする - CMakeでビルドしたライブラリを使うにはインストール先のディレクトリを渡して find_packageでpxrを取得すると簡単に使える - いくつかの小さいライブラリに分かれているみたいなので リンクするときは必要なものを列挙する
OpenUSDをビルドする - ビルド環境はVFX Reference Platformを参考にすると良い - https://vfxplatform.com/ 様々なDCCツールが環境を合わせてビルドする指針となっている
OpenUSDをビルドする - ビルドするコンパイラとかそのバージョン、ライブラリバージョンが違うとABIが異な りプラグインが読み込めないなどが発生する - 例えばLinux環境はgcc前提なのでclangとかでビルドしても、 そのOpenUSDでプラグインを作ると既存の DCCツールと互換性のない プラグインになってしまう
OpenUSDをビルドする - ビルド環境はVFX Reference Platformを参考にすると良い - https://vfxplatform.com/ 様々なDCCツールが環境を合わせてビルドする指針となっている
OpenUSDをビルドする - Linux環境であればVFX Reference Platformのビルド環境はdockerで 公開されているのでこれを使うと良い - https://github.com/AcademySoftwareFoundation/aswf-docker
OpenUSDをビルドする - ビルド時に指定したインストール場所に必要ファイルが書き出される - - ビルド時のオプションを適用した includeやlibなどが手に入る C++でこのライブラリを使えばOpenUSDをC++のプログラムから扱えるようになる - ドキュメントは以下に公開されている https://openusd.org/release/api/index.html ドキュメント読んだりソース読めば使っていけるはず
OpenUSDを学ぶ - OpenUSDを知るのに役に立ったリンクを並べておきます - - OpenUSD公式チュートリアル - https://openusd.org/release/intro.html OpenUSD公式APIドキュメント - https://openusd.org/release/api/index.html HoudiniのOpenUSDのやつ - https://www.sidefx.com/ja/docs/houdini/solaris/usd.html あんどうめぐみ@れみりあ さんのブログ - https://fereria.github.io/reincarnation_tech/usd/what_is_usd OpenUSDのスライド - https://www.slideshare.net/slideshow/usd-79288174/79288174 他にもいろいろあった気がする/ Web上にいろいろ資料があるので各自検索してください
Hydraレンダラープラグインを作る
Hydraレンダラープラグインについて - OpenUSDは合成結果が最終シーンであることは分かった - - USDの各レイヤーを操作したい場合 pythonバインディングや、 C++のライブラリで行える しかし、レンダラーを作る場合は各レイヤーではなく 統合されたあとのステージの情報がほしい どうやって.usdファイル群からレンダリング用の最終的な フラット化されたシーンデータを手に入れるのか
Hydraレンダラープラグインについて - OpenUSDは合成結果が最終シーンであることは分かった - - USDの各レイヤーを操作したい場合 pythonバインディングや、 C++のライブラリで行える しかし、レンダラーを作る場合は各レイヤーではなく 統合されたあとのステージの情報がほしい どうやって.usdファイル群からレンダリング用の最終的な フラット化されたシーンデータを手に入れるのか ⇒ Hydra APIを使う!
Hydraレンダラープラグインについて - HydraはOpenUSDのライブラリの中で定義されているAPI ただし.usdファイルには依存しておらず、 任意のシーン表現に対してこのAPIを使える - 例えばMayaのシーンツリーをこの API経由でHydraレンダラーに渡したりできる スクショは https://openusd.org/files/Siggraph2019_Hydra.pdf より引用( 2025/11/14アクセス)
Hydraレンダラープラグインについて - Hydraはプログラミング言語のLanguage Server Protocol (LSP) みたいなもの - Hydraが無い場合はレンダラーが各 DCCツール向けに専用のコードを書く必要があった Hydraという共通化された APIのおかげで開発が楽になる - Hydraを中心にたくさん首が伸びているようなのでHydraという名前らしい? スクショは https://www.khronos.org/assets/uploads/developers/presentations/Autodesk_-_USD_and_MaterialX_on_the_Web.pdf より引用( 2025/11/14アクセス)
Hydraレンダラープラグインについて - HydraのAPIを経由して例えば以下のようなやり取りをする - HostのDCCツールからシーンデータ(メッシュなど)の差分をレンダラーに渡す レンダラーから HostのDCCツールのビューポートに描画した内容のテクスチャを返す Hostでビューポートの更新が必要なときにレンダリングを呼び出す スクショは https://www.khronos.org/assets/uploads/developers/presentations/Autodesk_-_USD_and_MaterialX_on_the_Web.pdf より引用( 2025/11/14アクセス)
Hydraレンダラープラグインについて - OpenUSDのファイルのレンダリングという観点でHydraを見ると、 - OpenUSDのフラット化した結果を HydraのAPI経由で受け取れる - - HdEngineとかHdxTaskControllerSceneIndexとかのあたりのAPIを使うと 開いたOpenUSDのステージをUsdImagingStageSceneIndex経由で良い感じに Hydra APIに変換してレンダラーに渡してくれる OpenUSDのステージをHydraのAPIに変換するAPIはOpenUSDの中に用意されている (usdImagingなど)ので自分でなんとかする必要はない OpenUSDの中にアニメーションする要素があった場合、 アニメーションした際の差分の要素だけ受け取れる
Hydraレンダラープラグインについて - Hydraレンダラープラグインに対応するとHydraに対応したDCCツールでも使える ようになる - - - 今回紹介するのは HoudiniとBlenderの事例 ただし一つのレンダラープラグインのバイナリがすべてのDCCツールで動くわけではない DCCツールに組み込まれているOpenUSDのバージョンやビルドオプションに合わせてビルドした プラグインじゃないとDCCツールからは読み込めない そのため現実的にはBlenderのバージョンごとにHydraレンダラーをビルドしたり HoudiniのバージョンごとにHydraレンダラーをビルドする必要はある 動作するソースコードは後日 https://github.com/MatchaChoco010/kanahebi-renderer で公開予定
Hydraレンダラープラグインの構造 - Hydraレンダラープラグインは最低限以下の構造を持ったフォルダ - 実際はplugInfo.jsonの位置に自由度はあるが、 plugInfo.jsonと動的ライブラリ( .soもしくは.dll)を含む形にはなっている Linux - Windows プラグインは動的ライブラリとしてホスト側にロードされる仕組み - なのでABIの不一致とかで動かなくなりうる ビルドに使うOpenUSDのバージョンをホストのツールと合わせる必要があるのはそのため
Hydraレンダラープラグインの構造 - 先のフォルダをDCCツールのOpenUSDが読み込むパスに配置すると このプラグインがツールに読み込まれる - OpenUSDが読み込むパスは環境変数 PXR_PLUGINIPATH_NAMEにplugInfo.jsonのある ディレクトリのパスを入れれば良い 例:
Hydraレンダラープラグインの構造 - プラグインをビルドすると動的ライブラリの中に.pxrctorというセクションが作られる - dllロード時にこの .pxrctor内部のstatic関数が呼ばれる - - その際に必要なクラスがOpenUSDのシステムに登録されることになる このあたりのロードの仕組みは pxr/base/arch/attributes.h あたりのコードを見ると良い - Arch_ConstructorInit の中で Arch_ConstructorEntry の関数ポインタを順番に呼び出していく処理がある その際にプラグインがビルドされたOpenUSDのバージョンとホストのOpenUSDのバージョン番号が 等しいことも確認しているので、ホストとバージョンの違うOpenUSDでビルドされたプラグインは動かない
plugInfo.json - まずはdllの中身より前に plugInfo.jsonを見ていく - plugInfo.jsonは次のような構造の jsonファイル
plugInfo.json - プラグインの名前やdllとresourceの パスなどが指定されている プラグインのエントリーとなるクラスと その継承元のbaseクラスも指定している - 今回はHdRendererPluginを継承した HdKanahebiRendererPluginがメインのクラスになる
Hydra 2.0について - 動的ライブラリの中身について語る前にHydraのバージョンについて - Hydraは現在Hydra 2.0のAPIに少しずつ移行中 - OpenUSDのライブラリ内部には Hydra 1.0時代のAPIも大量に含まれている OpenUSDのサンプルの hdTinyとかを参考にすると Hydra 1.0時代のコードを書いてしまう 現状完全移行はしておらず 1.0時代のAPIを使わざるを得ない部分もあったりはする - - が、徐々にHydra 2.0がメインになるように少しずつAPIが足されたり変わったりしてる 今回はHydra 2.0をベースに説明していく
Hydra 2.0について - Hydra 2.0はシーンの差分通知などの仕組みが SceneIndexという仕組みになったというのが大きな変更点 - - SceneIndexが出てくればHydra 2.0時代のAPIということになる DirtyBitsとかが出てきたら Hydra 1.0時代のAPIを使っているので注意 SceneIndexはシーン情報の受け渡しの中核を担うもの - 次の公式ドキュメントに必要なことは書かれているので読むべし https://openusd.org/release/api/_page__hydra__getting__started__guide.html
動的ライブラリ内部のメインのクラス構造 - 動的ライブラリには次のようなクラスが含まれている - - HdKanahebiRendererPlugin - - 自作レンダラーの名前を kanahebiとした場合 HdRendererPluginを継承したクラス プラグインのエントリーポイント HdKanahebiRenderDelegate - HdRenderDelegateを継承したクラス レンダラーの中心的なクラス
動的ライブラリ内部のメインのクラス構造 - 動的ライブラリには次のようなクラスが含まれている - - 自作レンダラーの名前を kanahebiとした場合 HdKanahebiRenderBuffer - HdRenderBufferを継承したクラス レンダリング先のレンダーターゲットのバッファ ここにレンダリング結果の RGBの値を格納する AOVの数だけ作られる (color / depth / material id などなど…… )
動的ライブラリ内部のメインのクラス構造 - 動的ライブラリには次のようなクラスが含まれている - - 自作レンダラーの名前を kanahebiとした場合 HdKanahebiRenderPass - HdRenderPassを継承したクラス _Execute()メソッドでレンダリングを行う ホスト側でレンダリングを呼び出す際にこのクラスのインスタンスが作られて _Execute()が呼び出されることになる
動的ライブラリ内部のメインのクラス構造 - 動的ライブラリには次のようなクラスが含まれている - - 自作レンダラーの名前を kanahebiとした場合 HdKanahebiSceneIndexObserver - HdSceneIndexObserverを継承したクラス SceneIndexからシーンの変更を受け取る役割
動的ライブラリ内部のメインのクラス構造 - 最初にプラグインが読み込まれるとプラグインレジストリに HdKanahebiRendererPluginが登録される HdKanahebiRendererPlugin
動的ライブラリ内部のメインのクラス構造 - レンダラーがホスト側で必要になると HdKanahebiRendererPlugin::CreateRenderDelegate()から HdKanahebiRenderDelegateが作られる HdKanahebiRendererPlugin HdKanahebiRenderDelegate HdRenderDelegate* CreateRenderDelegate(); もしくは HdRenderDelegate* CreateRenderDelegate(HdRenderSettingsM ap const& settings_map);
動的ライブラリ内部のメインのクラス構造 - ホストが必要とするAOVのRenderBufferの作成が行われる - HdkanahebiRenderDelegate::CreateBprim() ウィンドウサイズの変更などでも RenderBufferの再作成が行われる HdKanahebiRenderDelegate HdBprim* CreateBprim(TfToken const& type_id, SdfPath const& bprim_id); HdKanahebiRenderBuffer
動的ライブラリ内部のメインのクラス構造 - 作られたRenderDelegateの HdKanahebiRendererPlugin::SetTerminalSceneIndex()が呼ばれる - ここで渡ってくる SceneIndexにHdKanahebiSceneIndexObserverを登録する HdKanahebiRenderDelegate void SetTerminalSceneIndex(const HdSceneIndexBaseRefPtr& sceneIndex) の引数のsceneIndexにObserverを登録する HdKanahebiSceneIndexObserver
動的ライブラリ内部のメインのクラス構造 - ホストでレンダリングを呼び出すとレンダリング開始前に HdKanahebiRenderDelegate::Update()が呼ばれる - ここでGPUに頂点バッファをアップロードしたりする HdKanahebiRenderDelegate void Update();
動的ライブラリ内部のメインのクラス構造 - ホストでレンダリングを呼び出すと HdKanahebiRenderDelegate::CreateRenderPass()が呼ばれる - HdKanahebiRenderPassが作られる HdKanahebiRenderDelegate HdKanahebiRenderPass HdRenderPassSharedPtr CreateRenderPass(HdRende rIndex* index, HdRprimCollection const& collection)
動的ライブラリ内部のメインのクラス構造 - その後HdKanahebiRenderPass::_Execute()が呼ばれて レンダリング処理を走らせる HdKanahebiRenderDelegate HdKanahebiRenderPass void _Execute(HdRenderPassStateShared Ptr const& render_pass_state, TfTokenVector const& render_tags)
動的ライブラリ内部のメインのクラス構造 - ホストからのレンダリング結果の受け取りは RenderBufferの Map() / Unmap() もしくは GetResource でテクスチャを 返してホストに結果を返す VtValue GetResource(bool multiSampled) void* Map() / void Unmap() HdKanahebiRenderBuffer
SdfPathとTfToken - まずはよく使われる基本の型を紹介する - SdfPathはPrimのパスなどの階層構造を持ったパスを表現する型 - - 例えば /Meshes/SphereMesh とか 例えば /materials/material1 とか pxr/usd/sdf/path.h TfTokenはいろいろなところで使われるトークン文字列 - 例えばAOVの種類のcolorとdepthとか 例えばPrimのタイプのmeshとかgeomSubsetとか そういうタイプを表現する文字列を通常の文字列比較より効率良くやるためのものらしい pxr/base/tf/token.h
HdRendererPlugin - HdRendererPluginを継承した型を プラグインとして登録する - CreateRenderDelegate()や DeleteRenderDelegate()を持ってる IsSupported()という関数もあり、 gpu対応しているかどうかを返せる 新しいバージョンでは IsSupportedの オーバーロードも必要
HdRendererPlugin - 実装の.cpp側には以下のようなTF_REGISTRY_FUNCTIONというマクロで プラグインレジストリへの登録処理を書く必要がある - この部分が.pxrctor領域に格納されてレンダラープラグインの登録処理が プラグイン読み込み時に走るようになる
HdRenderDelegate - レンダラープラグインが作成するレンダラーの実体 このクラスを継承したクラスをRendererPluginでCreateしたら返す pxr/imaging/hd/renderDelegate.h
HdRenderDelegate - 実装しないといけない関数はたくさんあるが その多くはHydra 1.0時代のAPIのもの - ただし実装が必須指定なので Hydra 2.0を使う場合でも 1.0のAPIの実装が必要 Hydra 2.0を使うなら ダミー実装でも良いかも
HdRenderDelegate - Hydra 2.0で実装すべき関数は 実装必須の1.0のものも含めて - const TfTokenVector& GetSupportedRprimTypes() const const TfTokenVector& GetSupportedSprimTypes() const const TfTokenVector& GetSupportedBprimTypes() const HdInstancer* CreateInstancer(HdSceneDelegate* delegate, SdfPath const& id) void DestroyInstancer(HdInstancer* instancer) HdRprim* CreateRprim(TfToken const& type_id, SdfPath const& rprim_id) void DestroyRprim(HdRprim* rprim) HdSprim* CreateSprim(TfToken const& type_id, SdfPath const& sprim_id) HdSprim* CreateFallbackSprim(TfToken const& type_id) void DestroySprim(HdSprim* sprim) HdBprim* CreateBprim(TfToken const& type_id, SdfPath const& bprim_id) HdBprim* CreateFallbackBprim(TfToken const& type_id) void DestroyBprim(HdBprim* bprim) HdResourceRegistrySharedPtr GetResourceRegistry() const void SetRenderSetting(TfToken const& key, VtValue const& value) VtDictionary GetRenderStats() const void CommitResources(HdChangeTracker* tracker) HdAovDescriptor GetDefaultAovDescriptor(TfToken const& aovName) HdRenderPassSharedPtr CreateRenderPass(HdRenderIndex* index, HdRprimCollection const& collection) void SetTerminalSceneIndex(const HdSceneIndexBaseRefPtr& scene_index) void Update()
HdRenderDelegate - const TfTokenVector& GetSupportedRprimTypes() const const TfTokenVector& GetSupportedSprimTypes() const const TfTokenVector& GetSupportedBprimTypes() const - Rprim / Sprim / Bprim はそれぞれ レンダリングされるもの / その他ステート / テクスチャやレン ダーターゲットなどのバッファ に対応する
HdRenderDelegate - const TfTokenVector& GetSupportedRprimTypes() const const TfTokenVector& GetSupportedSprimTypes() const const TfTokenVector& GetSupportedBprimTypes() const - ここではレンダラーが対応するタイプのTfTokenのvectorを返すことになる ただしこれらは基本的にHydra 1.0でシーン情報を受け取るために使われるもの Hydra 2.0ではRenderBufferさえ作れればなんとかなるので次のような実装でも動く
HdRenderDelegate - HdInstancer* CreateInstancer(HdSceneDelegate* delegate, SdfPath const& id) void DestroyInstancer(HdInstancer* instancer) HdRprim* CreateRprim(TfToken const& type_id, SdfPath const& rprim_id) void DestroyRprim(HdRprim* rprim) HdSprim* CreateSprim(TfToken const& type_id, SdfPath const& sprim_id) HdSprim* CreateFallbackSprim(TfToken const& type_id) void DestroySprim(HdSprim* sprim) HdBprim* CreateBprim(TfToken const& type_id, SdfPath const& bprim_id) HdBprim* CreateFallbackBprim(TfToken const& type_id) void DestroyBprim(HdBprim* bprim) - Hydra 1.0時代の差分検知のDirtyBitとかを使うRprimやBprim、Sprimを作成破棄するためのもの Hydra 2.0のSceneIndexでシーンデータを受け取るならBprimでRenderBufferだけ作れればとりあえず動く
HdRenderDelegate - HdResourceRegistrySharedPtr GetResourceRegistry() const - HdResourceRegistrySharedPtr を返さないといけないらしい - とりあえずメンバに HdResourceRegistrySharedPtrを一つ持っておいて返せば動く
HdRenderDelegate - void SetRenderSetting(TfToken const& key, VtValue const& value) - レンダラーの設定を Hostから受け取るためのもの - 例えばtarget sppとかexposureの値とか、その他色々必要なものは何でも受け取れる - kanahebi:global:targetsamples のように名前空間をつけたトークンをキーにすると良さそう - また、Houdiniのビューポートの場合 renderCameraPathというキーで ビューポートカメラの SdfPathが手に入るので受け取っておくと良い
HdRenderDelegate - void SetRenderSetting(TfToken const& key, VtValue const& value) - 私のレンダラーでは例えば次のようにして必要なパラメータをホストから受け取っている
HdRenderDelegate - void SetRenderSetting(TfToken const& key, VtValue const& value) - 私のレンダラーでは例えば次のようにして必要なパラメータをホストから受け取っている
HdRenderDelegate - VtDictionary GetRenderStats() const - レンダリングの統計情報を返せる - Houdiniの場合、次の URLで説明されるように UsdRenderers.jsonも用意すると GUI上にレンダリングの進捗 %を表示したりできる - https://www.sidefx.com/docs/hdk/_h_d_k__u_s_d_hydra.html
HdRenderDelegate - void CommitResources(HdChangeTracker* tracker) - GPUにリソースをコミットするタイミングの関数だった - が、Hydra 2.0時代になったら Update()でやっても良さそう - 私のレンダラーでは単に空の実装にしている
HdRenderDelegate - HdAovDescriptor GetDefaultAovDescriptor(TfToken const& aovName) - 対応しているAOVのタイプに対応するピクセルの値の型を返す - 最低限HdAovTokens->colorとHdAovTokens->depthを返したほうが良さそう
HdRenderDelegate - HdRenderPassSharedPtr CreateRenderPass(HdRenderIndex* index, HdRprimCollection const& collection) - RenderPassの作成の起点 - 自分のレンダラーの RenderPassを作成して返すと良い
HdRenderDelegate - void SetTerminalSceneIndex(const HdSceneIndexBaseRefPtr& scene_index) - RenderDelegateにSceneIndexがセットされるときに呼ばれる関数 - 基本的にシーンがセットアップされて RenderDelegateが作られたら一度呼ばれるみたい - ここでSceneIndexの変更を購読することで Hydra 2.0のSceneIndexでの シーン情報取得ができるようになる - ちなみにterminalというのはSceneIndexは連鎖させてパイプを通す感じにできて、 その最後の最終的な変換されたSceneIndexを取得するから
HdRenderDelegate - void Update() - RenderPassの_Executeが呼ばれる前に一度呼ばれる関数 - これが呼ばれる際にはすでに前回の _Executeが終わっている - このタイミングは _Executeが走っていないので GPUの頂点バッファの更新などは このタイミングでできるはず - 私のレンダラーでは SceneIndexObserverが溜めた シーンの差分を renderer_に反映させて GASやIASのリビルド、 SBTのアップデート処理を 書いている
HdRenderBuffer - レンダリング先のバッファのクラス これを継承して自分用のバッファを作ることになる pxr/imaging/hd/renderBuffer.h
HdRenderBuffer - 実装すべきはこのあたり - bool Allocate(GfVec3i const& dimensions, HdFormat format, bool multiSampled) - unsigned int GetWidth() const unsigned int GetHeight() const unsigned int GetDepth() const HdFormat GetFormat() const bool IsMultiSampled() const void* Map() void Unmap() bool IsMapped() void Resolve() bool IsConverged() VtValue GetResource(bool multiSampled) - - これは必須ではないがGPUのバッファをCPUにリードバックせずに ホストに渡したい場合は必要 void _Deallocate()
HdRenderBuffer - bool Allocate(GfVec3i const& dimensions, HdFormat format, bool multiSampled) - unsigned int GetWidth() const unsigned int GetHeight() const unsigned int GetDepth() const HdFormat GetFormat() const bool IsMultiSampled() const void Resolve() - MSAAの解決とか - bool IsConverged() void _Deallocate() - このあたりはそのままなので特記することはない
HdRenderBuffer - void* Map() void Unmap() bool IsMapped() - CPU上でこのMapされた配列を読み込むことでホストが描画されたデータを読み込む 実装は必須だが、この実装だけだとGPU上のレンダリングしたバッファを 常にCPUにリードバックしてからホスト側で描画のために GPUに再アップロードすることになる - GetResource()を実装することでGPUバッファを渡せる
HdRenderBuffer - VtValue GetResource(bool multiSampled) - RenderDelegateがVtValueにHgiTextureHandleを入れて返す場合、 Map/Unmapは呼ばれず、そのHgiTextureHandleのテクスチャがそのまま ホストのビューポート描画に使われるようになる - HgiTextureHandleは内部でHgiTextureを持っており、 HgiTextureはhgiというGPU APIを抽象化した層のテクスチャの抽象 内部はOpenGL / Metal / Vulkan (experimental)のテクスチャ HgiTextureHandle::GetRawResource()でOpenGLの場合GLuintのtextureIdが手に入る - 例えばCUDAの内容をOpenGLテクスチャへコピーするコードは書けるので、 OptiXの内容をCPUに読み戻すことなくホストに返せる
HdRenderBuffer - VtValue GetResource(bool multiSampled) - HgiはRenderDelegateあたりで初期化しておくと良い
HdRenderBuffer - VtValue GetResource(bool multiSampled) - HgiはRenderDelegateあたりで初期化しておくと良い - GLuintのテクスチャIDが手に入るので cudaGL.hとかを使ってCUDAのバッファの内容をコピー
HdRenderPass - 実際のレンダリングの実行を行うためのクラス HdRenderDelegateのCreateRenderPass()経由で作成される pxr/imaging/hd/renderPass.h
HdRenderPass - 実装すべき関数は以下の通り - void _Execute(HdRenderPassStateSharedPtr const& render_pass_state, TfTokenVector const& render_tags) bool IsConverged() const - こちらはオプショナル
HdRenderPass - _Executeの引数にHdRenderPassStateSharedPtrが渡ってくる - それにGetAovBindings()を使うことでHdRenderPassAovBindingVectorが手に入る - HdRenderPassAovBindingVectorはstd::vector<HdRenderPassAovBinding> - HdRenderPassAovBindingは次のような構造体 - つまり_Executeではレンダリング先のrenderBufferが手に入る
HdRenderPass - _ExecuteでrenderBufferへの値の書き込みを行うことでホストに描画される - _ExecuteはHostの判断で呼ばれる - 最初は高頻度で呼ばれるが、Convergeしない場合少しずつ間引かれて呼ばれる _Executeで1spp進めるのではなく、裏でレンダリングスレッドを回しておいて _Executeが呼ばれたら現在のレンダリングされた最新の絵を返すようにすると良い
HdRenderPass - bool IsConverged() const で収束したかを返すと、収束していない場合に繰り返しホストが _Executeを呼び出してくれるようになる - sppが増えていく過程をホスト側に描画したい場合は収束するまでfalseを返すことで プログレッシブなレンダリングができる パストレなどの時間がかかるレンダリングの場合は_Executeは即座に返して IsConverged()がfalseになるプログレッシブレンダリングが基本
HdRenderPass - _Executeをレンダリング完了まで同期で待機して bool IsConverged() const でtrueを返す ブロッキングモードも用意しておくと、CLIで_Executeを繰り返し呼んで収束を 確認する手間が省ける - RenderSettingsとかでブロッキングモードにも設定できるようにしておくと便利
HdSceneIndexObserver - SceneIndexの内容を通知で受け取るためのクラス pxr/imaging/hd/sceneIndexObserver.h SceneIndex周りは次の公式ドキュメントのページが詳しいので読むこと - https://openusd.org/release/api/_page__hydra__getting__started__guide.html
HdSceneIndexObserver - 実装すべき関数は - void PrimsAdded(const HdSceneIndexBase& sender, const AddedPrimEntries& entries) void PrimsRemoved(const HdSceneIndexBase& sender, const RemovedPrimEntries& entries) void PrimsDirtied(const HdSceneIndexBase& sender, const DirtiedPrimEntries& entries) void PrimsRenamed(const HdSceneIndexBase& sender, const RenamedPrimEntries& entries) - 関数名通り、シーンのステージにPrimが追加削除編集リネームのタイミングで呼び出される これらの関数内部でSceneIndexからその内容を取得することでシーンの情報が手に入る - PrimsAddedで購読した項目だけPrimsDirtiedなどに流れるので注意 - 購読せずにログだけ流して動作確認しようとするとAdded以外何も流れない
HdSceneIndexObserver - SceneIndexからのデータ取得に使えるAPIについては先のURLが詳しい - HdSceneIndexからGetPrimでPrimのデータが手に入る - PrimはprimTypeとHdDataSourceのpropertiesを持っている - propertiesにアクセスすることでシーンのPrimの情報が手に入る
HdSceneIndexObserver - propertiesはHdDataSourceという型で以下のいずれか - HdContainerDataSource - - HdVectorDataSource HdSampledDataSource - - 他のDataSourceを入れ子で持てる DataSource 時間で変化する値のコンテナ pxr/imaging/hd/dataSource.h
HdSceneIndexObserver - 例えば次のようにしてmeshのdata sourceにアクセスできる
HdSceneIndexObserver - DataSourceのスキーマは次のページに定義されている - https://openusd.org/release/api/_page__hydra__prim__schemas.html
HdSceneIndexObserver - 例えばmeshのDataSourceは次の通りのスキーマ - まずは基本のPrimが持っているスキーマ
HdSceneIndexObserver - 例えばmeshのDataSourceは次の通りのスキーマ - 描画可能なPrimであるGprimのスキーマ
HdSceneIndexObserver - 例えばmeshのDataSourceは次の通りのスキーマ - 描画可能なPrimであるGprimのスキーマ
HdSceneIndexObserver - 例えばmeshのDataSourceは次の通りのスキーマ - Mesh本体のスキーマ
HdSceneIndexObserver - 例えばmeshのDataSourceは次の通りのスキーマ - Mesh本体のスキーマ
HdSceneIndexObserver - DataSourceに対して愚直に自分でロケーターのパスを指定して与える他に、 スキーマ用のクラスが用意されていたりしてそれを使うと便利だったりする - 以下の例ではmeshのDataSourceから子要素のtopologyを HdMeshTopologySchemaを使ってアクセスしている様子
HdSceneIndexObserver - SceneIndex経由で手に入る以下のデータについて個別に説明する - camera - mesh - geomSubset - material - その他は先のスキーマのページを見てほしい
HdSceneIndexObserver - cameraのHydra Prim スキーマ - xform/matrixで姿勢が手に入る - camera/verticalApertureとcamera/foocalLengthを使うと fovYが計算できる
HdSceneIndexObserver - meshのHydra Prim スキーマ - xform/matrixで姿勢が手に入る - materialBindings/0でマテリアルのSdfPathが手に入る - mesh/topologyでトポロジー情報が手に入る - mesh/topology/faceVertexCountsで各面がいくつずつ頂点を保持するかわかる - 三角形面以外の面も渡ってくる - mesh/topology/faceVertexIndicesでインデックスバッファを取得できる - mesh/topology/Orientationでインデックスの順序が右手系かどうかが手に入る - primvars に頂点属性が入っている
HdSceneIndexObserver - primvarsは頂点属性などを表し、配列データが手に入る - Interpolationという情報も付随して手に入る Interpolation - Constant - - Uniform - - メッシュ全体で一つの値のみ / 頂点カラーが全頂点で等しい場合など 面ごとに単一の値 / 頂点カラーが面ごとに違う場合など Vertex - 頂点ごとのデータ / 頂点位置など - FaceVarying - - 面の頂点ごとに異なるデータ / UVやハードエッジなNormalなど varying - 歴史上残っているらしい / FaceVaryingと同等
HdSceneIndexObserver - それぞれのInterpolationで次のようにアクセスすることになる - constant - uniform
HdSceneIndexObserver - それぞれのInterpolationで次のようにアクセスすることになる - vertex
HdSceneIndexObserver - それぞれのInterpolationで次のようにアクセスすることになる - faceVarying
HdSceneIndexObserver - pointsという頂点位置はvertexのInterpolationであることが保証されている 他のuvとかnormalとかcolorとかは存在するかとかどのInterpolationかは 取得して確認する必要あり
HdSceneIndexObserver - GeomSubsetというサブメッシュの仕組みがある - メッシュの一部に別のマテリアルを割り当てる場合、geomSubsetというPrimが meshのPrimの子Primとして存在する - geomSubsetはサブセットの面インデックスを保持している
HdSceneIndexObserver - GeomSubsetもMaterialBindingsを持っておりマテリアルのSdfPathが手に入る どのGeomSubsetにも属さない面が元のMaterialBindingsに属す
HdSceneIndexObserver - primvarsは三角形化されているとは限らない 三角形化するutilが存在する HdMeshUtil - HdMeshUtil::ComputeTriangleIndices() - - HdMeshUtil::DecodeFaceIndexFromCoarseFaceParam() - - これで三角形化したメッシュの頂点インデックスが手に入る これで三角形化したあとに元の面インデックスとの対応が取れる pxr/imaging/hd/meshUtil.h
HdSceneIndexObserver - 地味に毎フレーム頂点情報が変わるたびに geomSubsetを分離して三角形化の処理が 必要になってくるので数百万頂点のポリゴンとかを扱う場合は余計な処理をしないように注意 - 私の提出作品で流体を描画する際にバカみたいな頂点数のメッシュを与えて自前でインデックスを いろいろ計算してたら頂点の三角形化したメッシュの抽出で思ったより時間がかかった ので提出作品は大幅にポリゴンリダクションを掛けている
HdSceneIndexObserver - materialのHydra Prim スキーマ
HdSceneIndexObserver - materialのHydra Prim スキーマ - 各シェーダーノードが格納されていて,、inputのconnectionで繋がれたグラフデータ
HdSceneIndexObserver - ノードはnodeIdentifierで 種類がわかる - 次のコードはsurfaceの Terminal接続から UsdPreviewSurfaceの シェーダーノートにアクセスするもの
HdSceneIndexObserver - ノードのparametersでパラメータを取得できる
HdSceneIndexObserver - テクスチャの場合はUsdUVTextureノードにつながっている - ノードを辿ってUsdUVTextureノードにアクセスしfileというパラメータで SdfAssetPathのテクスチャのパスが手に入る SdfAssetPath::GetResolvedPath()とすることでアセットの解決済みのパスが手に入る テクスチャを普通に画像読み込みのstbとかで読み込めば良い
DCCツールごとのHydraレンダラープラグインのビルド - ここまでの情報で基本的なHydraレンダラーは作れる - 実際にはDCCツールごとにHydraのビルドに当たって注意すべきことがある 今回は以下のツールについて実際にプラグインとして読み込めるビルドを 作るうえでの注意をそれぞれ紹介する - Houdini 21.0 Blender 4.5.4 LTS CLI
Houdini 21.0のHydraレンダラープラグイン - Houdini 21.0のOpenUSDのバージョンはv25.05 - Houdini用のプラグインを作る場合は v25.05でのビルドが必須
Houdini 21.0のHydraレンダラープラグイン - OpenUSDのビルドでビルドされるsoのプレフィックスがデフォルトと異なる - デフォルトでは libusd_usd.soだが、Houdiniは古い?libpxr_usd.soを使っている デフォルト設定のビルドではリンク先の動的ライブラリの名前が異なるため動作しない - OpenUSDのビルド時のオプションでPXR_LIB_PREFIXでプレフィックスを変更する必要がある
Houdini 21.0のHydraレンダラープラグイン - HoudiniのビューポートはcolorとdepthのAOVへの対応が必須 - - colorだけだと何も描画してくれない Houdiniの内部のアセットパス (op:/hoge.png みたいなop:/始まりのパス)は 解決してくれずSceneIndexに渡ってくる - 例えばHoudiniに入っているPigHeadのモデルのテクスチャを扱いたい場合に困る Houdiniのアセット解決は HDKというHoudiniのSDKを使う必要がありそう HDKのアセットパス解決を OpenUSDのアセットリゾルバのプラグインとして 登録してやれば解決できそうな気はする
Houdini 21.0のHydraレンダラープラグイン - OpenGLのコンテキストがしょっちゅう破棄される - Houdiniは最近ViewportがVulkanになったみたい しかしOpenUSDのHgiのVulkanはexperimentalなので、Hydraを動かすためだけに OpenGLのコン テキストをその場で作っているみたい そのOpenGLコンテキストの寿命がおかしい - RenderDelegateが作られて最初の _Executeの時点でOpenGLのコンテキストの 初期化が間に合っていない - RenderBufferの内部でOpenGLのテクスチャを作ると、コンテキストが無い場合 invalidなテクスチャIDしか作られないので注意
Houdini 21.0のHydraレンダラープラグイン - OpenGLのコンテキストがしょっちゅう破棄される - さらになぜか一度作られた OpenGLのコンテキストが時々破棄される そのため、破棄される前に作っていた OpenGLのTextureIDが無効になったりする - - CUDAのバッファの内容をHgiのOpenGLテクスチャに書き込もうとしたら、 謎のタイミングで書き込み失敗するので頭を抱えていたが どうもOpenGLのコンテキストが度々リセットされている模様 常にOpenGLのコンテキストが存在するか確認 & CUDAのResourceとしてregister / unregisterはtry/catchで囲んで 例外を握りつぶすので対処した……
Houdini 21.0のHydraレンダラープラグイン - GUIは.dsという謎のファイルを用意するとよい HOUDINI_PATHという環境変数の下に soho/parameters/HdKanahebiRendererPlugin_Global.dsという ファイルを作成するとRenderSettingsのGUIに kanahebi用のタブが増える
Houdini 21.0のHydraレンダラープラグイン - .dsはHoudini組み込みのKarmaのものを参考にするとよい まとまったドキュメントはどこにもない - おおよそ次の感じのものを書くことになる
Houdini 21.0のHydraレンダラープラグイン - .dsはHoudini組み込みのKarmaのものを参考にするとよいが
Houdini 21.0のHydraレンダラープラグイン - .dsはHoudini組み込みのKarmaのものを参考にするとよいが
Houdini 21.0のHydraレンダラープラグイン - .dsのパラメータ名には「:」のような文字は使えないので Houdini上のPythonで hou.text.encodeParm(“kanahebi:global:targetsamples”) を実行した結果のエンコードした文字列を使う - これで.dsで定義したGUIがRenderSettingsのGUIに現れる このRenedrSettingsで指定したものはRenderDelegateのSetRenderSettingで 受け取ることができる
Houdini 21.0のHydraレンダラープラグイン - PXR_PLUGINPATH_NAMEにプラグインを配置してHoudiniを立ち上げることでレンダ ラーを有効化して立ち上げられる - Linuxならhoudini -foregroundとすることで標準出力の内容が見れる
Houdini 21.0のHydraレンダラープラグイン - プラグインを有効化して立ち上げるとSolarisのレンダラーの一覧に 自作レンダラーも並んでいるはず
Blender 4.5.4 LTSのHydraレンダラープラグイン - OpenUSDのバージョンはv25.02 - 次でOpenUSDのビルドをしている https://projects.blender.org/blender/blender/src/branch/blender-v4.5-release/build_files/build_e nvironment/cmake/usd.cmake
Blender 4.5.4 LTSのHydraレンダラープラグイン - BlenderのOpenUSDはモノリシックビルドされているので Hydraレンダラープラグインを作る場合はOpenUSDをモノリシックビルド してやる必要がある - 内部の名前空間も変更されているのでビルドオプションで変更する必要がある
Blender 4.5.4 LTSのHydraレンダラープラグイン - 「--build-monolithic」のオプションが必要
Blender 4.5.4 LTSのHydraレンダラープラグイン - BlenderのOpenUSDはビルド時に謎のパッチを当てている - https://projects.blender.org/blender/blender/src/branch/blender-v4.5-release/build_files/build_e nvironment/patches/usd_ctor.diff pxrctorという領域名を謎に pxbctorに変えており、そのままビルドすると プラグインの読み込み登録処理が走らなくなる そのためこのパッチを自分でビルドする場合も当てる必要がある
Blender 4.5.4 LTSのHydraレンダラープラグイン - Pythonでアドオンもしくは エクステンションとして 次のようなコードを書くことで レンダラーを登録できる
Blender 4.5.4 LTSのHydraレンダラープラグイン - bpy.types.HydraRenderEngineを継承した型をつくり registerでPluginPathを登録すると良い - https://docs.blender.org/api/current/bpy.types.HydraRenderEngine.html
Blender 4.5.4 LTSのHydraレンダラープラグイン - get_render_settingsでdictionaryを返すことで、RenderDelegateに RenderSettingsを渡すことができる
Blender 4.5.4 LTSのHydraレンダラープラグイン - 非Viewport (=通常レンダリング) で使うには'aovToken:Combined': "color"を Dictionaryに追加しておく必要がある
Blender 4.5.4 LTSのHydraレンダラープラグイン - GUIは普通のBlenderのPythonとして作れば良い
Blender 4.5.4 LTSのHydraレンダラープラグイン - 最近のBlenderはアドオンではなくエクステンションに移行しているので エクステンションとして定義すると良いと思う - blender_manifest.tomlをpythonの他に用意して zipにまとめるだけ
Blender 4.5.4 LTSのHydraレンダラープラグイン - エクステンションはディスクからインストールできる
Blender 4.5.4 LTSのHydraレンダラープラグイン - インストールしたらレンダラーのリストから選んで使えるようになっている
Blender 4.5.4 LTSのHydraレンダラープラグイン - ビューポートのカメラはSprimとして取得することになる BlenderではSceneIndexを使う場合でもSprimでのカメラの対応が必要 C++にSprim対応を追加する必要あり
Blender 4.5.4 LTSのHydraレンダラープラグイン - ビューポートのカメラはSprimとして取得することになる BlenderではSceneIndexを使う場合でもSprimでのカメラの対応が必要 C++にSprim対応を追加する必要あり
Blender 4.5.4 LTSのHydraレンダラープラグイン - BlenderではRenedrBufferのcolorはHdFormatUNorm8Vec4ではなく HdFormatFloat32Vec4が要求される
Blender 4.5.4 LTSのHydraレンダラープラグイン - BlenderではRenderSettingsのfloatの値もdouble型に化けてやってくるので RenderSettingsでfloatを受け取る部分はdoubleにも両対応する必要あり BlenderではRenderSettingsのintの値もlong型に化けてやってくるので RenderSettingsでintを受け取る部分はlongにも両対応する必要あり
Blender 4.5.4 LTSのHydraレンダラープラグイン - BlenderではRenderSettingsのfloatの値もdouble型に化けてやってくるので RenderSettingsでfloatを受け取る部分はdoubleにも両対応する必要あり BlenderではRenderSettingsのintの値もlong型に化けてやってくるので RenderSettingsでintを受け取る部分はlongにも両対応する必要あり
Blender 4.5.4 LTSのHydraレンダラープラグイン - Pythonのプロパティにbl_use_gpu_contextがあるがかなり様子がおかしい - bl_use_gpu_contextをTrueにするとRenderBufferが渡されなくなる - Viewportの描画領域がOpenGLのframebufferとして登録された状態で_Executeが呼ばれるみたい _ExecuteでOpenGLの描画を行うと、Blenderのビューポートに描画されるという仕組み Hydraの標準的な描画結果の渡し方では無いと思う……
Blender 4.5.4 LTSのHydraレンダラープラグイン - 前にも述べたがBlenderはOpenUSDのMaterialXのノードに対応していない マテリアルは単純なPrincipled BSDFがUsdPreviewSurfaceに 変換されて渡ってくる形になるみたい - MaterialXのノードで組まれた複雑なマテリアルとかPrincipled BSDFを使う場合でも複雑な ネットワークは現状では持ってこれない
CLIでのHydraレンダラープラグイン - CLIでHydraレンダラープラグインを動かしたい場合、 小さなHydraのホスト側のコードを書くことになる OpenUSDのバージョンは何でもよいが、最新のv25.11を前提に話を進める
CLIでのHydraレンダラープラグイン - UsdImagingSceneIndicesがOpenUSDの.usdファイルのステージを SceneIndexに変換してくれる - OpenUSDをusdImaging付きでビルドすると使える
CLIでのHydraレンダラープラグイン - レンダラープラグインからRenderDelegateを取得する
CLIでのHydraレンダラープラグイン - RenderDelegateにRenderSettingを渡すのもここでやる
CLIでのHydraレンダラープラグイン - HdEngineとHdRenderIndexをつくる - HdRenderIndexはHydra 1.0の時代の強く残る部分だが、SceneIndexを渡すHydra 2.0のAPIも追加されているのでそれを使うとよい
CLIでのHydraレンダラープラグイン - HdxTaskControllerSceneIndexというのを作る - これを登録して Executeすることで諸々が実行される 古いHdxTaskControllerのSceneIndex版じゃないものもあるので注意
CLIでのHydraレンダラープラグイン - フレームごとにSceneIndexにSetTimeしつつengine.Executeを呼ぶ
CLIでのHydraレンダラープラグイン - 実行結果は AOVを取り出し RenderBuffer経由で アクセスできる
CLIでのHydraレンダラープラグイン - RenderPassがプログレッシブモードの場合は収束するまで Executeを複数回呼ぶ必要があるはず stbでpngを書き出すと上下がflipしたりするので RenderSettingsにflipYのオプションも入れておくと良い
CLIでのHydraレンダラープラグイン - .dllやその他プラグインなどを同梱しないと動かない - Linuxで.soの場合はライブラリロードをするようにした.shファイルで起動すると良い - .dllだけでなくusd/以下のプラグインもPXR_PLUGINPATH_NAMEのパスに 入れておかないとOpenUSDのアセット解決とか諸々動かないので注意
その他ビルド時の注意 - WindowsではCMakeに次のフラグが必要かも - set_property(TARGET hdKanahebi PROPERTY LINK_OPTIONS "/OPT:NOREF" "/OPT:NOICF") set_property(TARGET hdKanahebi PROPERTY COMPILE_OPTIONS "/Zc:inline-") これらがないと pxrctor領域が使われていない領域として削除されうる
その他ビルド時の注意 - Windowsでは_DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR=1が必要かも - Windowsのランタイムは mutexにconstexprをつけるために ABIを破壊している - ABIの互換性のためにこれは無効化できるようになっている Blenderのビルドなどでは無効化されているっぽいので、有効化した環境でビルドした Hydraプラグ インでmutexを使うと Access violation でセグフォになる https://stackoverflow.com/questions/78598141/first-stdmutexlock-crashes-in-application-builtwith-latest-visual-studio
その他ビルド時の注意 - うまく動かない場合はリンクするdllやdllのシンボルが間違っていないかを確認すると良い - ビルドに使うpythonのバージョンを間違えると python311.dllにリンクすべきなのに python313.dllにリンクしたりして音もなくプラグインが立ち上がらないので注意 うまく動かないときは lddとかnmコマンドとかdumpbin.exeを使って依存 dllやシンボル名を調べると 良い
君もHydraレンダラープラグインを作って、 自作レンダラーをDCCツールで使ってみよう!
OpenUSDについて & Hydraレンダラー実装 レイトレ合宿 11 セミナー資料 折登 樹