てんちょーの技術日誌

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

【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

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

【Unity】既存のEditor拡張を乗っ取って自分のEditor拡張を使う【Editor拡張】

はじめに

いろいろなアセットを使っていると便利なことにEditor拡張がついてきて使いやすい!!

けど、個人的にもうちょい足したい…が手を入れるとアセットの更新があったときに毎回マージするのはしんどい…

Editor拡張の拡張は出来なかったんですが、乗っ取ることはできたので今回はその話をします。

やりかた

Editor拡張を用意する

なんか書きます。

using UnityEngine;
public class Test : MonoBehaviour
{
    [HideInInspector]
    public string str = "こんにちは";
    public void Message()
    {
        Debug.Log("メッセージだよ: " + str);
    }
}
using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(Test))]
public class TestEditor : Editor
{
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();
        var test = target as Test;
        if (GUILayout.Button("メッセージをよむ"))
        {
            test.Message();
        }
    }
}

ボタンが出るようになるので、押すとログが出ます。

f:id:shop_0761:20190206041502p:plain

上書きしたいEditor拡張を書く

今回のメインはここ。とっても邪法です。

以下は推測です。

  • [CustomEditor(typeof(Hogehoge))] のtypeof で指定したクラスには一つのEditor拡張しか使えない
  • Editor拡張用のクラスを探すのは辞書順

だと思われます。これを逆手に取ります。

今回の場合は 辞書順にソートしたとき、 TestEditor.cs より早い名前にしてあげれば良さそうです。一文字削ってTestEdito.cs でもよいです。

using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(Test))]
public class TestEdito : Editor
{
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();
        var test = target as Test;
        if (GUILayout.Button("メッセージをよむぞ"))
        {
            test.Message();
        }
    }
}

f:id:shop_0761:20190206042011p:plain

できた~~~~~~~

拡張メソッドを書く

まあこれだとpublicな関数がたたけるくらいで、はい なるほど ってなって終わりなんですが

拡張メソッドも一緒に使うと便利です。

using UnityEngine;
public static class TestExtension
{
    public static void MessageExtention(this Test test)
    {
        test.str = "やあ " + test.str;
        Debug.Log("おりゃ 上書きしてあるぞい!: " + test.str);
    }
}

そして、上書きしたほうのEditor拡張である TestEdito.csには

using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(Test))]
public class TestEdito : Editor
{
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();
        var test = target as Test;
        if (GUILayout.Button("メッセージをよむぞ"))
        {
            test.MessageExtention(); //拡張メソッド
        }
    }
}

f:id:shop_0761:20190206042734p:plain

ということができます。

まとめ

なるべくよそのアセットには手を入れたくないけど、便利につかいたい…もうちょいEditor拡張したい…

ときに便利です。Editor拡張を _.cs とかにされたらどうするんだろ… 

だれが使うんだろ。おわり。

【VRM】キャラクター以外のVRMのつくりかた

はじめに

VRoid Hub やら THE SEED ONLINE、 VRM コンソーシアムなどいろいろでてきました。

そんな中以前、ふと試したら思いの外上手くいったVRMのハックです。 意外とすでにあるVRM対応アプリで読み込めたりします。

あわよくばこういうのに無理やり使えるのでは…??? とおもったり

今回試したもの

Candy Rock Star のステージをVRM化しました。

f:id:shop_0761:20181221213740p:plain

f:id:shop_0761:20181221213422p:plain

ちゃんと他のVRM対応ツールでも読み込めます。

VDRAW

f:id:shop_0761:20181221215045p:plain

Virtual Motion Capture

f:id:shop_0761:20181221215514p:plain

やりかた

とてもかんたんです。ようはUnityでHumanoidになれば何でもいい。 VRM化するところは省略します。他を参考にしてください。

DCCツールで骨を入れる

今回はBlenderにいれました。

f:id:shop_0761:20181221215806p:plain

で、Blenderの Rigifyで人型のボーンをいれます。 ここが参考になりました。

nn-hokuson.hatenablog.com

うごいた~~~

f:id:shop_0761:20181221220255g:plain

UnityにいれてHumanoidにする。

GenericからHumanoidにして、Configure みてみると

ちゃんときてる~~(あたりまえ)(虚無の人がいることになってる)

f:id:shop_0761:20181221220630p:plain

よくみると怒られています。

f:id:shop_0761:20181221220727p:plain

うるせ~~!!!!!

知らね~~~~~!!!!

Enforce T p

ose

をして黙らせます。

f:id:shop_0761:20181221220932p:plain

これで無事VRMとして書き出すことができます。よかったね!!!!!

f:id:shop_0761:20181221221533p:plain

さいごに

ちゃんとウェイトやBlendShapeを作ってあげれば、 手を振るとライトが回ったり、 LipSyncがスピーカーのエフェクトと同期させたりなんてこともできるかなと思います。

VRMは人型キャラクターだけ!と思われがちですが、 その辺の草とか石にもなれます。自分のほしい体を手に入れよう!

こういうことをしてVRoid Hubに上げて、SHOWROOM V と連携すれば 「学芸会の木」として配信ができるかも??? (ライセンスには気をつけてね)

参考

prtimes.jp

SHOWROOM V

SHOWROOM V

  • SHOWROOM INC.
  • エンターテインメント
  • 無料

hub.vroid.com

hub.vroid.com

横断歩道になりたかった

【Unity】SteamVR Plugin 2.0の入力方法を調べてみた

はじめに

少し前に正式版になったSteamVR Plugin 2.0 ですが、ベータ版のころ なんとかの男 に

「Steam VR Plugin 2.0 は入力周りがめっちゃ楽になるから移行しようぜ!!」

と言われて、ホイホイ乗り換えたのですが Steam VR Input周りでハマって見なかったことにしました。

けど正式版になったので、使ってみた というお話です。

現状だと、TsubokuLab の

3台目以降のViveコントローラーのボタン押下が取得できない

teruaki-tsubokura.com

が解決できるかもしれません。たぶん。おそらく。(未検証)

というのも旧版のSteam VR Pluginのときに Trackerを繋いだ瞬間、コントローラーの入力が全く取れなくなる という現象に遭遇しましたが(正式版2.0でも遭遇した)、

Steam VR Plugin 2.0 にした際に Steam VR のご機嫌と Unityのご機嫌を伺いながらやれば解決しました。

ここ最近のSteam VR わからんなんも…

導入とか

こちらが参考になるかと思いますので、今回は省略します。

qiita.com

ただ、SteamVRとSteamVR_Inputのフォルダの場所はAssets以下のほうが安心かもしれません…(InputのGenerateのときに永遠に終わらなかったことがある)(ベータの話)(治ってるかもしれない)

更新に伴う問題点

Trackerが変な方向に回ってる

最近のTrackerを体につけることが流行っているせいか、SteamVR側の仕様変更により 弊害がゴロゴロでてきています。(IKinemaとか)

解決方法

qiita.com

TrackerのSettingsにLeft FootやWaistがあるのでIKのターゲットにしたい人が増えたんだなぁという気がします。

コントローラーの入力が取れない

Trackerを繋ぐと入力がこなくなったりします。 ここはコントローラー2つペアリングしてからTrackerを繋ぐと治ったりします。おまじない。

他に考えられるのはSteamVR Inputで作ったActionsがちゃんとbindされていないとか。

f:id:shop_0761:20181012064521p:plain

f:id:shop_0761:20181012064618p:plain

そもそも入力のとり方がわからない

これさ…ドキュメントがなさすぎるんよ…

ということで、UniRxのMessageBrokerを使った便利クラスをちょっと書いてみたのでよければどうぞ

SteamVR_Input_LiveWindow.cs をほぼコピペです。ここが一番まともかなとおもって…

gist.github.com

サンプルのとこをコメントアウトして試すとLogが出る…はず…

一緒に Window → Steam VR Input Live View も見ておくと心に優しい。

参考

qiita.com

Tips

コントローラーしかペアリングしてないのにSteam VR Input Live View が真っ赤になる

ラッキングされてないと入力もこない ようです。 面倒がらずにセンサーから見えるとこに移動しましょう。

それでもだめな場合は、おとなしくSteam VRとUnityを再起動しましょう。

Steam VR 起動→ コントローラーペアリング → Unity 起動

の順がよい気がします。

ビルドすると入力がこない

EditorとビルドではBinding設定が異なる 気がします(めんどいのであまり検証してない)

密かにBinding UIの下の方にあるReplace Default Bindingでなんとかなるかも…しれない

f:id:shop_0761:20181012065536p:plain

そもそもこのBindingがPCごと?アカウントごと? に紐付いているようで、 この設定がうまくいかない場合 毎回PC OR アカウントごとに Bindingし直し が発生します。

ということは ビルド配布がほぼ無理 きがします(ビルドもらったユーザーがBindingしなおしはしんどすぎる

方法がわかったら誰か教えて…

--2018/11/08 追記-- Save Personal Binding をするときにちゃんと ファイル名をつける といける…かもしれない --追記おわり--

Steam VR Input のGenerate が終わらない

進捗バーが最後のほうまできたけど、なぜか終わらない…ということがあります。

が、無理やり中止しても動くときもあります。試してみましょう。

あとUnityはアクティブにしてないと処理が進まないようです。なんだこれ。

ひょっとしたら Trackerの設定を Disabledにすると入力がとれない?

怖くて検証するのを辞めたんですが、先程の参考記事にあった

「Manage Vive Trackers」ボタンで全てのtracker設定をdisableにしてください。

をすると…入力が何もこなくなるかもしれない…こわい…もうやだ…Cameraとかにしとこ…

ちなみにOrionのためにTrackerをたくさん繋ぐとManage Vive Trackers で左端のTrackerが見切れることがあります。

ブラウザでも一応みれるんですが、左端が見切れてしまう…

f:id:shop_0761:20181012070337p:plain

対処方法としては4Kモニタとかでブラウザ全画面表示するとみえました(解決にならない)

--2018/10/15 追記-- Ctrl + マウスホイール?でブラウザの拡大率を調整すればみえます()

オフライン環境

オフライン環境下で動かしたいことがあるかもしれません。もしくはSteamへのログインが面倒でしてないときがあったりします。

このままいくと「Steam VRがDisableだよ!!」みたいのがBinding UIのところにでます。

ので大人しくログインしましょう…ネット環境必須…っぽい…

--追記おわり--

まとめ

Steam VR への信仰心が高いとおまじないが効いてくるのでがんばりましょう。 Unity わからんなんも…

なにかあれば Twitterできいてください twitter.com

ホントそれ!!!!!!!!!!!!!!!!!!!!!! UE4 つかお!!!!!!!!!!!!!!

おわり