てんちょーの技術日誌

自分がつまづいたこととかメモ

【Houdini】SOP→LOP→COP→TOP + OCIO でワークフローを整えてみた

はじめに

Houdini Advent Calendar 2021 の2日目の記事です

qiita.com

1日目は蒸留スイさんの「フェイシャルキャプチャ― in Houdini」でした

qiita.com

最近は毎週日曜20時ごろにHoudiniで作ったものをTwitterにあげています
今回はこのワークフロー周りについて紹介しようとおもいます

サンプルファイルも用意しています
普段はRedShiftを使っていますが、KarmaでもMantraでも使えるかなと
Appearanceでも動作するはず...

drive.google.com

想定読者

SOP / ROP などは記事やブログでよく見かけるのですが、
それ以降の最終的にレンダリングして書き出して静止画/動画にする
までを俯瞰できる物が少ないなと思い、手元の環境が参考になればと書いています

自分も何度も飽きて辞めたり挫折したりでしたが、
ワークフローが整ってきた最近では楽しくなってきました

そのため、下記を想定しています

  • Houdiniを始めたばかり
  • Houdiniで静止画や動画まで書き出したい
  • 環境構築が好きな人

環境

Houdini: 19.0.383 (Indie)
Renderer: RedShift

OS: Windows 10 (21H1 19043.1348)
CPU: Ryzen 3900X
GPU: RTX 2080
メモリ: 64GB

始める前に

こちらのhipファイルをかなり参考にしています
ありがとうございます!

booth.pm

これを元に少しアレンジしつつ、ハマったところを共有できればいいなと思っています

一部作例解説動画もあります
Skeleton SOP からカーブを作る話が面白かったのでリンクを貼っておきます

youtu.be

ポイント

詳細はhipファイルを見てもらうとして、いくつかピックアップして紹介します
hipファイルにはもう少し細かくコメントしてあります

subnetwork内にまとめちゃう

1つの作品 / 1つのhipファイル
というのもよいですが、
個人制作の場合は
複数の作品 / 1つのhipファイル
というスタイルもアリだなと思っています

f:id:shop_0761:20211202100107p:plain

f:id:shop_0761:20211114103013p:plain

意外と作品ごとに管理しやすく、
例えばsubnetworkのノード名を使用して下記のようにパスを分けています

file cache (SOP)
$HIP/geo/`opname("../../")`/$OS.$F4.bgeo.sc

また、こんなふうに手元で並べていくと楽しいです

f:id:shop_0761:20211123173212p:plain

パラメータ変更によるレンダリング結果の比較

機能紹介になってしまいますが、Houdini18.5からSnapShotがあります

www.sidefx.com

デフォルトだとSceneViewの下に折りたたまれているので、△のとこを押すと出るはず

f:id:shop_0761:20211123122329p:plain

f:id:shop_0761:20211123121903p:plain

Revert Network to SnapShot を押すと
各ノードのパラメータまでSnapShot時まで戻ります

f:id:shop_0761:20211123121935p:plain

COP内でのカラースペースの変換

気が変わってNukeやDaVinci Resolveでも
シーンリニアワークフローで作業できるようにしてあります
(実際趣味で環境構築しただけですが...)

ただ普段はHoudini内で完結させたいので、COP内で変換をしています

全体

f:id:shop_0761:20211114105750p:plain

VOPCOP 2 Filter 内部

f:id:shop_0761:20211114105258p:plain

とりあえずsRGBにしています

f:id:shop_0761:20211114105324p:plain

ROP File Output
Convert To Image Format's を切る (自分で色空間の変換をしているため)

f:id:shop_0761:20211114111534p:plain

注意事項として

  • Houdini上でのプレビューはvopcop2filter の前でする
  • 書き出しはvopcop2filter を対象にする

ことをオススメします

Houdini上でPreviewでOCIOのON/OFFでもよいですが、
面倒なのでプレビューは変換前までにしています

Composite View: 変換前 / 出力: 変換後 / OCIO: Enable
(オススメ)

f:id:shop_0761:20211114110353p:plain

Composite View: 変換後 / 出力: 変換後 / OCIO: Disable
(結果は同じ、都度Disableにするのがめんどい)

f:id:shop_0761:20211114110750p:plain

Composite View: 変換後 / 出力: 変換後 / OCIO: Enable
(色が変わってしまう)

f:id:shop_0761:20211114110704p:plain

とまあ色々書きましたが、
OCIOはある程度知識がないと一生色が合わない沼にハマるのでご注意ください...

関連リンク

Houdiniに導入するときの参考記事

www.sidefx.com

シーンリニアワークフローの読み物

area.autodesk.jp

(余談) Houdini Launcher

少し前からHoudiniもLaucherができました

www.sidefx.com

f:id:shop_0761:20211123171343p:plain

18.5以前はログインするのもコツがいる(?)感じでしたが、
19からはだいぶ一新されて使いやすくなりました

Dailyビルドも選択できます
f:id:shop_0761:20211123171617p:plain

ハマりポイント

この環境をつくるまでにハマったところがいくつかあったので、書いておきます

TOP内でffmpegを使って動画を書き出しされない

ffmpeg単体で入れるとffmpegencodevideo(TOP) が正しく動かないっぽいです
(Mplayからffmepg + mp4 書き出しはできるようになります)

手元ではimagemagick経由でffmpegを入れるとうまくいきました

www.sidefx.com

また FrameListと書き出し先が同じ階層にないと怒られるので下記のように設定しています
(記事だけ見ても意図が分かるようにサンプルファイルとは少しパスが異なります)

Frame List File
$HIP/video/`opname("./")`/framelist.txt

Output File Path
$HIP/video/`opname("./")`/video.mp4

RedShiftでのレンダリング(書き出しの方)がされない

普段リアルタイム系ばっかりやっているせいか、プリレンダのお作法?があるようです

再現手順
1. LOPでRedShiftのプレビューを有効にする
2. USD RenderROP でレンダリングする (Render To Disk in BackGround など)

f:id:shop_0761:20211114113816p:plain

と手元だと一生レンダリングされませんでした

これは同時に起動できるRedShiftが(ライセンス的に?) 1つの場合、
Preview側で使っているためライセンスが見つけられないようです

Houdini GL に戻す / Pause Render にするなどすればだいたい動きます

f:id:shop_0761:20211114114109p:plain

また、どこかがRedShiftを掴みっぱなしになったまま、
レンダリングできない (もしくはめちゃめちゃ遅い) ということもあったので
Houdiniを再起動する (それでもダメならPCごと) すると治ったりしました

いろいろ試した結果の推測なので、間違っていたら教えてください...

また、Houdini 19 から LOP で Pause Render したら
パラメータ変更や階層を移動してもPauseしたままになるようになったっぽいです(たすかる)

Houdini 19 に移行したらそもそも起動しない

This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.

みたいなエラーになって起動しなくなってしまいました
(Houdini 18.5 Python3 系を使っていたので問題ないかと思っていたんですが...)

これは自分でpythonの開発環境 (anaconda) を構築したときにやらかしたっぽいです
おとなしくアンインストールしたら解決しました

参考

https://insilico-notebook.com/conda-uninstall/

最後に

最初は下記みたいなことがありました

  • うまく書き出せなくてflipbookからMPlayで書き出し...
  • 作品はできたけど最後の書き出しが間に合わず無理やり別のツールで仕上げ...
  • 前に上手くできたhipファイルどこいったっけ...

安定したワークフローがあると作るものに集中できていいなと思いました

持続可能な開発管理(Sustainable Development Governances) ということで
SDGs をやっていきましょう(?)
お後がよろしいようで...

何かあればTwitter までご連絡ください~

twitter.com

3日目は山里 ぽん太さんの「今年のカード」です

note.com

M1 Mac Mini を買ったので初期セットアップを自動化してみた

はじめに

9月の発表でM1後継来てくれ〜〜〜と思っていたけど、来なかったので(もう少しあとに来るかもだけど)
そろそろ待てなくなってきたので勢いで買ってしまいました (後継機が出たら買い替えます...)

PCを買うたびにアプリを入れて...とかがさすがに面倒になってきたので
どこまでできるのか調べてやってみた という内容です
すでにいろいろな人がやっていたので、自分のメモみたいなものと紹介がメインです

やること

homebrew は Brewfile を作成することでまとめてinstallするものを書けるようです
下記をかなり参考にしています

www.karakaram.com

これでアプリのインストール、環境構築の類はかなり終わります

残りはMac自体の設定をしますが、これもすごい記事を見つけました

zenn.dev

defaults から変更できるものはすべて網羅されていそうです
ものによってはPCごと再起動しないと反映されないようなので要注意です

一部はApple Scriptを使わないといけなさそうです...

その他

この辺の設定をshell scriptにしてバージョン管理をしています
ついでに symbolic link で .zshrc とか karabiner の設定も含めています

karabiner.json は直接 symbolic link を貼ってはいけないようなので注意です

karabiner-elements.pqrs.org

おわりに

地味〜〜〜に時間がかかるし、毎回忘れるので今回始めてやってみました
Windows側もできそうだしM1後継機が来ても乗り換えやすくしておきたい... という気持ちがあったのでなんとかなってよかったです

【Unity】SetHumanPoseを使うとなぜか吹っ飛んでしまう時の対策

概要

HumanPoseHandlerを使っていたら、なぜか遥か彼方へ飛んでいってしまう…
みたいなことに遭遇していました

f:id:shop_0761:20210331145116g:plain

f:id:shop_0761:20210414094405g:plain

f:id:shop_0761:20210414094424g:plain

今回ようやく原因と一部対処方法が分かったので書いておきます

検証環境

Unity2019.4.22f1

発生条件

把握してる範囲だと2パターンあります

Aパターン

  1. HumanPoseHandler生成時の第2引数 root に不正な Pos/Rot/Scale 値がある
  2. SetHumanPose をする

Bパターン

  1. HumanPoseHandlerを生成する
  2. Animator が Attach されている Transform の Pos/Rot/Scale を変える
    (Editor操作を含む)
  3. SetHumanPose をする

対処方法

Bは対処方法がないので触らない…ということになってしまいます…

Aはキャラが原点にいないせいでHumanPoseHandler生成時に発生します
こっちのほうは対処法を見つけたのでコードを載せます

    private HumanPoseHandler CreateHumanPoseHandler(Animator animator)
    {
        if (animator == null) { return null; }
        var position = animator.transform.position;
        var rotation = animator.transform.rotation;
        var scale = animator.transform.localScale;

        animator.transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity);
        animator.transform.localScale = Vector3.one;
        var humanPoseHandler = new HumanPoseHandler(animator.avatar, animator.transform);

        var hipBone = animator.GetBoneTransform(HumanBodyBones.Hips);
        hipBone.rotation = rotation;
        hipBone.position = position + hipBone.up * hipBone.position.y * scale.y;
        hipBone.localScale = scale;
        return humanPoseHandler;
    }

日本語にすると

  1. animatorのあるTransformをキャッシュ
  2. 全部初期値
    (Position : Vector.zero / Rotation: Quaternion.identity / Scale: Vector.one) に戻す
  3. HumanPoseHandlerの生成
  4. HipBoneにキャッシュ分を反映する

4つ目は恐らく HumanPose.bodyPosition/ HumanPose.bodyRotation でもよいですが
Scaleを反映させる術がなさそう?だったのでhipboneにしています

position + hipBone.up * hipBone.position.y * scale.y

この部分はUnityによくある体が半分くらい床に埋まってしまうやつの対策です
hipBoneのYだけ考慮したかったので up と掛け算しつつ、
元のscaleも計算に入れてつじつま合わせをしています

推測

おそらく animator.transform を基準にSetHumanPoseの計算をしており、
これが初期値でないと毎フレームoffsetとして加算されてしまうようです

他に試したこと

Hipの親をHumanPoseHandlerの第2引数にする

ちゃんとroot boneが用意されているモデルを使って試しました
吹っ飛ばなくなる…がMuscleが反映されませんでした
ということはanimator.transformを渡すのが必須のようですね…

HumanPose.bodyPosition/bodyRotation で反映する

途中までこっちで確認していましたが、やや計算誤差がありそうです

まとめ

調べてもあまり同じようなことで悩んでる人がいなさそう…?
だったので記事にしておきました

とりあえずanimator.transformを操作しなければ
一旦これで対策できそうなのでなんとかなってよかったです

なにかあれば Twitter までご連絡ください~

【Unity】結局LinearとGammaどっちにしたらいいのかを考えてみた

はじめに

Unityを使っていると無意識のうちにColor SpaceをLinearにすることが多かったですが 「なんで?」とふと思ったのでドキュメントと自分の解釈を合わせて書いておこうと思います

間違ってたら教えて下さい
以前の記事で色についてちょっと勉強したことがあるので、
そんなに外れてはいないはず…
2020/07/10 現在の話です

ここを参考に話を進めます

docs.unity3d.com

以降、Unityにおけるリニア色空間は Linear、ガンマ色空間は Gamma 表記にします

結論

よっぽど古い端末、Unityだけで描画周りが完結しないみたいな制約がない限り、
""9割くらいはLinearにしておいたほうが安牌""っぽい

です

LinearとGamma ってなに

ここはUnityに限らずの話です
簡単に言えば、人間の目に見えやすくする補正をかけるのをガンマ補正と呼びます
(だいぶガバガバな説明です)   詳しく知りたいかたはこちらをどうぞ

qiita.com

Unityにおけるガンマ値は体感約2.2辺りで固定なので sRGB想定なんだと思います
P3とかどうなるんだ…という話はあるので厳密にはGammaよりsRGB( or Gamma(sRGB) etc... )の方が表記としては正しそうだなと思ってます

ガンマ値自体も約2.2固定ではないので…

Texture

特に意識せずPhotoShopなどで作成するとsRGBになると思います
なのでUnityで言うところのGamma Textureに当たります

余談

マスクとして作るTextureやPattern Texture、LUTなどはLinearにしたほうがキレイに出ると思います

厳密にやるならPhotoShop等で作業した後にLinearでTexture書き出しをしたほうがよさそうですが、大体はsRGBで作ってゲームエンジン上でsRGBのチェックボックスを外す でよさそうです

Shader

テクスチャはガンマ色空間に保存される傾向がありますが、シェーダーはリニア色空間を前提としています。

docs.unity3d.com

なので、Gammaで使っているときに「なんか色が思ったより暗い」というのは Shader側が Gamma Texture を Linear Texture のように扱おうとしてしまっているのが原因だと思われます

じゃあLinearにするとどうなるのか というと

リニアカラー空間を使用するとき、すべてのマテリアルカラープロパティーは sRGB カラーで提供されます。しかし、シェーダーに渡されるときにリニアの値に変換されます。

docs.unity3d.com

のでユーザーから見ればLinearにしただけで治るケースが多いです

じゃあ Gammaで正しく使うにはどうするの という話ですが、

Color Space: Gamma モードで sRGB サンプリングを回避するよう設定できます。これを行うには、テクスチャの Inspector ウインドウ の sRGB (Color Texture) チェックボックスを無効にします。

docs.unity3d.com

なので使う側に一手間いる ということですね
「わかんないけどなんかsRGBのチェックを外すと治る」みたいなケースは
「デフォルト(Gamma)で使っており、Gammaが考慮されていないShaderを使っているため」が大体だと思われます

余談

Shader側でGamma想定のTextureがほしいときの対応もあるにはあるっぽい…?

[Gamma] - Float/Vector プロパティーが UI で sRGB 値で指定されており (色とまったく同じ)、使用するカラースペースに応じて変換が必要な可能性があることを示しています。詳しくは、Cg/HLSL でシェーダープロパティーを参照するを参照してください。

docs.unity3d.com

Textureも実質(?) Vectorなので効きそうな気もしますが未確認です

2020/07/10 21:30 追記

とても参考になる記事を見つけたので貼っておきます
自分でShaderを書いて対応する場合は参考になると思います

light11.hatenadiary.com

対応端末

これじゃあGamma辞めればいいじゃん!!という話になりますが、現実はそうもいかないケースがあります

プラットフォームの中には、ハードウェアがガンマ形式しかサポートしていないものもあります

docs.unity3d.com

まあこのご時世さすがに…そろそろ…ないでしょ…という気持ちはありますが…
特にAndroid端末は遭遇しがちだったりしますので各々のProjectで要確認ですね

まとめ

UnityにおけるLinearはGammaからのスムーズな移行を実現するためにこういった仕様になってるのかな~と思いました

実際ちゃんとカラーワークフローまで考慮して開発するケースはゴリゴリの映像作品とかになると思うのでそこまでちゃんとした知識はなくてもなんとかなると思います!

なにかあればTwitterの方にご連絡ください~

https://twitter.com/shop_0761

【Unity】BlenderからUnityにFBXを持ってくるときに気をつけること

まとめ

はちゃめちゃに簡単なので !EXPERIMENTAL! Apply Transform にチェックを入れて書き出して欲しい。するといろんな人が幸せになります という話です

2020/02/23 現在での方法です 仕様が変わるかもしれません

Blender 2.79以前

f:id:shop_0761:20200221152836p:plain

f:id:shop_0761:20200221152853p:plain

f:id:shop_0761:20200221152942p:plain

Blender 2.8以降

f:id:shop_0761:20200221153200p:plain

f:id:shop_0761:20200221153214p:plain

f:id:shop_0761:20200221155633p:plain

検証環境

Unity 2017.4.28f1
Unity 2018.4.14f1

Blender 2.79b
Blender 2.82

簡単な説明

ぱっと見 異常なくFBXが作成できているように思います

f:id:shop_0761:20200222184155p:plain

ですが、Unityが変に気を利かせて問題なく見えてしまっている というのが実情です よく見るとTransformの値が初期値ではない値が入っています

f:id:shop_0761:20200222184119p:plain

Blenderから出力したFBXファイルをUnityに持っていくとRotationやScaleが100倍になったりとおかしくなる

これが原因で様々な不具合が発生しやすくなります…

Boothでのモデル販売やVRChatで使うためにBlenderを使う人が増えてきたように思うので、

  • Rotationの X が -90 になっていないか
  • Scale が100倍になっていないか ( こっちのほうがやばい )

を確認するようにしましょう!
せっかくならキレイなデータになってるほうがよいので!

ちなみに最新のBlender 2.82 ではこの操作をしなくても Transform の値がキレイになってました
わ~い~!!

この件は典樹さんに教えていただきました ありがとうございます! twitter.com

告知

最近はこれのお手伝いをしています おたのしみに~

【UE4】FilmicTonemapperを打ち消してみた

はじめに

以前 こういうものをつくりました

speakerdeck.com

リポジトリはこちら

github.com

今回のも追加済みです

このイベント登壇後、いろいろ作り込んだり整理していたんですが、
Textureの色がそのままでない!!!!!

この話はこの辺でも触れられています

togetter.com

そこでこのスライドをみました

speakerdeck.com

f:id:shop_0761:20191014182156p:plain

これだ~~~~ これをちゃんとやればテクスチャの色が出る~~~ 

ということでやりました。 エンジン改造をしてしまうとごく少数の人しか使えないので、 Customノードで全部コードを書きました。

UE4.22 です。

コード

上記スライドの

return FilmToneMapInverse(col);

を以下に差し替えてください。

gist.github.com

もしくは上記リポジトリの下記Material Functionを AssetAction→Migrate 等で導入してください。(依存するのはMPC_tToonのみ)

tToon/MF_InverseTonemap.uasset at master · shop-0761/tToon · GitHub

解説

ながいので省略します 気が向いたらやります

精度的にはこのくらいいけます

これは

  • Color_checker テクスチャ(Texture_Color)
  • Viewportで打ち消し処理を入れてunlit表示したもの(Viewport_Color)

とを比較した結果です
適当なマテリアルを作ってスポイトで色を取っています

f:id:shop_0761:20191014182737p:plain

f:id:shop_0761:20191014182733p:plain

PostProcessVolumeのこれらの値を定数ではなく変数で式を組み立てたので
ここを編集しても変更に耐えうるとおもいます(未検証)

f:id:shop_0761:20191014183245p:plain

補足

色空間の変換や桁落ち、Tonemapper内で max(0,a) による負の値の欠損 などにより、一部誤差が発生しています
エンジン側のコードが変わらないと対応が難しいかも?
まあぼちぼち合っていますが…

2019/10/20 追記
現在 こちらの動画のように PostProcess のFilm Parameter を変更すると一部描画が乱れます
これは逆関数を作成した際に分母に0が来る場面があったり、少数での割り算が発生したりしやすくなっています
すぐ治らなさそう というとこまで分かったのでここに書いておきます

まぁ本来のACESにないパラメータを追加したUE側の検証不足な気もしますが

まとめ

難しい話をするよりコピペで使えるほうが便利かなとおもって説明を省きました
ここまでくるのに2ヶ月くらいかかったのですがようやく次にすすめるのでうれしい~~ というかんじです

何かあれば てんちょー / 筑野(ちくの)えり💕🍱 (@shop_0761) | Twitter まで~

【Unity】Fragment Shader と Surface Shader を一緒につかってみた【Shader】

引っ越しました。インターネットがありません。

はじめに

凹みさんの記事が読めればできます。 おわり。

tips.hecomi.com

この記事は先述の凹みさんの記事からいくつか抜粋して、簡略化したもの です。

簡易版というか最低限のコードを描くと、最終的にはこうなります。

そもそもなんで

Unity で使えるShaderはいろいろありますが、よく使うのは

  • Vertex Shader (以下 Vertex)
  • Surface Shader (以下 Surface)
  • Fragment Shader (以下 Fragment)

あたりだとおもいます。 で、これらを使うときには

  • Vertex + Surface
  • Vertex + Fragment

のペアで使うのが一般的だと思います。というかこれしか出来ない と思っていました。 ですが、ふと

Vertex + Fragment + Surface

はできないのかな と思っていろいろ調べて、先程の凹みさんの記事をよんでいたらできることがわかったので、かいておこうかなとおもいます。

今回は Shaderとは? みたいな説明は省略します。いろいろ良い記事があるので、そちらを参照ください。

コード

先にコードをはります。

gist.github.com

とこのように Surface, Vertex, Fragment がならんでおります。

簡単なせつめい

まず見通しをよくするためにForward Baseしか計算していません

Surfaceは人類がShaderを書く時に楽ができるようにしてくれている やつなので、「内部的にはfragmentに展開している」 と考えればそんなに難しくないかな とおもいます。

Vertex

Vertexは普段とほとんどやることはほぼ変わらないので、よいかとおもいます。
ただUNITY_TRANSFER_LIGHTINGがちょっとよくわからなかったので、だれか教えて…

surface

Fragmentに行く前に、surfaceを見ておきましょう
といってもStandard Surfaceと同じなので、ここは問題ないかなとおもいます

fragment

さて、今回の見どころはここです

ざっくり流れを説明すると

  1. Surface用の初期化と設定
  2. Surf関数を呼ぶ
  3. Lightの減衰 atten を取得
  4. GIの初期化と設定
  5. Standard用Lightningの計算

という感じです。こんなことができるんだ…

ほぼお作法みたいな感じな気がしますが。
Surfaceの関数だけ使いたいなら、上二つまででよいです。

せっかくならGIも と思って書いてあります。

これのいいところ

fragment で surface の展開ができる ということは、

  • 手元で書いてるのは fragment だけど、みつけたsample は surface だった
  • Unity GI を自前で計算できる

あたりかな…
GIを自前計算するときにsurfaceで使ってる情報が必要になってくるのでsurface周りの処理は省略はできなさそう。

個人的には冒頭の凹みさんの記事にある

機能単位(ライトマップ、リアルタイムGI、ライトプローブ、リフレクションプローブなど)を把握していれば、どこで何が行われているのか、ということを理解できるのではないでしょうか。これを理解するだけでも、自分の好みの絵作りをしたいときに役に立つよう使うことは可能だと思います。ということを示せるよう、どこかでトゥーンシェーディングに PBR の結果をブレンディングする内容を書いてみたいと思っています。

トゥーンシェーディングに PBR の結果をブレンディングする

にべんりかなぁ とおもいました。そのきっかけになれば〜

まとめ

SurfaceはFragment内で展開できる
トゥーンシェーダーにPBRの結果を混ぜられそう

なにかあれば Twitterで〜

twitter.com

引っ越し祝いも待ってます💕