線形空間で、GrabTextureの明るすぎる表示に対処するにはどうすればよいですか？

今回の主な話題：Androidプラットフォームの線形空間でGrabTextureの表示が明るすぎる、Graphics APIの選択、アニメーションをインポートする際のdiscarding joint scale/translation。

---
###レンダリング
Q1:歪み効果のためにGrabPassを使用しました。PCプラットフォームとiOSでは正常ですが、Androidプラットフォームでは、Bloomを開かないとエラーが表示されます。本来は一つの透明なパッチでありますが、比較的透明度の低い白いフィルムになりました。シェーダー全体をDebugした後、カラースペースの問題と疑わりました。Gammaスペースに戻った後、表示は正常になりました。

Shaderコードは下記のように：

```ruby:Shader
Shader "Custom/Effect/Distortion" {
    Properties {
        _TintColor ("Tint Color", Color) = (1.0, 1.0, 1.0, 1.0)
        _Refraction ("Refraction", 2D) = "white" {}
        _RefractionIntensity ("Refraction Intensity", Range(0, 1)) = 1
    }
    SubShader {
        Tags {
            "IgnoreProjector"="True"
            "Queue"="Transparent"
            "RenderType"="Transparent"
        }

        GrabPass{ "_GrabTexture" }
        Pass {
            Blend SrcAlpha OneMinusSrcAlpha
            ZWrite Off
            Lighting Off
            
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            #pragma target 3.0
            uniform sampler2D _GrabTexture;
            uniform sampler2D _Refraction; uniform float4 _Refraction_ST;
            uniform float _RefractionIntensity;
            fixed4 _TintColor;
            struct VertexInput {
                float4 vertex : POSITION;
                float2 texcoord0 : TEXCOORD0;
                float4 vertexColor : COLOR;
            };
            struct VertexOutput {
                float4 pos : SV_POSITION;
                float2 uv0 : TEXCOORD0;
                float4 vertexColor : COLOR;
                float4 grabPos : TEXCOORD1;
            };
            VertexOutput vert (VertexInput v) {
                VertexOutput o = (VertexOutput)0;
                o.uv0 = TRANSFORM_TEX(v.texcoord0, _Refraction);
                o.vertexColor = v.vertexColor;
                o.pos = UnityObjectToClipPos( v.vertex );
                o.grabPos = ComputeGrabScreenPos(o.pos);
                return o;
            }
            fixed4 frag(VertexOutput i) : COLOR {
                float4 _Refraction_var = tex2D(_Refraction, i.uv0);
                float2 sceneUVs = (i.grabPos.xy/i.grabPos.w + (_Refraction_var.rg*i.vertexColor.a*_RefractionIntensity));
                return tex2D(_GrabTexture, sceneUVs);
            }
            ENDCG
        }
    }
}
```

注：frag最後に線形スペースに強制された後、普通のreturnに近づいてきました
     pow(tex2D(_GrabTexture,sceneUVs),2.2)
>問題主が提供したコードによって、Redmi４Xでこの問題を再現しました。確かに、問題主が予測したように、それは設備に関連しています。pow（color、2.2）を追加した後、それは正常のようです。関連する公式ドキュメントを確認したところ、同じようなBugフィードバックがありました。ここでGLCoreが修復したことが示されています。GLESは修復していないと推定します。
https://issuetracker.unity3d.com/issues/grabpass-matrial-with-grabpass-shader-renders-much-brighter-on-opengl-in-linear
同時に、Unity2018バージョンでRedmi4Xを使用してテストしました、問題が解決されていることがわかりました。問題主がUnity2018を試すことができるようにすることをお勧めします。

---
###OpenGL
Q2：UnityでのGraphics APIの選択に関して、いくつかの質問があります。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/486c9cdd-c0b0-7762-ec41-e16953fc1315.png)
1）Androidで、選択肢はES2.0と3.0二つだけ、上図のように両者を選択した場合、Autoを選択することの違いはなんですか？常にES3.0を優先し、失敗したらES2.0に後退しますか？
2）他の人が言った通りに、ES2.0の効果は3.0の効果より悪いです。自分が変更したUnity PBR Shaderも、2.0の効果が3.0の効果よりも悪いという状況に遭いました。フレームをつかんだとき、それが電話での実際のShaderコンパイルバージョンが異なることがわかりました。Shaderが同じなら（マクロ定義が異なることはなし、すべて同じ路線と仮定します）、この両者がコンパイルされた2つの間にこのような大きなパフォーマンスの違いがありますか？
3）効率に関しては、Graphics APIの選択はGPUの効率にのみ影響し、CPUの効率には影響しませんでしょう？
>一つ目の問題に対して、問題主の理解は正しく、ES3.0がいつも2.0よりも優先されます。

>二番目の質問について、ES3.0は新しいバージョンのGLSL Shading Languageを導入しましたから、コンパイルされたものは明らかに異なります。
さらに、ES2.0とES3.0の変更はAPIだけではなく、ハードウェア機能の向上も表しています。特に、ES3.0は32ビットのフローティングポイント操作を完全にサポートしています。これだけで、効果に大きな違いをもたらすのに十分です。ちなみに、ES2.0はDepth Bufferに16Bitsをサポートすることを要求しますが、ES3.0は24Bits及び32Bitsをサポートすることを要求しています。

>三番目の質問に関しては、APIの変更により、CPU効率は必然的に変化します。たとえば、ES3.0はVAOをサポートしますが、ES2.0はサポートしません。

>参照：
https://www.khronos.org/registry/OpenGL/specs/es/2.0/es_cm_spec_2.0.pdf
https://www.khronos.org/registry/OpenGL/specs/es/3.0/es_spec_3.0.pdf
http://www.openglsuperbible.com/2013/12/09/vertex-array-performance

---
###アセット管理
Q3: 4で割り切れるNPOTアトラスを生成する方法は？ 良いアトラス分割戦略を選択する方法は？ テクスチャ圧縮形式はETC2（Android）+ ASTC（iOS）であるため、画像サイズが4で割り切れることが出来れば良いです。

現在、アトラスはUGUIに付属のSpritePackerを使用しています。生成されたアトラスのデフォルトサイズはPOTであるため、一部のアトラスが不十分になり、空白の領域が増えます。アーティストがアトラスの属性を手動で調整するのは非常に面倒なので、 NPOT +が4で割り切れるアトラスを生成するため、アトラスの属性をランダムに割り当てることができ、空白が多すぎることはありません。しかし、カスタムアトラスパッケージのドキュメントを読んだ後、関するインターフェイスが開いていないようです。

TexturePackerは、2で割り切れるNPOTアトラスしか提供できないため、類似のシステムを実現した友達はいませんが？考えの流れを頂戴。

さらに、いくつかの質問があります。

1）プロジェクトに異なるテクスチャ圧縮フォーマットが存在すると、（より大きな）パフォーマンスの低下が発生しますか？ たとえば、「すべてのETC2」および「できればETC1を優先し、次にETC2」。

2）現在のNPOTの実現（OpenGLESのNPOT拡張など）は、自動的にPOTに拡張されるではないでしょうか？ このようにすると、NPOTのメモリ占用はピットになります。

3）NPOTのパフォーマンスはPOTと比較してどうですか？ 確かなことは、POTは間違いなくNPOTより悪くはないということですが、2つの間のパフォーマンスのギャップをGoogleしたら多くの異なる意見があります。 したがって、こちらの質問は現代（モバイル）GPUに関するものですが、NPOTとPOTの間のパフォーマンスのギャップを考慮する必要がありますか？

4）以前はアーティストの習慣に気を配り、なるべく制限を少なくする傾向があったので、アトラスの分割では「アーティストは全く知らず、参加しない」ことを目指しており、アトラスが満たされないことを導きました。アトラスの分割は通常どのように行いますか？「アトラスを完璧に分割する」と「高い開発および維持コスト」の間のより良いバランスをどうやって見つけますか？私たちの主な考慮事項は、作業コストを削減することです。これにあまり時間をかけなく、そうすれば、完璧ではなく、良い効果を保証できます。

①
>私たちのプロジェクトのアトラス方案をシェアします。参照のみにしてください。
1）正方形のグラフのみが許可されます。
2）2のn乗を保証します（4で割り切れる問題を解決します）。
3）形式は問題主と同じですが、ETC1と2の混同には同意しません。ETC2の圧縮品質は明らかに良いで、高速です。
4）ICONと画像の名前と標準化を保証します。アーティストはアトラスを気にする必要はなく、プランナーさんが計画してテーブルを割り当てる予定があります。アトラスが変更された場合でも、アトラスのテーブルの名前のみを変更すれば大丈夫です。
5）アトラスの計画は、パブリックアトラスとシステムアトラスに分けられますが、関するUIインターフェイスには、アーティストとプランナーの使用を制限するためのアトラスの引用インデックスリストがあります。
6）プロジェクトは、3者間の制約のある環境です。自由が多すぎると、必然的に作業と通信のコストが増加します。アートデザインに対してのシステム標準化デザインが不可欠です。

②
>目前、私たちもETC（Android）+ ASTC（iOS）を使用していますが、要求は引き続きPOTであります。しかし、合併した2枚の連続正方形テクスチャのために、非正方形のテクスチャサイズは開かれています。UI部分はTexturePackerによって合併された後のAtlasを提出することを要求し、必ずPOTであります。
問題主の具体的な問題に対して、TexturePackerにはプラグインを作成する方法があるようです。あなたのニーズを満たさせられるために、プラグインを使用してサイズを4の倍数に制限してエクスポートできるかどうかがわかりません。
アーティストの習慣にお世話をするのは良いプログラムの表現です。問題主に「いいね！」を与えますが、パフォーマンスや他の役職に転嫁されないように、この部分の面倒のコストに注意してください。そうではない場合は、アーティストに勉強させ、ルールに従って作成することをお勧めします。

③
>NPOTに関して、公式ドキュメントを参照できます：
https://docs.unity3d.com/Manual/ImportingTextures.html

>2番目の問題に対しては：
https://answer.uwa4d.com/question/5b4422bbf91024518ab77aed（中国語注意）

>さらに、問題主は必ずNPOTアトラスを採用することに対して、もちろん、誰もあなたを止めることはできません。JSによって作成されたPackアルゴリズムが以下にあります。
https://github.com/jakesgordon/bin-packing

---
###アニメーション
Q4: Mecanimを使用してモデルをUnityにインポートすると、「has translation animation that will be discarded」と「has scale animation that will be discarded」というプロンプトが表示されます。つまり、一部の関節のScale/Translateアニメーションが破棄されますが、一部のアニメーションは正常に再生できます。ですから、MecanimはScale/Translateアニメーションをサポートしていますか？
>MecanimのHumanoidモードは、Scale / Translateアニメーションをサポートしていません。Scale/ Translateアニメーションが必要な場合は、Genericモードに切り替えることができます。 さらに、一部の関節のScale/Translateアニメーションは正常に機能します。これは、これらの関節が非Humanoid（Genericモードで実行する関節）関連であります。

---
###ロジックコード
Q5：PropertyInfoのCanWrite = false、このプロパティがListの場合、読み取りのみが可能で、書き込みはできません。このListに値を割り当てるにはどうすればよいですか？PropertyInfo.SetValueは、このプロパティに書けないため機能しません。今は、ListのAddメソッドを使用して値を追加したいと思いますが、それをうまく行う方法がわかりません。
>問題主はPropertyInfo.GetValueを使用してオブジェクトを渡し、asキーワードで戻り値をListに変換してから、Addをコールすることができます(PropertyInfo.GetValue(obj) as List).Add(xxx)。ただし、これで問題が発生する可能性があります。このListは毎回newされたものの場合、オブジェクト内部の変数は依然として変更できません。

---
UWA Technologyは、モバイル/VRなど様々なゲーム開発者向け、**パフォーマンス分析**と**最適化ソリューション**及び**コンサルティングサービス**を提供している会社でございます。

UWA公式サイト：https://jp.uwa4d.com
UWA公式ブログ：https://blog.jp.uwa4d.com