AddressableRemoteBuildPathでのアセット更新のアップロードの問題

1)AddressableRemoteBuildPathでのアセット更新のアップロードの問題

2)Shaderのメモリ使用量が突然増加します

3)Unity2018.4のマテリアルによるテクスチャへの冗長な参照

4)多数のGC操作がエディターに表示され、フリーズが発生します

5)JsonUtility.ToJson浮動小数点は小数を保持する問題


 

Addressable

QAddressableRemoteBuildPathを設定した後、Remote_Groupでアセットバンドルの一つを変更し(このGroupには複数のアセットバンドルがあります)、Build]-> Update the previous buildが終了後、RemoteBuildPathRemote_Groupのすべてのアセットバンドルがもう一回生成されます。(このパスからすべてのアセットバンドルを削除しても、再度実行するとすべて生成されます)。Remote_Groupの下のアセットバンドルをサーバーにアップロードしたいので、変更されたRemoteアセットのみをアップロードし、すべてのアセットバンドルを繰り返しアップロードしたくないのですが、どうすればよいですか?

 

A1:全部が再生成されますが、変更されたものだけが異なるはずです。hashファイルに記録されたhashが変更されているかどうかを比較して確認できます。実際、サーバーに直接アップロードするだけで十分であり、クライアントはさまざまなhashに従って変更されたBundleをダウンロードします。このモードでは、サーバーにあるのは最新であり、クライアントはバージョンに関係なく差分Bundleをダウンロードするだけで済みます。

 

A2:折衷案は以下の通りです。アップロードする前に、既存のファイルのmd5を計算し、新しいファイルとmd5値が変更されたファイルをサーバーにアップロードします。


 

Memory

Q:プロジェクトのUnityバージョンがアップグレードされた後、Shaderのメモリ使用量は元の100倍になりましたが、それは何故でしょうか?

A:これは、Unity2019.4.20がShaderのメモリ使用量の統計方法を変更したためです。 Unityはこのように変更したのは、問題をより適切に特定できるように、使用量が一番高いShaderを直接確認できるようになりました。

バージョンアップグレード後、Shaderの使用量は120 MB以上になり、ShaderLabは92KBになることがわかります。

2019.4.20f1 Release Notes


 

Material

Q:パッケージ化後、AssetHunterプラグインで分析すると、冗長な参照が多数あることがわかりましたが、ゲームでProfilerを使用するとなくなります。

マテリアルファイルを開いて、古いテクスチャ参照情報がたくさん保存されていることがわかります。

古いバージョンで使用されていた_CloudTex属性は、新しいShaderには含まれていません。参照を見つける一般的な方法は、関連するすべてのGUIDを見つけることです。そうすると、これらの古い参照が見つかりますが、スマホでProfilerを使用してメモリを調べると、関連する参照テクスチャは読み込まれません。Unityがパッケージ化時にこれらの古い参照を自動的に除外するためですか?エディターでこれらの冗長な参照を見つけることはできますが、無視できますか?

 

A1:古いShaderで使用されていたテクスチャ参照はシリアル化情報に保留されます。これはエディターでShaderを切り替えてから元に戻す際の再配置の問題を回避するために、Unityの意図的な設計です。

Unityはパッケージ化時にマテリアルに詳細な検査を行い、現在のShaderで使用されていないすべてのTexture依存関係を削除します。そのため、通常、古い参照をパッケージ化してもパッケージが大きくなることはありません。

ただし、エディターの下の古い参照にはまだ問題があります。

AssetDatabase.GetDependenciesインターフェイスによって返される参照には古い参照が含まれ、それらをカリングするための詳細な検出は実行されません。右クリックのアセットSelectDependenciesはこのインターフェースを呼び出すため、以下に示すように、古い参照も表示されます。

pic2とpic3は、現在Shader2によって参照されていません。

したがって、GetDependenciesインターフェースを使用して一部の機能を実装すると、古い参照が原因で予期しない問題が発生する可能性があります。解決策は、EditorUtility.CollectDependenciesインターフェースを使用して、古い参照をカリングした結果を返すことです。

さらに、Matとpic1、pic2、およびpic3に個別のABパッケージが割り当てられている場合、古いTexture参照がmat.manifestファイルに表示されます。これは、AssetBundleパッケージの不合理なところです。新しいAddressableシステムに改善するかどうかは調べていません。

 

 

A2:この投稿を参照してください:

https://forum.unity.com/threads/material-asset-keeps-references-to-assets-that-are-not-used.523192/

その中にCleanUpMaterialsを直接使用して、マテリアルをクリーンアップできます。


 

Editor

Q:エディターのAssetDatabase.GetAllAssetBundleNamesWithoutVariant()には多くのGC操作があり、フリーズになってしまいました。

 

手順の再現:

1.ゲーム内のマテリアルまたはその他のオブジェクトを選択します。

2.Unityエディターをバックグラウンドに切り替えてから元に戻します。ここでは、SublimeをクリックしてUnityに戻ります。

上記の2つの手順を完了すると、Unityは非常にスタックします。プロファイラーを介してEditorLoopを分析すると、以下に示すように、

AssetDatabase.GetAllAssetBundleNamesWithoutVariantに多数のGC操作があることがわかります。

 

使用されたのはUnity 2019.4.15f1です。私が試した解決策は次のとおりです。

  1. Unityバージョンの問題かと思ったが、ノートブックにインストールされている同じバージョンのUnityはプロジェクトを作成することが再現できません。
  2. OnInspectorGUIに問題があると思われ、コード内のすべてのOnInspectorGUIにコメントを付けても、再現できます。
  3. ShaderGUIに問題があると思われ、ShaderGUIに関連するすべてのコードを削除すると、再現することもできます。

 

他のアイデアはありますか?こちらの一時的な解決策は、選択したオブジェクトを切り替えることで、スタックすることはなくなります。

 

A:プロジェクトはAssetImporterのbundleNameを設定してバンドルをマークしますか?

importer.assetBundleName = bundleName;
importer.assetBundleVariant = variant;

エディター部分のソースコードを見ると、

AssetDatabase.GetAllAssetBundleNamesWithoutVariant();というAPIは、次の部分が描画されたときに呼び出されることがわかりました。

BundleNameとBundleVariantがもっとあるとしたら、ラグが発生しますか?

 

Q:プロジェクトがアセットをインポートしたとき、Bundle Nameのみが設定されました。つまり、importer.assetBundleName = bundleNamというように設定されました;プロジェクトはBundleVariantを設定しませんでしたが、実際に多くのBundleNameがあります。BundleNamesの数に対し、上限はありますか??

 

A:コードでAssetDatabase.GetAllAssetBundleNamesWithoutVariant()(internal方法、リフレクションを通して呼び出します。)を手動で呼び出して、大量のGCとフリーズすることになるかどうかを確認します。自分で呼び出しても、ラグも発生したら、これが原因だと判定できます。Bundle Nameが多すぎてスタックしている場合は、AABメソッドを使用してバンドルをパッケージ化したら済みます。importer.assetBundleNameは設定しないでください。


 

Script

Q:JsonUtility.ToJsonを使用する場合、floatタイプを保存するときに、小数点以下2桁が事前に予約されていますが、ToJsonの結果は1.059999999999999です。解決策はありますか?

 

A:残念ながら、UnityのJsonUtilityはNativeレイヤーに実装されています。ネイティブレイヤーはクローズドソースであり、インターフェイス機能をほとんど提供していません。Newtonsoft.jsonのような他のJsonプラグインを使用することをお勧めします。

 

A2:LitJson4Unityの改正バージョンをお勧めします。

https://github.com/XINCGer/LitJson4Unity

LitJson4Unity:Unity用の改良されたLitJsonライブラリ

紹介:ネイティブLitJsonライブラリに基づくUnity用のLitJsonライブラリ。

ネイティブバージョンでサポートされていない次の機能がサポートします。

floatタイプをサポートします(最新のネイティブバージョンはすでにサポートしています)

Unityの内部で構築されたタイプ(Vector2、Vector3、Rect、AnimationCure、Bounds、Color、Color32、Quaternion、RectOffsetなど)をサポートします。

JsonIgnore Attritubeをサポートし、一部のフィールドのシリアル化をスキップします

出力Jsonコンテンツのフォーマットのサポートし、より定期的になります。

使用方法:Plugins/LitJsonディレクトリにあるすべてのcsスクリプトをプロジェクトに配置するだけです。

[Unityゲーム開発]MaSanをフォローして、LitJsonを魔法のように変えましょう

https://www.cnblogs.com/msxh/p/12541159.html


UWA公式サイト:https://jp.uwa4d.com

 UWA公式ブログ:https://blog.jp.uwa4d.com

UWA公式Q&Aコミュニティ(中国語注意):https://answer.uwa4d.com

【HDRと色彩管理】SDRとHDR

このセクションは、HDRとACESの部分の下地にしているにすぎません。例として最もよく知っているsRGB色空間を取り上げ、主に、前述のさまざまな知識がSDRラインでどのように機能するかを学びます。 主には:

(1)色空間のViewing EnvironmentとImage State

(2)ゲームレンダリング用のSDR Color Pipelineはどのように機能しますか?

(3)Tonemappingは何ですか、必要となる理由は?


 

3.1理想世界:HDR

PBRレンダリングでは、シーンを照らすために実際の照明値を参照することがよくあります。 たとえば、明るい日光環境は120k luxに達する可能性がありますが、月光は約0.25 luxにすぎません(wikiを参照)。輝度( Luminance)を使用して、特定の方向の単位面積あたりの発光強度Luminous Intensity、単位cdカンデラ)を測定します。そのSI単位International System of Unitsはcd /m²(カンデラ/平方メートル)、つまりnitsです。 ここでは、明度Brightnessと輝度Luminanceの違いに注意してください。明度は主観的な視覚を表すことに対し、輝度は測光値です。

https://chrisbrejon.com/cg-cinematography/chapter-1-color-management/を参照

一般的なLCDモニターの輝度は約250nit、HDR TVは450〜1500 nit、蛍光灯は12,000 nit、太陽のは約16億nitです。

Source: HDR in Call of Duty

 

特定の方向の単位面積あたりの光度を測定する輝度と同様に、よく目にするもう1つの物理量は照度Illuminanceであり、そのSI単位はlm /m²(ルーメン/平方メートル)で、lux(ルクス)です。 照度は、単位面積あたりの物体の表面に入射する光束Luminous Flux、単位lmルーメン)を測定する物理量です。 まとめると、輝度(Luminance、単位cd /m²)と光度(Luminance Intensity、単位cd)、照度(Illuminance、単位lm /m²)、光束(Luminous Flux、単位lm)の関係は次のようになります(これらの光学物理量間の詳細な数学的関係はwikiを参照できます):

Source: HDR in Call of Duty

現在、UE4とUnity HDRPはどちらも物理的な照明パラメーターをサポートしているため、アーティストはエンジン内の現実世界のさまざまな光源を簡単にシミュレートして復元できます。物理的な照明環境についてLiWenleiが書いたUE4 Blog(中国語注意)をお勧めします。 UE4を例にとると、UE4はバージョン4.21で物理ライトユニットを導入しました。

(1)平行光:照度(Illuminance)を使用して強度を測定します。つまり測定単位はluxです。

(2)静的光源としての天光およびその他の自己発光材料:輝度(Luminance)を使用して強度を測定します。つまり測定単位はcd/m²です。

(3)ポイントライト、スポットライト、サーフェスライト:発光強度(Luminance Intensity)と光束(Luminous Flux)のいずれかを選択できます。つまり、つまり測定単位はcdまたはlmです。

実世界の光の比率が非常に大きいことがわかります。レンダリングでこのハイダイナミックレンジレンダリング(High Dynamic Range Rendering,HDR rendering)を復元して、レンダリングされた画像がより詳細でコントラストを保持できるようにします。Nvidiaは、HDRを使用する3つの動機をまとめました。

Bright things can be really bright, dark things can be really dark, and details can be seen in both.

—— From Nvidia

照明値に比例するような色空間で作業する場合、この色空間を「シーン参照色空間Scene Referred Color Space」または「レンダリング空間Rendering Space」または「作業空間Working Space」と呼びます。

A scene referred image is one whose light values are recorded as they existed at the camera focal plane before any kind of in-camera processing. These linear light values are directly proportional to the objective, physical light of the scene exposure. By extension, if an image is scene referred then the camera that captured it is little more than a photon measuring device.

—— From this article

 

レンダリングで最も一般的なシーン参照色空間は、sRGB色空間です。 ほとんどの場合、ゲームレンダリングで使用されるカラースタンプは、ほとんどがsRGB色空間で作成されます。Photoshopを例にとると、PSの色設定で現在の作業スペースを選択できます(次のsRGB IEC61966-2.1は長い名前ですが、最も頻繁に使用するsRGB色空間です)。

これらのsRGBスタンプは、sRGB OETF関数を介してエンコードされ、さまざまなスタンプ形式で保存されます。これらのsRGBスタンプをレンダリングエンジンにフィードします。エンジンがこれらのテクスチャを読み取ると、エンコードされた値がsRGB EOTF関数を介して元の線形カラー値にデコードされ、対応するBDRF照明計算が他の物理的なものと組み合わせて実行されます。


 

3.2厳しい現実:SDR

HDRレンダリングは素晴らしいですが、レンダリング結果を表示する必要がある場合、SDRディスプレイに遭遇します。 SDRディスプレイの2つの最も一般的な色空間標準は、sRGBとRec.709/BT.709です。以下は前の記事で言われたことのリマインダーです:

lRec.709:フルネームはITU-R Recommendation BT.709であり、Rec. 709、BT.709、ITU 709などと略されることがよくあります。1990年にHDTV(high-definition television)およびその他の分野の色空間標準として最初に提案されました。

lsRGB:フルネームはstandard Red Green Blueです。これはRec. 709から派生し、1996年にHPとMicrosoftによって開発され、ネットワーキング、Windows、印刷などの分野で使用されたRGB色空間標準です。 IEC委員会International Electrotechnical Commission。によって設定されたIEC61966-2-1:1999によって標準化されており、指定された色空間を持たないすべての画像で使用される「デフォルト」の色空間でもあります。

 

これらのディスプレイデバイスに依存する色空間は、「Display/Output Referred Color Space」または「Display/Output Space」と呼ばれます。

A display referred image is one defined by how it will be displayed. Rec.709 for example is a display referred color space meaning, the contrast range of Rec.709 images is mapped to the contrast range of the display device, a HD television.

—— From this article

前回の記事では、この2つの色空間について簡単に触れましたが、実際にはまだ取り上げていない詳細がたくさんありますので、ここで説明します。 sRGBとRec.709の3つの原色と白色点の値はまったく同じです。つまり、CIE 1931 XYZ色空間の変換行列とまったく同じであり、それらの違いは転送関数にあります。別の伝達関数を使用する必要がある理由は、sRGBとRec. 709のViewing Environmentが異なるためです。

 

では、Viewing Environmentとは何ですか?後でさまざまな用語を理解しやすくするために、これまでに言及されていない色空間の他のいくつかの特性を説明します。完全な色空間を定義するときは、3つの原色、白色点、伝達関数に加えて、他のいくつかのプロパティも定義する必要があります。

(1)Image State:色空間をいくつかの異なる画像状態に分類します。最も一般的なのは、前述のScene Referred ImageとDisplay/Output Referred Imageです。

(2)Viewing Environment:Viewing Environmentの厳密な定義について、良く理解していません。ここでは、私自身の理解に基づいて、このプロパティが必要な理由を説明することしかできません。人間の目の視覚は適応性があるため、脳は現在の観察環境に依存して色を理解します。たとえば、同じ白い紙は明るい天光とタングステン光の両方で白と見なされますが、実際には2つの照明環境で異なる光を反射します。したがって、色空間の観測環境を定義する必要があります。これは、色空間の白色点値、伝達関数、およびその他の値に影響します。たとえば、DCI-P3の白色点とガンマは、ある程度に劇場などの薄暗い投影条件に適合しています。

(3)Data Type:データが8-bit、10-bit、16-bitのいずれであり、形式がinteger整数またはfloating point浮動小数点であるかなど、この空間でのカラーデータの範囲と精度を指定します。

sRGBとRec.709の違いに戻りましょう。 前述のように、sRGBとRec.709のViewing Environmentは異なります。 sRGB規格で想定されている表示環境は、PCの一般的なアプリケーションシナリオである、照明条件の良いオフィス環境です。 Rec。709規格の表示環境は、ホームシアターなどのより薄暗い照明環境で使用されます。したがって、それらの伝達関数は、それぞれの環境でより良く画像の詳細を表す関数曲線として選択されます。 これら2つの伝達関数を同じ画像に使用した場合の効果の対照は次のとおりです(画像の背景は観察環境を示しており、右側の画像のコントラストが暗い部分で強くなっていることがわかります)。

Source: HDR in Call of Duty

Rec.709規格は、実際にはデジタルカメラの正確なOETF伝達関数(encoding function、camera gamma/scene-referred gammaとも呼ばれます)のみを定義し、表示用のEOTF伝達関数を指定していないことに注意してください。 この正確なOETF関数は次のとおりです。

このうち、Lは0〜1のシーン輝度値に正規化され、Vはエンコードされたデジタル信号値を表します。Rec.709自体はEOTF(display referred gamma)を指定していないため、委員会はITU-R BT.1886(BT.1886)のRec.709の表示ガンマ関数EOTF(decoding function)を指定しました。この関数は次のとおりです。

ここで、aとbは2つの定数パラメーターであり、ターゲットディスプレイのblack levelとwhite levelの値から導出できます。理想的な条件下のディスプレイデバイスの場合、そのblack levelは純粋な黒であると見なすことができ、上記のEOTFは純粋な2.4ガンマ曲線になります。 これは、CES Rec. 709 Output Transformで使用される関数曲線でもあります(ACESについては後で詳しく説明します)。

 

対照的に、sRGB色空間標準のOETF関数は次のように定義されています。

このうち、Lは0〜1のシーン輝度値に正規化され、Vはエンコードされたデジタル信号値を表します。 sRGBのEOTF関数は次のように定義されています。

IEC 61966-2-1:1999で規定されている規格は上記のとおりですが、sRGB画像のEOTFが正確に何に使用されるかについてはいくつかの論争があります。 sRGBの伝達関数は2.2のガンマ曲線に近似しているため、sRGB OETFの線形部分は、0に近い部分の量子化誤差の低減を防ぐためだけのものであり、その本質は2.2のガンマ曲線であると考える人もいます。彼らは、モニターを校正するための純粋な2.2EOTFガンマ曲線を使用すべきだと考えています。これにより、ユーザー端末のsRGBディスプレイに表示される輝度値がさらに不確実になります。これらの複雑で混沌とした状況については、ここでは詳しく説明しません。

 

これまでのところ、ゲームでのHDRレンダリングからSDR表示までの一般的なプロセスは、次のように要約できます。

1.Photoshopなどの描画ツールで生成されたsRGB空間のカラー画像は、sRGB OETFを介して線形カラー値を非線形信号値にエンコードして保存し、レンダリングエンジンに送信します。

2.レンダリングエンジンは、非線形データをsRGB EOTFを介して線形カラー値に再デコードし、線形レンダリングパイプラインに入力します。

3.線形レンダリングパイプラインは、物理的な光パラメータと線形オブジェクトのマテリアルプロパティを使用して、対応するBRDF計算を実行し、最終的にダイナミックレンジの高いscene referred imageを取得します。

4.使用するSDRディスプレイの色空間標準に従って、上記のscene referred imageに対して色空間変換を実行し、ディスプレイの色空間のOETFを使用して、ディスプレイが読み取れるビデオ信号にエンコードし、display referred imageを取得します。

5.SDRディスプレイは、EOTFを使用して、エンコードされたdisplay referred image信号値を最終的にディスプレイ画面の輝度値に変換します。

 

ほとんどの場合、ゲームで使用されるSDR Color Pipelineのscene-referredとdisplay referred色空間は、sRGB / Rec.709で使用される3原色と白色点の値であるため、手順4での色空間変換は通常は省略でき、sRGB OETF(PC)またはRec.709 OETF(TV)を直接使用して、scene referred imageをdisplay referred imageに変換します。つまり、sRGB PCディスプレイを出力する最も単純なSDR Color Pipelineの場合、ゲームエンジンが実行する必要のあるプロセスは次のように簡略化できます。

6.sRGBカラースタンプにsRGBEOTFデコードを実行します

7.線形レンダリング空間でのシーンレンダリングを行います

8.LinearTosRGBなどの関数を使用してsRGBOETFで最終出力をエンコードし、ディスプレイに送信します

 

これは、よく言われる線形空間レンダリングとガンマ補正のプロセスです。


 

3.3 HDRからSRDへ:Tonemapping

 

上記のSDR Color Pipelineには致命的な問題があります。scene referred imageからdisplay referred imageに変換するプロセスでは、これらの高ダイナミックレンジの輝度値を非常に制限されたディスプレイ輝度値に変換する必要があります。sRGBのOETF関数を振り返ると、出力値Vは0〜1の範囲のビデオ信号値である必要があり、入力値Lの範囲は0〜1の間である必要があります。HDRレンダリングで得られたシーンカラー値をLとしてOETF関数に直接入力すると、1を超える輝度値は完全に失われます。これにより、最終的にレンダリングされた画像のコントラストが非常に低くなり、中間の灰色の値が明るすぎ、ハイライトが完全に切り捨てられます。

Source: https://chrisbrejon.com/cg-cinematography/chapter-1-color-management/

 

この問題を解決するには、scene referred imageからdisplay referred imageに変換するプロセスで変換ステップ——Tonemappingを挿入する必要があります。Tonemappingは、シーン内の光源の輝度やマテリアルプロパティを実際に変更する必要はなく、画像の表示方法を変更します。フィルムや撮影にも同様の概念があります。Tonemappingは近年提案された新しい用語ですが、長い間、特に現実的なスタイルを描くの創造的なプロセスでは、アーティストに使われてきました。初期の画家は、絵を描くときの顔料の特性と種類が限られていたため、顔料を使用して実際のシーンをキャンバスに再現しようと最善を尽くします。この動作自体が、Tonemappingを適用するベストプラクティスと言えます。フィルムの領域でも、Tonemappingのような操作で、シーンの輝度をフィルムが表現できる限られた輝度の範囲に再マッピングする必要があります。

 

グラフィックスでは、Tonemappingの本質は、関数を使用して高ダイナミックレンジの輝度値を0-1の範囲にマッピングすることです。ゲーム開発の歴史には、最も初期の最も単純な経験派であるReinhardから、アンチャーテッド2で使用された適合派であるHable Filmic、使いやすさとパフォーマンスを向上させるための改良版のFilmic Curves、更に集大成のACES Filmic Tonemappingまで、さまざまな種類のTonemapping曲線がありました。より詳細な比較については、トーンマッピングの進化(中国語注意)を参照してください。また、さまざまなトーンマッピング曲線の効果の比較については、MJPのブログを参照してください。

 

Tonemappingは現在まで発展しており、基本的にはSカーブを使用して各領域(shadow、midtone、highlight)のパフォーマンスを制御するようにでき、カーブの中央部分のコントラストを増加させ、両端を縮小させます:

Source: https://chrisbrejon.com/cg-cinematography/chapter-1-color-management/

ACES Filmic Tonemappingカーブでは、輝度が1である値が約0.86に再マッピングされます。これは、元のシーンで1を超えるハイライトされた部分が0.86〜1の範囲に再マッピングされることを意味します。 これにより、最終的にレンダリングされた画像は、より多くの照明の詳細とコントラストを保持でき、画像はより鮮明になります。

Source: https://chrisbrejon.com/cg-cinematography/chapter-1-color-management/

 

Tonemapping以外、HDRレンダリングに密接に関連する別の計算は露出(Exposure)です。 簡単に言えば、露出は輝度のスケーリング倍率です。たとえば、天光を使用するシーンの場合、撮影の分野でよく知られている太陽光16のルールを参照し、レンダリングされた画像の輝度をスケーリングできます。

 

このように、TonemappingとExposureを追加した後、比較的完全な初期のSDR Color Pipelineを取得できます。 以下は、HDR Color Pipelineを使用する前に、コールオブデューティインフィニットウォーフェアとアドバンスドウォーフェアの以前の作品で使用されたSDR Color Pipelineです。

Source: HDR in Call of Duty

図にある手順は次のとおりです。

(1)青い枠付けの部分は、Scene Referredスペースでの操作を表しています。これは、sRGBの3原色で表される線形カラー値を使用し、レンダリングされたシーンの輝度の値は数千ニットに達する可能性があります。このHDR Scene Referred(sRGB linear space)では、いくつかの後処理計算も適用されます。

(2)露出曲線とTonemapping曲線を使用して、シーンの輝度を表示可能な範囲に再マッピングします。

(3)その後、sRGB OETF伝達関数を使用してデータをエンコードします。このステップでは、sRGB gamma space(緑色の枠付けの部分)であるDisplay Referred色空間に変換しました。

(4)sRGB gamma spaceで、後続のSDR後処理計算、Color Grading、AAとUIレンダリング操作を引き続き実行します。

(5)最後に、信号がSDRディスプレイに送信され、ディスプレイアプリケーションEOTFによってエンコードされた電気信号が再び実際のディスプレイの輝度に変換されます。


 

3.4将来のトレンド:HDR Display

ハードウェアテクノロジの継続的な更新に伴い、既存のSDR Color Pipelineの欠点が徐々に明らかになります。まず、sRGB/Rec.709色空間の色域は非常に限られており、CIE 1931色空間の約35.9%しか占めていません。そして、異なるSDRディスプレイデバイスのピーク輝度は異なり、SDRTVは一般にSDRPCディスプレイのピークよりも明るいです。たとえば、sRGB CRTディスプレイの明るさは約80cd /m²で、120 cd /m²に調整できますが、ほとんどのLCD TVモニターは200〜300cd/m²の輝度を実現できます。したがって、より良い視覚効果を得るために、異なる輝度ピークを持つSDRディスプレイに異なるTonemapping曲線を使用することをお勧めしますが、これは、異なる出力デバイスとの互換性が必要であることも意味します。

 

この種のデバイスの互換性は、HDRディスプレイの導入後、より複雑になります。どのように最小限のコストのもとで、レンダリングされた画像をさまざまなSDRおよびHDRディスプレイで一致している画面を得るか、より多くの3Aゲームのレンダリングに対しては考慮すべき方向です。幸いなことは、映画およびテレビ業界によって提案されたACES(Academy Color Encoding System)は、多くの互換性作業を削減する統一されたソリューションを提供します。これについては、次の記事で説明します。


参考文献:

  1. https://chrisbrejon.com/cg-cinematography/chapter-1-color-management/
  2. Digital Dragons 2018: HDR in Call of Duty
  3. https://www.tftcentral.co.uk/articles/pointers_gamut.htm
  4. https://nick-shaw.github.io/cinematiccolor/common-rgb-color-spaces.html
  5. https://64.github.io/tonemapping/

UWA公式サイト:https://jp.uwa4d.com

UWA公式ブログ:https://blog.jp.uwa4d.com

UWA公式Q&Aコミュニティ(中国語注意):https://answer.uwa4d.com

Addressableホットアップデートアセットタイプに関する質問

今回の話題:

1)Addressableホットアップデートアセットタイプに関する質問

2)Unityの再起動後、ローカルで削除されたFBXのDefaultMaterialが無効になります

3)MeshRendererの効果を実現する方法

4)Itemを動的にロードするUGUIのDrawCall問題

5)Loading.CheckConsistency[Editor Only]エディターでの最適化問題


 

Addressable

Q:Addressableは、AssetBundleを使用せずに、Text/Xmlなどの元のアセットをホットアップデートできますか?Addressableをホットアップデートソリューションとして使用するかどうかを検討しています。一部のアセットは、AssetBundleを経由せず、直接読み取りたいと考えています。Addressableがそれをサポートしているかどうかわかりませんか?

 

A:現在、AddressableはRawアセットを直接サポートしておらず、基本的にAssetBundleを使用しています。

1つのアイデアは、これらのアセットを単独にAssetBundleにすることです。論理的には、それは引き続き別個のTextとして扱われ、Binaryはそれを読み取ります。

もう一つのアイデアは、拡張変換を行うことです。「File.ReadAllText(path);」を使用して内部でアセットを取得するTextDataProviderというProviderクラスがあることがわかります。実際にAddressableAssetGroupSchemaとBuildScriptBaseを実装し、RawAssetSchemaとBuildScriptRawAssetの拡張を作成してパッケージ化することができます。


 

Editor 

Q:Addressablesシステムを使用してAssetBundleにすると、Default Materialが冗長になります。パッケージャーでスクリプトを実行してFBXのデフォルトのマテリアルを削除し、紫色に変えますが、プロジェクトを再び開いた後、デフォルトのマテリアルが元に戻り冗長も残られています。(Unityバージョン2018.4.34)

 

マテリアル削除されたスクリプト:

using System;
using UnityEngine;
using System.Collections;
using System.IO;
using UnityEditor;
using Object = UnityEngine.Object;

class DisableMaterialImport : AssetPostprocessor {

    [MenuItem("Tools/Reimport All Model")]
    public static void ReimportAllModel()
    {
        var assetPaths = AssetDatabase.GetAllAssetPaths();
        Array.Sort(assetPaths);
        Debug.LogWarning(string.Format("Total assets count: {0}", assetPaths.Length));
        int processedCount = 0;

        foreach (string assetPath in assetPaths)
        {
            string normalizedAssetPath = assetPath.ToLower();
            if (!normalizedAssetPath.EndsWith(".fbx") &&
                !normalizedAssetPath.EndsWith(".obj") &&
                !normalizedAssetPath.EndsWith(".3ds"))
            {
                continue;
            }

            var modelImporter = AssetImporter.GetAtPath(assetPath) as ModelImporter;
            if (modelImporter == null || modelImporter.importMaterials)
            {
                continue;
            }


            AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.ImportRecursive | ImportAssetOptions.ForceUpdate);
            Debug.Log(assetPath, AssetDatabase.LoadMainAssetAtPath(assetPath));

            processedCount++;
        }

        Debug.LogWarning(string.Format("Total processed model count: {0}", processedCount));
        AssetDatabase.SaveAssets();
    }

    private static void FixedModelImport(ModelImporter modelImporter, GameObject model)
    {
        //Debug.Log("FixedModelImport "+model);
        var renderers = model.GetComponentsInChildren<Renderer>(true);
        if (renderers == null)
        {
            return;
        }

        modelImporter.importMaterials = false;
        modelImporter.importBlendShapes = false;
        modelImporter.importAnimation = false;
        modelImporter.isReadable = false;
        modelImporter.optimizeMesh = true;

        foreach (var renderer in renderers)
        {
            if (renderer == null)
            {
                continue;
            }

            renderer.sharedMaterials = new Material[renderer.sharedMaterials.Length];
        }

/*        var animator = model.GetComponent<Animator>();
        if(animator!=null) Object.DestroyImmediate(animator);*/
    }

A1:ここでテストしましたが、元に戻りません。プロジェクトがロールバックされた可能性があります。さらに、このスクリプトのReimportAllModelは、「Import Materials」がオンになっていないモデルにのみ有効です。

A2:何度か試したところ、Cache Serverをオフにすれば済みます。


 

Editor

Q:Prefabをシーンに直接ドラッグするのではなく、レベル内のオブジェクトをスクリプトを介して間接的に作成する必要があります。 そのため、MeshRendererのようにシーンに直接表示して、選択と編集を簡単にできるようにする必要があります。

 

コードは次のようになります。

public class SpawnPrefab : MonoBehaviour
    {
        public GameObject prefabEntity;
        void Start()
        {
            Instantiate(prefabEntity);
        }
    }

MeshRendererには、次の2つの特性があります。

1.Editorモードでは、SceneViewとGameViewが同時に表示されます。

2.実行モードで描画されたオブジェクトは、SceneViewで選択できます。

 

現在、OnDrawGizmos関数でGraphics.DrawMeshを呼び出していますが、SceneViewで選択できず、Updateで描画するときにエディターモードで表示できません。方向が間違っているような気がします。

 

A:OnDrawGizmosで描画することは明らかに不可能です。この関数は、Runtimeがパッケージ化されているまでは呼び出されません。

SceneViewで「編集」を選択するには、シーン内のGameObjectである必要があります。 (GameObjectでMeshRendererをハングアップすると、「SceneView編集」と「ランタイムスクリプト作成」の2つの要件を確実に満たすことができます。)

問題主の要件がGraphicsの即時レンダリングインターフェイスを使用してMeshを描画し、それをEditorの下に表示することである場合は、クラスにExecuteAlwaysプロパティを追加したら済むが、SceneViewで選択して編集することはできません。

Sceneウィンドウに編集機能も実装したい場合は、シーンにあるMeshRendererをハングアップしたGameObjectを描画するMeshにバインドすることしかできません。 Graphics.DrawMesh描画オブジェクトのTransformは、このGameObjectと一致すればいいです。次の図に示すように、GameウィンドウはOnPostRender関数でGraphics.DrawMeshNow関数によって描画される効果を示し、Sceneウィンドウはバインドされた編集と調整用のオブジェクトです。2つのTransformは同じです。

キーコードは次のとおりです。


 

UGUI

Q:Itemの動的ローディングに関して、これは散在していますか?Itemが多数ある場合、何回のDrawCallが必要になりますか?誤っていると感じたが、この面に関してどう勉強すれば良いか?または実際の作業では、これは気にしなくても良いでしょうか?

これは所詮一つの例にすぎません。通常のプロジェクトで要素がこれほど少なくなることは不可能です。要素が多い場合、それらを動的にロードするにはどうバッチすればよいですか。動的にロードされたItemの要素を処理するための別のスクリプトを作成する場合、それはあまりにも不合理です。たとえば、NGUIはDepthを使用して、パネルの下の要素のバッチ処理を制御しました。UGUIが配置の順序によって制御されることだけを知っています。この場合、動的ロードにはあまりにも不向きです。

 

A1:同じマテリアルを共有し、他のバッチ条件を満たすメッシュは、隣接する順序でレンダリングすることでバッチ処理できるため、DrawCallが削減されます。したがって、バッチ処理の鍵は、同じマテリアルを使用するオブジェクトのレンダリング順序を制御することです。

バッチ条件と最適化方法には、次の資料があります。

https://blog.uwa4d.com/archives/optimzation_cpu.html

https://docs.unity3d.com/Manual/DrawCallBatching.html

Unityでのレンダリング順序に影響を与える要因:

https://zhuanlan.zhihu.com/p/55762351

さまざまなアセットがさまざまな方法でレンダリング順序を制御します。たとえば、MeshRendererはマテリアルのRenderQueueを設定でき、ParticleSystemはOrderInLayerとSortingLayerを設定できます。

UGUI要素のレンダリング順序は、UGUIプラグイン自体によって決定されます。必要なのは、UGUIが要素をレンダリングする方法を理解し、同じマテリアルのUI要素を可能な限り隣接する順序でレンダリングすることです。具体的な重要なポイントは次のとおりです。同じレイヤーのUI要素が重複しないように、UGUIはレイヤーごとに描画され、同じマテリアルのUIが同じレイヤーとして描画されるようにします。たとえば、問題主のプロジェクトのImgは同じレイヤーに配置され、Txtは2番目のレイヤーに配置されます。 2つのImgを積み重ねると、1つのImgが2番目のレイヤーとして描画され、Txtの描画とImgの描画が互いに散在し、DrawCallが追加されます。

それらが重ならない限り、同じアトラスを使用する同じレイヤーの要素は自動的に一緒にバッチ処理されます。複雑なインターフェイスの場合は、可能な限りアトラスを組み合わせることができます。複数のレイヤーの場合、同じマテリアルの要素が同じアトラスを使用し、隣接する順序で描画することを確認する限り、バッチ処理することができます。UGUIにアトラスが増えると、DrawCallを制御する良い方法はなくなります。

 

A2:Itemの領域が別のItemの領域と重ならない限り、すべてのテキストは2番目のレイヤーとしてカウントされ、Imageは1番目のレイヤーとしてカウントされます(2回のDrawCallのみ)。他のUI要素の影響を受けることを恐れている場合は、これらのItemをCanvasだけに配置して、他のUI要素の影響を受けないようにすることができます。

 

Editor

Q:Loading.CheckConsistency [Editor Only]はエディターで時間がかかりますが、それは何をし、どのように最適化するのですか?

A:ReadObjectは、ロード後にObjectを実際に逆シリアル化します。一つのPrefabが逆シリアル化されたら、多数のObjectが生産されます。IntegrateAllThreadedObjectsはこれらのObjectをトラバースし、Loading.CheckConsistencyはこれらのオブジェクトをトラバースするときにデータの整合性をチェックします。

いわゆる整合性チェックとは、たとえば、次の図のPrefabのシリアル化されたファイルの場合、2つの赤枠付けのfileIDが整合性があるかどうかをチェックすることを意味します。

ソース:https://www.cnblogs.com/luguoshuai/p/12323186.html

このブログで述べたように、2つのfileIDに一貫性がない場合、CheckConsistencyエラーが発生します。

整合性チェックがEditorでのみ実行され、パッケージ化後にRuntimeをチェックする必要がないのはなぜですか?筆者は、パッケージ化中にすべてのオブジェクトがチェックされたと推測しているため、Runtimeをチェックする必要はなく、チェックによって生じる高い時間コストも回避できます。

証拠を次の図に示します。パッケージ化されたエラースタックには、CheckConsistencyのステップが含まれています。


UWA公式サイト:https://jp.uwa4d.com

UWA公式ブログ:https://blog.jp.uwa4d.com

UWA公式Q&Aコミュニティ(中国語注意):https://answer.uwa4d.com

【HDRと色彩管理2】色空間

このセクションでは、主に特定の色空間の関連する定義と、色空間変換に関連する内容について説明します。

(1)3原色、白色点、伝達関数を含む完全な色空間(カラースペース)を定義します

(2)一般的な色空間標準とその定義

この記事の視覚的な内容の多くは、このスピーチHDR in Call of Dutyからのもので、PPTも非常に良く作られて理解しやすいです。 同時に、CG業界のアーティストによる電子ブックCG Cinematographyをお勧めします。この本はカラーマネジメントから照明リファレンスまでを網羅し、品質が優れて、現在も更新されていて、とてもお勧めです。


2.1色空間

前のセクションでは、色度図(CIE 1931 xy chromaticity diagram)について説明しました。この色度図で定義されたCIE 1931 xy color spaceには、基本的に、認識できる最大の色域が含まれています。これにより、他の色空間を定義するために使用する標準空間にもなります。 通常、RGB色空間を指定します。これは、現在のワークスペースで関心のあるすべての色範囲の範囲を定義します。

 Source: https://www.colour-science.org/posts/the-importance-of-terminology-and-srgb-uncertainty/

上に示したように、RGB色空間は基本的に3次元空間(左の画像)ですが、視覚化の便宜のために、通常、CIE 1931 xy色空間図(右下の画像)でその色度範囲を表します。上の黒い点はこのRGB色空間の右上の画像のすべてのピクセルの位置を表します。 では、このような完全なRGB色空間はどのように数学的に定義されているのでしょうか。 次の3つの部分によって構成されています。

(1)三原色(Primaries)
(2)白色点(White Point)
(3)伝達関数(Transfer Functions)

2.2.1 三原色(Primaries)

RGB色空間の3つの原色を定義するために、通常、CIE 1931 xy色度図でその3つの原色のxy座標を指定します。これらの3つの原色は、この色空間の色域(gamut)を定義します。 たとえば、おなじみのsRGB色空間の3原色のxy座標は次のとおりです。

Source: HDR in Call of Duty

The color primaries tells us what the primary colors Red (1,0,0), Green (0,1,0) and Blue(0,0,1) in our new color space map to in terms of real world chromaticities.

—— From HDR in Call of Duty

以下は、いくつかの一般的な色空間と、それらの3つの原色と白色点の位置です(白色点については後で詳しく説明します)(他の空間の3つの原色の詳細については、wikiを参照してください)。

色度図のこれらの色空間の三角形は、さまざまな色空間の範囲を視覚的に比較する方法を提供します。色空間が大きいほど、より明るい色にアクセスできます。これは、画像の色体験とは非常に異なる感覚です。以下は、色度図のさまざまな色空間の色域範囲を比較したものです。

Source: https://chrisbrejon.com/cg-cinematography/chapter-1-color-management/

2.2.2 白色点(White Point)

前に述べたように、CIE 1931 xy色度図は、次元削減後、すでに2次元空間になっています。この空間は、明度情報をのぞいて、色度情報のみを表しています。しかし、実際に使用する必要のある色空間は、依然として3次元空間であるため、完全な色情報を取得するには、白色点White Pointを定義する必要があります。

The whitepoint defines the white color for a given RGB color space. Any set of colors lying on the neutral axis passing through the whitepoint, no matter their luminance, will be neutral to that RGB colorspace.

—— From this article

たとえば、前述のsRGB色空間での白色点D65の位置は、次のとおりです(xy座標は(0.31271、0.32902))。

Source: HDR in Call of Duty

(1)白色点の定義

簡単に言えば、白色点は、このRGB色空間における純白(1、1、1)の色度図上の位置を定義します。次の視覚化は、この定義プロセスを示しています。

 

ビデオの内容を説明します:色度図の3つの原色のxy座標を使用して、XYZ座標空間でのベクトル方向を取得します。計算の便宜上、それらの単位ベクトル方向のみを考慮して、(Rx、Ry、Rz)、(Gx、Gy、Gz)および(Bx、By、Bz)として記録することができます。これらの3つの単位ベクトル方向をスケーリングして重ね合わせることにより、この色空間内の任意の点の空間位置を取得できます。つまり、P =(Rx、Ry、Rz)* r +(Gx、Gy、Gz)* g +(Bx、By 、Bz)* b、ここで、r、g、およびbは、それぞれ3つのベクトルのスケーリングを表します。

次に、P =白色点の位置となるような(r、g、b)係数のセットを見つけることができます。つまり、この白色点を通して、3つの原色ベクトルの相対的な長さの関係を定義できます(この前、色度図の白色点とRGB色空間の実際の(1、1、1)純白との対応する関係を常に理解できませんでした。 私の理解では、色度図の白色点の座標はRGB 3次元色空間での純白(1、1、1)が2次元のxy空間での投影です。3つの三原色のxy座標は、RGB 3次元色空間での純粋な赤(1、0、0)、純粋な緑(0、1、0)、および純粋な青(0、0、1)が2次元のxy空間での投影と同じようになります。

つまり、色度図位置は、実際のRGB色空間内の各ポイントの投影位置を定義します。)では、相対的な長さの関係を使用して、この(r、g、b)係数のセットを比例的にスケーリングすることにより、原点から白色点までの光線上のすべての点の位置にアクセスできます。特に懸念される点が1つあります。 —明度の値は、縦座標Y = 1の白色点です。この特別な3次元空間の白色点の位置は、3原色の絶対的な長さの値を定義します。このようにして、XYZ色空間の新しいRGB色空間の3つの原色インデックスベクトルベースRxyz、Gxyz、Bxyzを最終的に定義できます。これらのスケーリング範囲は、0〜1であり、3つのスケーリング値が(1、1、1)、1の明度で白色点Wxyzに到達できます。0から1の範囲を持つこれらの3つのベクトルベースは、真の3次元RGB色空間範囲を定義します。

まだ少し紛らわしいですが、プログラマーは– Talk is cheap, show me the code!

次にRec709/sRGB空間を例をとし、XYZ色空間の3つの主要色のインデックス値を推定します。推定された擬似コードは以下のように示す:

//新しいRGB色空間(sRGB)の三原色がXYZ色空間の3原色ベクトルベースの値を求めます:
Rxyz =(Rx、Ry、Rz)
Gxyz =(Gx、Gy、Gz)
Bxyz =( Bx、By、Bz)

//色度図の三原色と白色点の座標から、次のことがわかります。
Rxyz =(0.64、0.33、0.03)* r 
Gxyz =(0.30、0.60、0.10)* g 
Bxyz =( 0.15、0.06、0.79)* b

//XYZ色空間の白色点のインデックス値は
Wxyz=(Wx、1、Wz)
=(0.31271、0.32902、0.35827)* w 
= | Rx Gx Bx| |1|
| Ry Gy By| |1| 
| Rz Gz Bz| |1| 

//では:
w = 3.03933 
Wxyz =(0.95043、1、1.08890)

// 2つを組み合わせると次のようになります:
0.64r + 0.30g + 0.15 b = 0.95043 
0.33r + 0.60g + 0.06b = 1 
0.03r + 0.10g + 0.79b = 1.08890

//次のように解きます:
r = 0.644463125 
g = 1.191920333 
b = 1.202916667

//次に、sRGB色空間はXYZ色空間でのインデックス値は次のとおりです。
Rxyz=(0.4124564、0.2193339.0196729、0)
Gxyz =(0.3575761、0.7151522、0.1191920)
Bxyz =(0.1804375、0.0721750、0.9503041)

このようにして、色度図の3原色と白色点のxy座標によって、XYZ空間のsRGB色空間の3次元ボリューム空間を復元できます。

Source: HDR in Call of Duty

(2)色空間変換

明らかに、上記のRxyz、Gxyz、Bxyzの座標値を使用して、新しいRGB色空間とXYZ色空間の間で色変換を行うことができます。 以下は、列行列形式の変換行列です。

RGB_2_XYZ_Mat = |Rx Gx Bx|               

|Ry Gy By|                

|Rz Gz Bz|

XYZ_2_RGB_Mat = inverse (RGB_2_XYZ_Mat)v

さらに、XYZ色空間を中間として使用して、任意の2つの色空間間で変換できます。 通常、これらの色空間変換行列をオフラインで計算し、その結果値を直接保存して、リアルタイムの色空間変換を行います。 UE4ソースコードを例にとると、ACES.ushにそのような変換行列が多数見つかります。

// REC 709 primaries

static const float3x3 XYZ_2_sRGB_MAT =

{      

3.2409699419, -1.5373831776, -0.4986107603,     

-0.9692436363,  1.8759675015,  0.0415550574,      

0.0556300797, -0.2039769589,  1.0569715142,

}; 



static const float3x3 sRGB_2_XYZ_MAT =

{     

0.4124564, 0.3575761, 0.1804375,     

0.2126729, 0.7151522, 0.0721750,     

0.0193339, 0.1191920, 0.9503041,

};

これで、最初は不思議に思えたこれらの行列を誰もが推測できるようになると思います。 XYZ空間のY軸の特殊性(Y軸は明度に対応)により、変換行列RGB_2_XYZ_Matの中央の行(Ry、Gy、By)には、新しいRGB色空間の色の明度計算に必要な係数値が保存されているます。 sRGB空間を例にとると、sRGB色空間の色(r、g、b)の明度値を計算する必要がある場合は、次の式を使用できます。

luminance = 0.2126729 * r + 0.7151522 * g + 0.0721750 * b

なじみですよね? はい、これは私たちがよく目にするLuminance関数です。

float Luminance (float3 Color)

{    

return dot(Color, float3(0.2126, 0.7152, 0.0722));

}

(3) Color Temperature

コンテキストと使用環境に応じて、同じRGB色空間に異なる白色点を定義できることは注目に値します。次に例を示します。

1.標準の表示条件で照明環境をシミュレートする場合は、D50を選択できます。これにより、暖かい色温度の色空間を得ることができます。

2.正午の条件下で照明環境をシミュレートする場合は、D65を選択できます。これにより、色温度がより低い色空間を得ることができます。

3.より涼しい日光環境をシミュレートする場合は、より涼しい色温度で色空間を取得できるD75を選択できます。

 

D50、D65、D75という名前は、色温度(Color Temperature)に基づいて表現された色情報に由来しています。 色温度は、黒体放射(Black Body Radiation)の物理理論に基づいた概念です。 物理的には、黒体はすべての光を吸収する物質ですが、異なる温度の黒体はその温度で特定のスペクトルの光を放出する可能性があります。

 

高温(1000Kなど)の黒体は赤い光を発します:

Source: HDR in Call of Duty

温度が上がると、ライトは黄色に変わります。たとえば、温度は2000Kでは:

Source: HDR in Call of Duty

温度がもっと高くなると、水色に変わります。たとえば、温度は6500Kでは:

Source: HDR in Call of Duty

更な高温になると、は徐々に青に近づきます:

Source: HDR in Call of Duty

温度と色のこの関係は非常に固定されているため、温度値(Calvin K)を使用して特定の色を指定できます。

上記の特定の温度での色を色度図にプロットすると、プランキアン軌跡(Planckian Locus,黒体軌跡とも呼ばれます)と呼ばれる曲線が得られます。

Source: HDR in Call of Duty

このプランキアン軌跡上の点を使用して白色点を定義することがよくあります。前述のD65は、CIE Illuminant Dシリーズの標準照明であることを示し、数字65は、6500K温度のカラー値にを示します。D65は、西ヨーロッパの正午の平均照明値を大まかに表しています。

Source: HDR in Call of Duty

CIEは、すべてのよく知られた標準光源(Standard Illuminantの普及を担当しています。これらの標準にはいくつかのシリーズが含まれ、そのうちCIE Illuminant Dは自然光の環境での標準照明を表しています。 通常、これらの標準照明値は、CIE1960UCS色度図にさまざまな温度でプロットされます。

Source: https://www.colour-science.org/posts/the-importance-of-terminology-and-srgb-uncertainty/

 

2.2.3 伝達関数

これで、新しいRGB色空間の三色値(tristimulus values)がわかりましたが、さまざまな電子デバイスに表示する必要があります。 線形三色値から非線形ビデオ信号へのこの変換関係は、伝達関数(Transfer Functions)によって定義されます。なぜわざわざこの非線形変換を使用しなければならないのですか? 線形入力と線形出力を直接行うことはできませんか? これは主にストレージスペースと帯域幅を最適化することを目的としています。これはSubstance PBR manualにも記載されています。

>The Human Visual System (HVS) is more sensitive to relative differences in darker tones rather than brighter tones. Because of this, not using gamma correction is wasteful as too many bits will be allocated to tonal regions where the HVS cannot distinguish between tones.

つまり、伝達関数は、パフォーマンスを向上させるためにエンコーディングスペースをより有効に活用するのに役立ちます。伝達関数は、次の2つのタイプに分けることができます。

(1)OETF:相対的なシーンの線形光(relative scene linear light)を非線形ビデオ信号値(non-linear signal value)に変換する光電伝達関数。たとえば、カメラで撮影する場合、実際のシーンの光はOETFを介してカメラのビデオ信号に変換されます

(2)EOTF:非線形ビデオ信号値(non-linear signal value)を表示光(display light)に変換する電光伝達関数。たとえば、ビデオ信号を画面に表示すると、EOTFを通過します。

これらの伝達関数は、ガンマ補正で使用される関数です。ガンマ補正Gamma correction(略してガンマ)は、線形三色値と非線形ビデオ信号の間のエンコードとデコードの操作を指します。ガンマ補正の最も単純なバージョンでは、γ<1の値をエンコードガンマ(encoding gamma)として使用し、そしてそのガンマ関数をOETF(encoding function)として線形カラー値を非線形線形信号値に変換します。このプロセスはガンマ圧縮(gamma compression)と呼ばれます;代わりに、γ> 1の値をデコードガンマ値(decoding gamma)として使用し、そしてそのガンマ関数をEOTF(decoding function)として非線形信号値を線形カラー値に変換します。このプロセスはガンマ展開として知られています。

sRGBのデコードされたガンマ値は2.2であるとよく言われますが、実際には、sRGBガンマ拡張変換関数で使用される指数値は2.4です。

This is because the net effect of the piecewise decomposition is necessarily a changing instantaneous gamma at each point in the range: It goes from γ = 1 at zero to a gamma of 2.4 at maximum intensity with a median value being close to 2.2.

—— From wiki

ガンマ定義のフルバージョンでは、伝達関数は2つのセグメントで定義されます。0に近い線形セグメント(C = 0で有効な定義を与えるため)と、残りの指数関数的に変化するセグメントです。 ガンマ曲線の各パラメータの導出については、ここでは詳しく説明しません。詳細については、wikiを参照してください。 簡単に言うと、次の式を使用して順方向伝達関数を表すことができます(ここでは、ガンマ圧縮プロセスで使用される伝達関数を指し、ガンマ拡張プロセスで使用される関数は、次の関数の逆関数です):

δ * I,                             I ≤ β

γ(I) = {         

α * C^(1/γ) - (α - 1),    β < I

 

2.3一般的な色空間標準

 

歴史的に、多くの色空間標準は、映画業界やさまざまなスクリーンメーカーによって開発されてきました。私たちに最も関連するいくつかの色空間標準は次のとおりです。

  • sRGB:フルネームはstandard Red Green Blueです。これは、1996年にヒューレットパッカードとマイクロソフトによって開発されたRGB色空間であり、ネットワーキング、Windows、印刷などの分野で使用されています。
  • Rec.709:フルネームはITU-R Recommendation BT.709で、Rec。709、BT.709、ITU709などと略されることがよくあります。 HDTV(high-definition television)などの分野で使用されています。 3原色はsRGBと同じですが、伝達関数が異なります。
  • DCI-P3:デジタルシネマプロジェクションのためにアメリカの映画産業によって開発されたRGB色空間です。
  • Rec.2020:フルネームはITU-R Recommendation BT.2020で、Rec。2020、BT.2020などと略されることがよくあります。UHDTV(ultra high-definition television))などの分野を定義するために使用され、将来のトレンドでもあります

 

上記の4つの色空間標準のパラメーターを以下に示します(Transfer Function Parametersは順変換関数のパラメーターを参照します。完全な表はwikiを参照します。

色度図の各色空間の範囲は次のとおりです(以下には、ACESとACEScgの2つの色空間も含まれています。これらについては、後のACESの部分で詳しく説明します)。

Source: https://www.colour-science.org/posts/the-importance-of-terminology-and-srgb-uncertainty/

必要に応じて、同じRGB色空間に対して異なる白色点を定義することに注意してください。上の表のDCI-P3には、異なる白色点の色空間標準があります。 DCI-P3スペースは、2010年にDCI組織(Digital Cinema Initiatives)によって、主にデジタルシネマプロジェクションに使用される色空間標準として最初に定義されました。その白色点はD63ですが、より緑色(x = 0.314、y = 0.351)、伝達関数は、映画館の暗室環境に適合した純粋なガンマ2.6曲線です。 2015年、AppleのiMacは、P3wide gamutを内蔵した最初の家庭用コンピュータになりました。これは、Appleが作成したDisplayP3カラースペースと呼ばれるスペースです。Display P3は、DCI-P3と同じ3原色を使用しますが、コンピューターディスプレイに一般的に使用されるD65の白色点値を使用します。また、DCI-P3の純粋な2.6ガンマ曲線とは異なり、Display P3はsRGBと同じ変換関数を使用します。

 

私たちが最も頻繁に扱うsRGBはCIE1931色空間の約35.9%しか占めておらず、sRGBはゲーム開発の分野でも最も広く使用されている色空間であり、これはほとんどのゲームのディスプレイの色域は大幅に制限されていることを意味します。もちろん、主な理由は、LDRディスプレイが現在でも最も一般的なディスプレイデバイスであり、sRGBがLDRディスプレイの業界標準であるためです。つまり、LDRデバイスは上の画像のsRGB三角形の外側のすべての色を再現することはできません。対照的に、Rec。2020の色域は大幅に改善されており、CIE 1931色空間全体の約75.8%を占めており、将来のトレンドの色空間標準でもあります。

 

sRGBについて話すとき、しばしば非常に混乱していると感じることは注目に値します。それについての混乱する記述動作が多すぎて、専門的な記事も多くあります。色空間だと言う人もいれば、伝達関数(ガンマ補正)だと言う人もいます。一般的な不正確な説明は次のとおりです。

  • sRGB is a slight tweaking of the simple gamma 2.2 curve.

この言い方は実際には厳密ではありません。上記のステートメントは、実際にはsRGB色空間のEOTF伝達関数(つまりガン​​マ)を説明しています。 厳密に言えば、sRGBはRGB色空間であり、その伝達関数(sRGBOETFおよびsRGBEOTF)は、0.454/2.2のガンマ値に近いガンマ曲線を使用します。これらの伝達関数はsRGB色空間の一部にすぎません。  Substance PBR manualでは、次のように説明しています。

It is critically important to disambiguate the sRGB OETF from the sRGB colorspace; the OETF is only one of the three components that make an RGB colorspace.

Color Scienceの記事から、これらのあいまいさを弁別する手がかりが得られる可能性があります。

When one talks about sRGB, is he describing the colourspace primaries or its transfer functions? Discussing about sRGB to linear transformation without emphasis on the EOTF component is unsettling: a rendering engine using linear sRGB colourspace input colours and textures, renders with the sRGB colourspace primaries and whitepoint(assuming no colour transformations are occurring internally), thus its output is within sRGB colourspace.

もう1つの注意点は、私たちがよく話す線形(linear)は色空間の概念ではありません、色はさまざまな異なる色空間で線形になれるが、線形空間で作業することは、アクセスできる色域は無限である(linear != infinite)ことを意味するわけでなありません。しかし残念ながら、多くの資料やプロのソフトウェアでさえ、他の色空間名と一緒に記述子またはオプションとしてLinearを使用しますが、表現したい「色空間」は、上記で説明した実際の色空間の概念ではないことがよくあります。たとえば、ガンマ補正とレンダリングの線形ワークフローでよく言及する線形空間の概念は、実際にはlinear working/rendering spaceを指しますが、RGB色空間(通常はsRGB色空間)を選択する必要があります。照明の計算を実行する前に、色情報をgamma sRGB color spaceからlinear sRGB color spaceに変換する必要があります。このような線形空間で計算を行うことによってのみ、照明が正しいことを確認できます。

 

これまで、RGB色空間の基本的な定義といくつかの一般的な色空間標準について理解してきました。しかし、色空間については、まだ話していないことがたくさんあります。たとえば、次のようなものです。

sRGBとRec.709で使用される伝達関数が異なるのはなぜですか(viewing environment)

良く見られるscene-referredとdisplay-referred imageは何ですか(image state)

線形ワークフローとさまざまな中間グレー値

TonemappingとACES

 

参考文献

  1. https://medium.com/hipster-color-science/a-beginners-guide-to-colorimetry-401f1830b65a
  2. https://chrisbrejon.com/cg-cinematography/chapter-1-color-management/
  3. https://agraphicsguy.wordpress.com/2018/11/29/basic-color-science-for-graphics-engineers/
  4. Digital Dragons 2018: HDR in Call of Duty

UWA公式サイト:https://jp.uwa4d.com

UWA公式ブログ:https://blog.jp.uwa4d.com

UWA公式Q&Aコミュニティ(中国語注意):https://answer.uwa4d.com

冗長性を回避できるために、Unityの内蔵アセットはどのようにパッケージ化すればいいのか

今回の話題:

冗長性を回避できるために、Unityの内蔵アセットはどのようにパッケージ化すればいいのか

SpriteAtlasの「冗長性」問題

Meshの使用メモリについて

UGUI.Rendering.UpdateBatches時間コストが高い

PluginsのDLLはどのようにPackageに影響するか


AssetBundle

 

Q:今はAssetBundleをパッケージ化しようと思いますが、Unityの内蔵アセットはAssetBundle名を指定できますか? AssetBundleにある内蔵アセットの冗長性は一般的にどのように解決しますか?

 

既存のデータを確認した後、内蔵アセットのパッケージ化により、AssetBundleの冗長処理では、内蔵アセットをローカルに抽出またはダウンロードし、アセットの参照関係を変更してから、パッケージがAssetBundle名を指定できるようになりました。Unityは、スクリプトがAssetBundleをパッケージ化する際に内蔵アセットのBundle名を指定することをサポートしますか。これにより、複数のアセットが同じ内蔵アセットに依存することを防ぎ、冗長性をもたらしますか?

 

A:Scriptable Build Pipelineを使用して実現できます。具体的な方法については、Addressableで内蔵のShaderをパッケージ化する方法を参照してください。

public static IList<IBuildTask> AssetBundleBuiltInResourcesExtraction()
    {
        var buildTasks = new List<IBuildTask>();

        // Setup
        buildTasks.Add(new SwitchToBuildPlatform());
        buildTasks.Add(new RebuildSpriteAtlasCache());

        // Player Scripts
        buildTasks.Add(new BuildPlayerScripts());
        buildTasks.Add(new PostScriptsCallback());

        // Dependency
        buildTasks.Add(new CalculateSceneDependencyData());
#if UNITY_2019_3_OR_NEWER
        buildTasks.Add(new CalculateCustomDependencyData());
#endif
        buildTasks.Add(new CalculateAssetDependencyData());
        buildTasks.Add(new StripUnusedSpriteSources());
        buildTasks.Add(new CreateBuiltInResourcesBundle("UnityBuiltInResources"));   //将CreateBuiltInShadersBundle改成自己创建的类
        buildTasks.Add(new PostDependencyCallback());

        // Packing
        buildTasks.Add(new GenerateBundlePacking());
        buildTasks.Add(new UpdateBundleObjectLayout());
        buildTasks.Add(new GenerateBundleCommands());
        buildTasks.Add(new GenerateSubAssetPathMaps());
        buildTasks.Add(new GenerateBundleMaps());
        buildTasks.Add(new PostPackingCallback());

        // Writing
        buildTasks.Add(new WriteSerializedFiles());
        buildTasks.Add(new ArchiveAndCompressBundles());
        buildTasks.Add(new AppendBundleHash());
        buildTasks.Add(new PostWritingCallback());

        // Generate manifest files
        // TODO: IMPL manifest generation

        return buildTasks;
    }

 

[MenuItem("AssetBundles/GenerateAB")]
    public static void GenerateAB()
    {
        var outputPath = "Assets/AssetBundles";
        if (!Directory.Exists(outputPath))
            Directory.CreateDirectory(outputPath);

        BuildTarget targetPlatform = BuildTarget.StandaloneWindows;
        var group = BuildPipeline.GetBuildTargetGroup(targetPlatform);

        var parameters = new BundleBuildParameters(targetPlatform, group, outputPath);

        var buildInput = ContentBuildInterface.GenerateAssetBundleBuilds();
        IBundleBuildContent content = new BundleBuildContent(buildInput);

        var taskList = AssetBundleBuiltInResourcesExtraction();   //创建自己的task
        ReturnCode exitCode = ContentPipeline.BuildAssetBundles(parameters, content, out result, taskList);

        if (exitCode < ReturnCode.Success)
            return;

        var manifest = ScriptableObject.CreateInstance<CompatibilityAssetBundleManifest>();
        manifest.SetResults(result.BundleInfos);
        File.WriteAllText(parameters.GetOutputFilePathForIdentifier(Path.GetFileName(outputPath) + ".manifest"), manifest.ToString());
    }

下記のコードはCreateBuiltInResourcesBundle.csからのもので,从CreateBuiltInShadersBundle.csから一つのクラスをコピーして、少しのコードを変更します:

public ReturnCode Run()
        {
            HashSet<ObjectIdentifier> buildInObjects = new HashSet<ObjectIdentifier>();
            foreach (AssetLoadInfo dependencyInfo in m_DependencyData.AssetInfo.Values)
                buildInObjects.UnionWith(dependencyInfo.referencedObjects.Where(x => x.guid == k_BuiltInGuid));

            foreach (SceneDependencyInfo dependencyInfo in m_DependencyData.SceneInfo.Values)
                buildInObjects.UnionWith(dependencyInfo.referencedObjects.Where(x => x.guid == k_BuiltInGuid));

            ObjectIdentifier[] usedSet = buildInObjects.ToArray();
            Type[] usedTypes = ContentBuildInterface.GetTypeForObjects(usedSet);

            if (m_Layout == null)
                m_Layout = new BundleExplictObjectLayout();

            //Type shader = typeof(Shader);
            //for (int i = 0; i < usedTypes.Length; i++)
            //{
            //    if (usedTypes[i] != shader)
            //        continue;

            //    m_Layout.ExplicitObjectLocation.Add(usedSet[i], ShaderBundleName);
            //}

            //上面是打包内置Shader的操作,改成全部资源就可以了
            foreach (ObjectIdentifier identifier in usedSet)
            {
                m_Layout.ExplicitObjectLocation.Add(identifier, ShaderBundleName);
            }

            if (m_Layout.ExplicitObjectLocation.Count == 0)
                m_Layout = null;

            return ReturnCode.Success;
        }

テスト結果は次のとおりです。

UnityのデフォルトのEffectをprefabにしてAssetBundleにパッケージ化します(Package名はpsです)。特殊効果に使用される内蔵アセットがすべてこのAssetBundleに含まれていることがわかります。

SBPでパッケージ化した後は、次のようになります。

psのAssetBundleにアセットがないことがわかります。生成された内蔵AssetBundleにはpsによって使用される3つの内蔵アセットがあり、psはUnityBuiltInResourcesのAssetBundleに依存します。

 

 

 

 


AssetBundle

Q:SpriteAtlasについて、UIがレンダリング時に関連するSprite情報に従って対応するSpriteAtlaを見つけるということだと思いました。各UIレンダリングが同じAtlasを使用するようになり、Draw Callを減らすことができます。したがって、理論的には、Atlasの一枚で十分です。しかし、なぜAtlasのパッケージ化したAssetBundleには、Atlasに加えて、参照されている元の画像もあるのか。UIのAssetBundleパッケージにも、参照されている元の画像があります。

 

なぜそのような「冗長性」があるのか​​、そしてImageがアトラスを参照するのか画像を参照するのか?またはその原理は何ですか?

 

元のイメージがAtlasパッケージに配置されている場合、元のイメージはAtlasPackageに含まれていますが、UIPackageには含まれていません。元のイメージがAssetBundlePackageの外部に配置されている場合、AtlasPackageとUIPackageの両方に元のイメージがあります。それは何の原理でしょうか?

 

A1:最初にこの記事を読むことをお勧めします:

【Unity游戏开发】SpriteAtlas与AssetBundle最佳食用方案

SpriteAtlasを適切に使用する場合、AssetBundleを解凍すると、Textureと複数のSpriteの2つのアセットが含まれていることがわかります。Texture

はテクスチャであり、表示されるファイルサイズは大きいです。Spriteはテクスチャ全体でのスプライトのオフセット位置情報を記述したデータファイルとして理解でき、表示されるファイルサイズは小さいです。

したがって、これは冗長ではなく、正常です。

 

A2:ただし、確かに冗長性の問題があります。Prefab1とPrefab2が同じAtlasの Spriteを参照している場合、Atlasは少なくとも1つのAssetBundleにアクティブに含まれている必要があります。そうでない場合、2つのPackageに受動的に入力され、冗長性が発生します。

AtlasはAssetBundlePackageを設定しません。

Atlasは、AssetBundlePackageの1つにパッケージ化します。

 


 

Mesh

Q:Meshのメモリ使用量に関して、Unity 2020のMeshにはどのような情報が表示されますか?

ボーンをインポートする

ここでボーンをインポートしないと、頂点情報が占めるスペースが2倍に減りますが、ボーンをインポートした後の頂点情報には何を増加しますか?

 

ボーンをインポートしない

2番目の問題は次のとおりです。ボーンをインポートする場合、メモリ内のMeshは0.6MBを占有します。これは、上記のInspectorに表示されるもののほぼ2倍であり、他のモデルのテストも2倍です。

 

Read/Write Enabledを有効にすることが問題だと考えていましたが、このオプションがどうであれ、メモリ使用量は変わらないことがわかりました。このメモリ使用量はどのように発生しますか。また、Read/Write Enabledを有効にすると、2倍のメモリコストが発生しますか?

 

テストの結果、ボーンをインポートせずに、Read/Write Enabledを有効にする場合は、有効にしない場合の2倍のメモリが必要となります。Read/Write Enabledを有効にしないと、Inspectorと同じメモリを占有することがわかりました。

ボーンをインポート時にRead/Write Enabledが有効になっているかどうかは、Inspectorインターフェイスの表示メモリの2倍です。ボーンがインポートされた後、モデルの頂点がデフォルトで変更されると推測されます。これは、デフォルトでRead/Write Enabledを有効にするのと同じです。

 

A:最初の質問:

InspectorパネルのVertices列は、Meshの頂点属性(またはチャネル)を指します。Meshにチャネルのデータが含まれている場合、各頂点に頂点属性があることを意味します。

Unityによって定義された頂点チャネルは14があります。

ボーンがインポートされる場合、追加の頂点属性は頂点のボーンウェイトとボーンインデックスです。

Mesh.boneWeights()およびMesh.GetBonesPerVertex()を介してアクセスできます。

ただし、BoneWeightプロパティは、4つのfloat32と4つのint32、合計8×4=32Bytesを格納します。一つのBones indexは一つのByteに相当します。

(8×4+1)Byte/Vert x 5512Vert = 177.63KB

2番目の質問:ボーンアニメーションをインポートして、CPU側でスキニング計算を実行します。つまり、CPUで頂点属性を取得します。


 

UGUI

 

Q:テストレポートでは、UGUI.Rendering.UpdateBatchesの使用量が多いと書かれています。それは何の原因でしょうか。

 

A1:シーンにあるTransformが変更されたUI要素が多すぎます。シーン内で変更されたCanvasが3つあり、これらの3つのCanvasの下Transformが変更された要素が312あるようです。

 

A2:CanvasのUI要素がCanvasRenderer.SyncTransformを何度も(数百回程度)トリガーすると、親ノードUGUI.Rendering.UpdateBatchesの時間も比較的高くなります。

テスト後、Unity 2018、2019、および2020のバージョンで、SetActive(true)を呼び出してUI要素をDeactive状態からActive状態に変更すると、UI要素が配置されているCanvas内のすべてのUI要素がCanvasRenderer.SyncTransformをトリガーします。 Unity 2017のバージョンでは、このような操作はこのSetActive(true)自体の要素にのみ影響します。UnityのBugなのか、このように設計されているのかはわかりません。ただし、Unity 2018、2019、および2020バージョンでは、Scaleを0または1に設定する方法を使用して、UIを非表示にできるため、Scanleが変更したUI要素のみがCanvasRenderer.SyncTransformをトリガーします。


 

Script

Q:下図に示すように、プロジェクトを開けるとすぐにTimeline異常が報告されます。後で、Pluginsの下のDLLに関連していることがわかります。DLLTimelineを削除すると、正常になります。では、DLLがTimeline

に影響を与えるのはなぜですか。Timelineのこれらのオーバーロードされた関数はUnityEditor.CoreModuleにあるはずだが、どうやって見つけられないでしょうか?

 

A:Unityスクリプトには厳密なコンパイル順序があります:

precompiled DLL -> asmdefs -> StandardAsset -> Plugins -> Plugins/Editor -> Assets -> Editor。

プリコンパイルされたDLLには、同じ名前が記述されたPlayableBehaviourクラスが含まれている可能性が高く、同じメソッドが実装されています。

このDLLは、Unityによって[Package]の[Timeline]の前にロードおよびコンパイルされます。Timelineをコンパイルすると、2つのPlayableBehaviourが検出されるため、書き換えに適した方法が見つかりません。

上記の考えに従って、エラーをローカルで再現しました。

このDLL(ConsoleApp1.dll)をPluginsディレクトリにスローすると、同じエラーが表示されます(DLLは元の質問と回答から取得できます)。


UWA公式サイト:https://jp.uwa4d.com

UWA公式ブログ:https://blog.jp.uwa4d.com

UWA公式Q&Aコミュニティ(中国語注意):https://answer.uwa4d.com

URPでのBRDF計算式の問題

1)URPでのBRDF計算式の問題

2)Job Systemがメインスレッドの時間を占めるという問題

3)ProfilerでTempBufferの問題を特定する

4)Unity2019でHDRPのカメラのGL線画の問題

5)UnityWebCamTextureによって取得されたカメラ画像が回転される


 

Shader

 

Q:最近URP Shaderを見ているときに問題が見つかりました。それが間違っているかどうかわかりませんが、最初にコードを貼り付けます。

 

1つ目は、URPのLighting.hlslでBRDFを初期化する部分です。

inline void InitializeBRDFData(half3 albedo, half metallic, half3 specular, half smoothness, half alpha, out BRDFData outBRDFData)
{
#ifdef _SPECULAR_SETUP
    half reflectivity = ReflectivitySpecular(specular);
    half oneMinusReflectivity = 1.0 - reflectivity;

    outBRDFData.diffuse = albedo * (half3(1.0h, 1.0h, 1.0h) - specular);
    outBRDFData.specular = specular;
#else

    half oneMinusReflectivity = OneMinusReflectivityMetallic(metallic);
    half reflectivity = 1.0 - oneMinusReflectivity;

    outBRDFData.diffuse = albedo * oneMinusReflectivity;
    outBRDFData.specular = lerp(kDieletricSpec.rgb, albedo, metallic);
#endif

    outBRDFData.grazingTerm = saturate(smoothness + reflectivity);
    outBRDFData.perceptualRoughness = PerceptualSmoothnessToPerceptualRoughness(smoothness);
    outBRDFData.roughness = max(PerceptualRoughnessToRoughness(outBRDFData.perceptualRoughness), HALF_MIN);
    outBRDFData.roughness2 = outBRDFData.roughness * outBRDFData.roughness;

    outBRDFData.normalizationTerm = outBRDFData.roughness * 4.0h + 2.0h;
    outBRDFData.roughness2MinusOne = outBRDFData.roughness2 - 1.0h;

#ifdef _ALPHAPREMULTIPLY_ON
    outBRDFData.diffuse *= alpha;
    alpha = alpha * oneMinusReflectivity + reflectivity;
#endif
}

私の理解では:

 

outBRDFData.perceptualRoughnessは、粗さで、ラフネスと呼ばれるものです。

outBRDFData.roughnessは、粗さの2乗です。

outBRDFData.roughness2は、粗さの4乗です。

 

URPのLighting.hlslでBRDFを計算する部分を見てください。

// Based on Minimalist CookTorrance BRDF
// Implementation is slightly different from original derivation: http://www.thetenthplanet.de/archives/255
//
// * NDF [Modified] GGX
// * Modified Kelemen and Szirmay-Kalos for Visibility term
// * Fresnel approximated with 1/LdotH
half3 DirectBDRF(BRDFData brdfData, half3 normalWS, half3 lightDirectionWS, half3 viewDirectionWS)
{
#ifndef _SPECULARHIGHLIGHTS_OFF
    float3 halfDir = SafeNormalize(float3(lightDirectionWS) + float3(viewDirectionWS));

    float NoH = saturate(dot(normalWS, halfDir));
    half LoH = saturate(dot(lightDirectionWS, halfDir));

    // GGX Distribution multiplied by combined approximation of Visibility and Fresnel
    // BRDFspec = (D * V * F) / 4.0
    // D = roughness^2 / ( NoH^2 * (roughness^2 - 1) + 1 )^2
    // V * F = 1.0 / ( LoH^2 * (roughness + 0.5) )
    // See "Optimizing PBR for Mobile" from Siggraph 2015 moving mobile graphics course
    // https://community.arm.com/events/1155

    // Final BRDFspec = roughness^2 / ( NoH^2 * (roughness^2 - 1) + 1 )^2 * (LoH^2 * (roughness + 0.5) * 4.0)
    // We further optimize a few light invariant terms
    // brdfData.normalizationTerm = (roughness + 0.5) * 4.0 rewritten as roughness * 4.0 + 2.0 to a fit a MAD.
    float d = NoH * NoH * brdfData.roughness2MinusOne + 1.00001f;

    half LoH2 = LoH * LoH;
    half specularTerm = brdfData.roughness2 / ((d * d) * max(0.1h, LoH2) * brdfData.normalizationTerm);

    // On platforms where half actually means something, the denominator has a risk of overflow
    // clamp below was added specifically to "fix" that, but dx compiler (we convert bytecode to metal/gles)
    // sees that specularTerm have only non-negative terms, so it skips max(0,..) in clamp (leaving only min(100,...))
#if defined (SHADER_API_MOBILE) || defined (SHADER_API_SWITCH)
    specularTerm = specularTerm - HALF_MIN;
    specularTerm = clamp(specularTerm, 0.0, 100.0); // Prevent FP16 overflow on mobiles
#endif

    half3 color = specularTerm * brdfData.specular + brdfData.diffuse;
    return color;
#else
    return brdfData.diffuse;
#endif
}

ここでの最終的な式は次のとおりです。

BRDFspec=roughness^2/( NoH^2*(roughness^2-1)+1)^2*(LoH^2*(roughness+0.5)*4.0)

 

次に、コードに記述されているアドレスであるUnityの2015年の論文を見てください。

https://community.arm.com/events/1155

コードにあるroughnessは、実際には画像のroughnessの2乗です。混乱を防ぐために、以下はroughness©和roughness(n)で表します。

roughness©=roughness(n)^2

 

これを見て、私は疑問を持っています。論文のroughness(n)+0.5

ステップはコードに対応したら、roughness©^0.5+0.5

はずだが、URPコードでroughness©+0.5を直接使用します。これは私の理解が間違っているか、それともURPのShaderが間違っているか。

 

A:未熟な見方ですが、私の結論は次のとおりです。

2乗roughness(n)^2プラス5は妥当です

1乗と2乗のどちらを使用してもほとんど違いはありません

SIGGRAPHレポートの元のV*F関数は次のとおりです。

使用される実際のV*F関数は、上記の関数の近似値であり、画像に近い関数を使用して最適化します。

次のように作者は1乗と2乗をとる関数を画像化します。

2つの画像はそれほど違いがなく、傾向から見れば、2乗を取るのは元のVFに近いように見えます(Modified KSK and Schlick Fresnel depend on LH)。

作成者は、Lighting.hlslのコードを変更して、最初の1乗を使用します。

outBRDFData.normalizationTerm=outBRDFData.perceptualRoughness*4

同じ画面でroughness(n)+0.5とroughness(n)^2+0.5

を使用してマテリアルを描画すると、ほとんど違いはありません。

グラフィックスの最初の法則によると、見た目が正しければ正しいので、両方が正しいことを理解するのは問題ありません。そうすれば、差が大きくなければ、掘り下げる必要がないということでしょうか。

 

Script

 

Q:下図に示すように、Job Systemで実行したのにメインスレッドの時間を占めるのはなぜですか?

A:子スレッドの実行が終了するのを待ちます。

 

Rendering

 

Q:写真に示されているように、シーンにある2つのTempBufferはC#スクリプトから作成したわけではありません。シーンはAfterEffectsを使用せず、Grab PassのShaderも使用せずに、シーンカメラはMSAAとHDRをオフにしており、これら2つのTempBufferがまだあります。それを完全に取り除く方法は?

これは、次の2つのことと関わります。

A1:次のように設定してみてください:Camera.forceIntoRenderTexture = false;

このオプションは、カメラを強制的にTempBufferにレンダリングします。

AfterEffectsを使用しない場合は手動でfalseに設定し、AfterEffectsを有効にすると自動的にtrueに設定します。したがって、After Effectsを使用する場合、TempBufferは避けられません。

 

A2:すべてのMonoBehaviorのOnRenderImage(RenderTexture source、RenderTexture destination)関数をブロックします。一般的に、各OnRenderImage(RenderTexture source, RenderTexture destination)

関数は一つのTempBufferを生成します。

 

A3:Grab RenderTextureは通常、Depthが最小のカメラのClear FlagsがDepth Onlyに設定されている場合に表示されます。

 

Rendering

 

Q:Unity 2019.3.0f6で、GL線画を使うと、Gameビューにカメラが見つかりません。プロジェクトはHDRPプロジェクトに属しています。

 

A1:GL描画をGLDraws()に配置してください。Unity2020.2.2f1c1で、HDRP10.2.2環境で効果を正常に描画しました。

protected void OnEnable()

{

if (GraphicsSettings.renderPipelineAsset != null)

RenderPipelineManager.endFrameRendering += OnCameraRender;

}

 

protected void OnDisable()
{
    if (GraphicsSettings.renderPipelineAsset != null)
        RenderPipelineManager.endFrameRendering -= OnCameraRender;
}

protected void OnCameraRender(ScriptableRenderContext context, Camera[] cameraList)
{
    foreach(var camera in cameraList)
    {
        if (CheckFilter(camera))
            GLDraws();
    }
}

Script

Q:Unity WebCamTextureから取得したカメラ画像が回転されました。WeChatをスワイプしたところ、画像は正しいです。スマホを回転させると、画像は常に正しくて、回転の痕跡はありません。スマホが縦向きの場合は正常ですが、横向きに回転させると画像が正しくなくなります。

 

A:画面を回転させたときに、表示に使用するRawImageの回転を次のように調整できます。


UWA公式サイト:https://jp.uwa4d.com

UWA公式ブログ:https://blog.jp.uwa4d.com

UWA公式Q&Aコミュニティ(中国語注意):https://answer.uwa4d.com

【HDRと色彩管理1】光、色、色度図

前回のプロジェクトでHDR表示を作成した時、カラーマネジメントの内容をたくさん理解する必要があると気づきました。見れば見るほど複雑になるので、勉強しながらこの記事をまとめました。

この記事は5つのセクションに分かれています。このセクションでは、光と色、CIE 1931 RGB/XYZ色空間と色度図に焦点を当てて説明しようと思います。私はそれをできるだけ簡単に説明しようとしています。私はできるだけ自分なりに分かりやすく説明しようと思います。これらの概念が何なのか、この章を読んでいただければ、はっきりと答えられると思います。

たくさんの定義と名詞の警告!恐れないで。始めましょう!


1.1 我々はどうやって光や色を見るのか

色につき、考慮すべき3つの側面があります。

  • オブジェクト

人間の目は非常に複雑な構造を持っており、機械を使って100%復元することは基本的に不可能です。人間の目にはいくつかの重要な構造があります。

  • 瞳孔(Pupil):虹彩(Iris)の真ん中にある円形の穴を指します。目の絞りに相当します。虹彩の働きにより自律的に大きさが変化して光量を調整しています。
  • 水晶体(Lens):光線が虹彩を貫いた後、水晶体を通過します。目のレンズに相当します。その幅を拡大または縮小することで、光の焦点範囲を制御できます。
  • 硝子体(Vitreous):水晶体によって屈折および集束された光は、硝子体を通過します。硝子体は、人間の目の大部分を満たし、網膜を支える厚い半透明のゲル状物質です。
  • 網膜(Retina):人間の目のフィルムに相当します。人間の目に渡された画像を受け取り、それらを電気インパルスに変換し、視神経によって脳に送信する役割を果たします。
  • 光受容体(Photoreceptors):網膜は光受容細胞で構成されており、桿体細胞(Rods)と錐体細胞(Cones)の2種類に分けることができます。
  • 桿体:光に敏感であるため、夜間および周辺視野にとって重要ですが、光受容色素の不足で色覚を発達させにくいです(色を区別できない)
  • 錐体:主に色の認識に関与し、明るい光でより良く役割を果たします。錐体光受容細胞には主に3つのタイプがあり、赤(約600 nmの波長)、緑(約550 nmの波長)、および青(約450 nmの波長)の光に最も敏感です。この視覚系は三色視覚と呼ばれます。これらの3種類の錐体はそれぞれ、長波(L)、中波(M)、および短波(S)に敏感であるため、L(ong)、M(edium)、およびS(hort)錐体と呼ばれます。

https://chrisbrejon.com/cg-cinematography/chapter-1-color-management/から

結局、脳はすべてのデータ信号を処理する責任を担います。たとえば、網膜にうつる像は上下左右が逆で、脳はそれを逆転します。したがって、実際、私たちが「見る」のは、実際に人間の目に当たる光ではなく、人間の目によって提供される信号に基づいて脳が再構築する効果です。

What we really see is our mind’s reconstruction of objects based on input provided by the eyes — not the actual light received by our eyes.

—— From this article

人間の目の構造(3種類の錐体細胞)は、私たちが知覚できる色域の範囲を決定します。他の生き物と比較して、人間の目の色覚能力は非常に無味です。たとえば、シャコには16の異なる色覚細胞があります。しかし、以下で説明するように、幸いなことに3つしかありません。そうでなければ、カラーマネジメントシステムはますます複雑になっていたでしょう。


1.2光と色とは

世界では、最初に光があり、次に色がありました。

「光」とは?

光は通常、人間の目で見ることができる電磁波(可視光)を指し、視覚は可視光への知覚です。可視光は、電磁スペクトルの特定の部分にすぎず、一般に400〜700ナノメートル(nm)の波長の電磁波、つまり、紫外線より長く、赤外線より短い波長の電磁波として定義されます。資料により、可視光の波長範囲を定義する方法は異なっています。狭いものでは420〜680 nm、広いものでは380〜800nmの範囲です。 …光は高周波電磁波であると同時に、光子と呼ばれる素粒子で構成される粒子の流れでもあります。したがって、光は粒子と波動の両方の特性を同時に持つか、光は「波動粒子の二重性」を持ちます。

-ウィキから

 

一般に、光は電磁波の形で伝わるエネルギーの一種です。多色光を分散系(プリズムなど)で分割した後、光の波長(または周波数)に応じて順番に並べてパターンを形成することができます。このパターンをスペクトル(Spectrum)と呼びます。人間の目に見えるのは可視スペクトルの一部のみです。これらの可視スペクトルは波長が約400nmから750nmで、可視光と呼ばれます。

「色」とは

色は、目、脳、および私たちの生活体験により、視覚的に感知された光の色の特徴であり、赤、オレンジ、黄色、緑、青、紫などの名前で光の色のカテゴリを表します。色への知覚は、可視スペクトルの電磁放射による人間の目の錐体細胞の刺激に由来します。色の種類と色の物理的仕様は、反射光の波長によってオブジェクトに関連付けられます。この反射は、光の吸収、発光スペクトルなど、オブジェクトの物理的特性によって決まります。しかし、色への知覚は、光の物理的性質だけでなく、心理学などの多くの要因も含みます。たとえば、色への知覚は、周囲の色の影響を受けることがよくあります。

普段いわゆる「色」とは、実際には、可視スペクトルの電磁放射による人間の目の錐体細胞の刺激です。しかし、脳の色の知覚は、光の物理的性質だけで決まるわけではありません。たとえば、色への知覚は、周囲の色の影響を受けることがよくあります。有名な青いドレスや白いドレスの事件を参照してください。

スペクトルの定義:

スペクトルとは、複雑な波長の光が分散システム(グレーティング、プリズムなど)で分割された後、光の波長(または周波数)に応じて順番に形成されるパターンです。スペクトルの一部可視スペクトルは、人間の目に見える電磁スペクトルの唯一の部分であり、この波長範囲の電磁放射は可視光と呼ばれます。スペクトルには、人間の脳が視覚的に区別できるすべての色が含まれているわけではありません。それは茶色やピンクなどの色は単一の色ではなくさまざまな色で構成されているからです。

-ウィキから

生活では、スペクトルにある単色光があまりに見られません。さまざまな強度と波長の光が混合して豊富な色世界を形成しています。光を表現する方法の一つとして、横軸に波長、縦軸にスペクトル放射発散度(明るさ、強度、フラックス)をとるスペクトルパワー分布(PSD)を使用することができます。

Source: https://agraphicsguy.wordpress.com/2018/11/29/basic-color-science-for-graphics-engineers/

 

簡単にまとめると、「光」は、スペクトルを使用して説明できる物理的な概念です。そして、「色」は、可視スペクトルの電磁放射による錐体細胞の刺激に基づいて人間の脳によって得られる視覚的な感知であり、感性的な色濃いが帯びられています。光と色は、理性と感性の絡み合いのように、離れることができません。


1.3色の量子化:カラーマッチング関数

スペクトルエネルギー分布マップは、実際に光を定量化する方法を提供します。可視光があれば、スペクトル上のすべての単一波長の光を横軸に、各単一波長のエネルギーを縦軸にし、2Dグラフを取得できます。レンダリングなどの多くの分野で、私たちが本当に気にかけているのは、各光の物理的特性ではなく、人間の目にどのような色が見えるかです。スペクトルエネルギー分布マップは、これらのフィールドについて記録する必要があるデータが多すぎます。結局のところ、可視単色光の波長範囲は400nmから750nmまでです。スペクトルエネルギー分布マップが光を定量化する一般的な方法であるというと、色を定量化するためのより簡潔な方法が必要です。

 

光の受信から色の表示まで人間の目はどのように働くかからヒントを得ました。脳の働きを考えると、脳に見えた色は、目の3種類の錐体細胞によって伝達された電気信号です。つまり、光のスペクトルエネルギー分布がどれほど複雑であっても、最終的に人間の脳に到達する信号源は常に3つだけです。さらに、スペクトル分布が完全に異なる2つの多色光があっても、錐体細胞を同じように刺激する限り、私たちの目からみれば、同じ「色」であるかもしれません。つまり、色と光の関係は1対多であり、メタメリズム(metamerism)としても知られている現象です。

 

このようにして、カラーマッチング実験が始まりました。3つの単一波長光を選択し、それらを三元光primariesと呼んでいます。可視スペクトルの単一波長光ごとに、各primaryの強度に対応する3つのパラメーターを見つけて、人間の目が同じように色を認識できるようにします。この方法で可視スペクトルのすべての単一波長光を測定すると、次のテーブルのように、関数r(λ)、g(λ)、b(λ)のセットを取得できます。

https://medium.com/hipster-color-science/a-beginners-guide-to-colorimetry-401f1830b65aから

この一連の関数は、カラーマッチング関数です。歴史的にも、このような等色マッチング実験が多く行われました。最も有名で広く使用されている(1つ)のは、1931年のCIE1931RGBカラーマッチング関数です。 CIE(International Commission on Illumination国際照明委員会、略語がCOIではなくCIEである理由は、フランス語に由来するからである)は、1913年に設立された組織であり、光と色に関連する国際規格の開発に取り組んでいます。 CIE 1931 RGBで使用される三元光の波長は、700 nm(R)、546.1 nm(G)、および435.8 nm(B)です。

 

上記のカラーマッチング関数は負の値であることに注意してください。たとえば、上の図の610nmの波長の場合、その3つの関数値は次のようになります。

λ=610nm

r(λ)= 0.34756

g(λ)= 0.04776

b(λ)= -0.00038

 

つまり、3つの正の値の三元光を使用することで、可視スペクトルのすべての単一波長光を表すことはできません。負の値を導入する必要があります。では、実験で「負の数の光」を取得するにはどうすればよいでしょうか。 520nmの波長での実験の概略図を以下に示します。

https://medium.com/hipster-color-science/a-beginners-guide-to-colorimetry-401f1830b65aから

 

520nmのような明るい緑色を再現するには、「負の赤色光」を使用する必要があることがわかります。これは、Reference Lightの側面とPrimary Red Lightの反対側に特定の強度値を持つ赤色光を使用することで相殺できます。これは赤色光の値が負です。

 

次のアニメーションは、可視スペクトルの等色マッチング実験の完全なプロセスを示しています。

 

https://medium.com/hipster-color-science/a-beginners-guide-to-colorimetry-401f1830b65aから

 

カラーマッチング関数は、単一波長の可視光源の測定を表しますが、光の重ね合わせにより、任意のスペクトルの光源に対してこのようなマッチング関数を実行できます。RGBを3次元空間の3つの座標軸とし、CIE 1931カラーマッチング関数の3つの関数を3次元空間に順番に描画すると、3次元空間にカラーラインを取得できます。この曲線はスペクトル軌跡(spectral locus)と呼ばれます。

https://agraphicsguy.wordpress.com/2018/11/29/basic-color-science-for-graphics-engineers/から

 

この曲線を原点に向かって、または原点から離れてスケーリングすることにより、この空間内のさまざまな強度の単色光の表現を表すことができます。また、この曲線上の各点に原点を接続し、放射線が得られました。各光線を無限大の方向に延長して一つの曲面に形成しました。この曲面はさまざまな波長のさまざまな明るさの単色光を表します。この曲面で囲まれたボリューム空間は、さまざまな波長とさまざまな明るさの光源を混合することで観察できるすべての色を表します。下記のビデオは、このプロセスを非常に鮮明に示しています(出典:Call of DutyのHDR、このPPTはすごい):

 

上記の3次元空間は、CIE 1931RGB色空間(次のCIE 1931 XYZ色空間と混同しないように注意してください)であり、CIE1931RGB色マッチング関数の各データセットによって定義されます。任意の可視光について、その色空間の三刺激値(tristimulus values)を使用してそれを表すことができます(前述の条件付き等色現象を思い出してください。これは、同じ三刺激値を使用してスペクトル的に異なるさまざまな光源を表すこともできることを意味します) :

人間の目に対応すると、スペクトルに対する3つの錐体の感度は、LMS色空間(Lは長い、Mは中間、Sは短い)を形成していると簡単に考えることができます。これは、色空間を簡単に定量化するために使用できます。


1.4最適化の維持:負の値を排除する

前述のように、CIE RGB色空間には負の値があり、これらの負の値はすべてRコンポーネントに表示されます。これらの負の値を排除するために、CIEは、RGB色空間から別の色空間XYZ色空間を拡張するという良いアイデアを思いつきました。3×3空間変換マトリックスを使用して、2つの色空間間で変換できます。 XYZ色空間の3つの基本ベクトルは、RGB色空間のような実際の物理的意味を持って実際の物理的な光ではなく、XYZの3つの軸は完全に想像されているため、XYZは想像色とも呼ばれます。これは、現実の世界でXYZ 3つの物理光を実際に構築し、上記のようにそれらに基づいてカラーマッチング実験を行うことができないことを意味します。しかし、XYZ色空間には多くの利点があります。最も明白なのは、XYZ色マッチング関数がすべて正であるということです。もう1つの重要な機能は、Y軸が意図的に選択されており、その方向が明るさ関数と一致していることです。つまり、Y値が大きいほど、明るさが大きくなります。さて、ここに新しい名詞の光度関数(luminosity function)があります。とりあえずスキップしましょう。

 

これはCIE1931XYZ色空間であり、カラーマッチング関数x(λ)、y(λ)、z(λ)によって定義されます。

https://agraphicsguy.wordpress.com/2018/11/29/basic-color-science-for-graphics-engineers/から

 

このビデオは、RGB色空間からXYZ色空間への変換プロセスを非常に鮮明に表現していることに注意してください(出典:Call of DutyのHDR。)。

 

前述の新しい用語である光度関数について説明します。その定義は以下のように示します。

A luminosity function or luminous efficiency function describes the average spectral sensitivity of human visual perception of brightness.

—— From wiki

 

簡単に言えば、人間の目は、同じエネルギーの条件下では、赤色光と青色光は緑色光よりも暗いと考えており、光度関数は、同じエネルギーで異なる波長の単色光に対する人間の目の光度知覚の変化を表します。 この関数は、色覚異常などの要因の影響を受ける可能性があります。下の図の緑(タンパク眼)、赤(緑の失明)、および黄色(CIE 1931標準)は、さまざまな条件下での光度関数曲線を表しています。

 

https://medium.com/hipster-color-science/a-beginners-guide-to-colorimetry-401f1830b65aから

 

CIE 1931 XYZ色空間のY軸方向は、基本的に上記の光度関数曲線と一致しています(上の図から、CIE 1931 XYZ色空間の光度関数曲線とy(λ)関数曲線が基本的に一致していることがわかります)。つまり、XYZ空間で色のY値を観察することにより、色の明るさ情報を取得できます。

 

また、CIE1931XYZとCIE1931RGBは、同じ色データの異なる表現であることに注意してください。XYZ色空間にはさまざまな利点があるため、通常、このXYZ空間で色を定義して説明しますが、カラーデータをRGB空間に変換するには、3×3空間変換行列が必要です。


1.5次元削減を継続する:明るさを排除する

XYZ色空間は素晴らしいですが、そのような3次元空間で色を議論するのは少し難しいです。多くの場合、実際には色の彩度と飽和度のみを考慮し、明るさは考慮しません。つまり、色の表現を3次元から2次元の表現に減らすことができます。一般に、XYZ色空間から平面X + Y + Z=1に色を投影できます。この2次元色度色空間(chromaticity color space)は、CIE 1931 xyz色空間と呼ばれます(本当に小文字の名前に変更しただけです)。x+y + z = 1という制約がある場合、色度を指定するために実際に必要な値は2つだけです。通常、xyを残してzをドロップすることを選択します。つまり、上記のx + y + z = 1平面をXY平面に再投影して、色度を指定するためにxy値のみを使用できるようにします。

 

これは有名なCIE1931xy chromaticity diagram(つまり色度図)であり、明るさを考慮せずに見ることができるすべての可視色を表しています。 この馬蹄形の境界は、単色光の各波長に対応する色、つまりスペクトル軌跡(spectral locus)に対応します。

スペクトル軌跡線で囲まれた領域は、さまざまな波長の単色光を混合することで知覚できる色を表しています。

色度図は、色について話し合うための基準を提供します。あらゆる分野の人々が、ハードウェアの表示などの要因による曖昧さなしに、色度図の特定の色について話し合うことができます。


UWA公式サイト:https://jp.uwa4d.com

UWA公式ブログ:https://blog.jp.uwa4d.com

UWA公式Q&Aコミュニティ(中国語注意):https://answer.uwa4d.com

前回のプロジェクトでHDR表示を作成した時、カラーマネジメントの内容をたくさん理解する必要があると気づきました。見れば見るほど複雑になるので、勉強しながらこの記事をまとめました。

この記事は5つのセクションに分かれています。このセクションでは、光と色、CIE 1931 RGB/XYZ色空間と色度図に焦点を当てて説明しようと思います。私はそれをできるだけ簡単に説明しようとしています。私はできるだけ自分なりに分かりやすく説明しようと思います。これらの概念が何なのか、この章を読んでいただければ、はっきりと答えられると思います。

たくさんの定義と名詞の警告!恐れないで。始めましょう!


1.1 我々はどうやって光や色を見るのか

色につき、考慮すべき3つの側面があります。

  • オブジェクト

人間の目は非常に複雑な構造を持っており、機械を使って100%復元することは基本的に不可能です。人間の目にはいくつかの重要な構造があります。

  • 瞳孔(Pupil):虹彩(Iris)の真ん中にある円形の穴を指します。目の絞りに相当します。虹彩の働きにより自律的に大きさが変化して光量を調整しています。
  • 水晶体(Lens):光線が虹彩を貫いた後、水晶体を通過します。目のレンズに相当します。その幅を拡大または縮小することで、光の焦点範囲を制御できます。
  • 硝子体(Vitreous):水晶体によって屈折および集束された光は、硝子体を通過します。硝子体は、人間の目の大部分を満たし、網膜を支える厚い半透明のゲル状物質です。
  • 網膜(Retina):人間の目のフィルムに相当します。人間の目に渡された画像を受け取り、それらを電気インパルスに変換し、視神経によって脳に送信する役割を果たします。
  • 光受容体(Photoreceptors):網膜は光受容細胞で構成されており、桿体細胞(Rods)と錐体細胞(Cones)の2種類に分けることができます。
  • 桿体:光に敏感であるため、夜間および周辺視野にとって重要ですが、光受容色素の不足で色覚を発達させにくいです(色を区別できない)
  • 錐体:主に色の認識に関与し、明るい光でより良く役割を果たします。錐体光受容細胞には主に3つのタイプがあり、赤(約600 nmの波長)、緑(約550 nmの波長)、および青(約450 nmの波長)の光に最も敏感です。この視覚系は三色視覚と呼ばれます。これらの3種類の錐体はそれぞれ、長波(L)、中波(M)、および短波(S)に敏感であるため、L(ong)、M(edium)、およびS(hort)錐体と呼ばれます。

https://chrisbrejon.com/cg-cinematography/chapter-1-color-management/から

結局、脳はすべてのデータ信号を処理する責任を担います。たとえば、網膜にうつる像は上下左右が逆で、脳はそれを逆転します。したがって、実際、私たちが「見る」のは、実際に人間の目に当たる光ではなく、人間の目によって提供される信号に基づいて脳が再構築する効果です。

What we really see is our mind’s reconstruction of objects based on input provided by the eyes — not the actual light received by our eyes.

—— From this article

人間の目の構造(3種類の錐体細胞)は、私たちが知覚できる色域の範囲を決定します。他の生き物と比較して、人間の目の色覚能力は非常に無味です。たとえば、シャコには16の異なる色覚細胞があります。しかし、以下で説明するように、幸いなことに3つしかありません。そうでなければ、カラーマネジメントシステムはますます複雑になっていたでしょう。


1.2光と色とは

世界では、最初に光があり、次に色がありました。

「光」とは?

光は通常、人間の目で見ることができる電磁波(可視光)を指し、視覚は可視光への知覚です。可視光は、電磁スペクトルの特定の部分にすぎず、一般に400〜700ナノメートル(nm)の波長の電磁波、つまり、紫外線より長く、赤外線より短い波長の電磁波として定義されます。資料により、可視光の波長範囲を定義する方法は異なっています。狭いものでは420〜680 nm、広いものでは380〜800nmの範囲です。 …光は高周波電磁波であると同時に、光子と呼ばれる素粒子で構成される粒子の流れでもあります。したがって、光は粒子と波動の両方の特性を同時に持つか、光は「波動粒子の二重性」を持ちます。

-ウィキから

 

一般に、光は電磁波の形で伝わるエネルギーの一種です。多色光を分散系(プリズムなど)で分割した後、光の波長(または周波数)に応じて順番に並べてパターンを形成することができます。このパターンをスペクトル(Spectrum)と呼びます。人間の目に見えるのは可視スペクトルの一部のみです。これらの可視スペクトルは波長が約400nmから750nmで、可視光と呼ばれます。

「色」とは

色は、目、脳、および私たちの生活体験により、視覚的に感知された光の色の特徴であり、赤、オレンジ、黄色、緑、青、紫などの名前で光の色のカテゴリを表します。色への知覚は、可視スペクトルの電磁放射による人間の目の錐体細胞の刺激に由来します。色の種類と色の物理的仕様は、反射光の波長によってオブジェクトに関連付けられます。この反射は、光の吸収、発光スペクトルなど、オブジェクトの物理的特性によって決まります。しかし、色への知覚は、光の物理的性質だけでなく、心理学などの多くの要因も含みます。たとえば、色への知覚は、周囲の色の影響を受けることがよくあります。

普段いわゆる「色」とは、実際には、可視スペクトルの電磁放射による人間の目の錐体細胞の刺激です。しかし、脳の色の知覚は、光の物理的性質だけで決まるわけではありません。たとえば、色への知覚は、周囲の色の影響を受けることがよくあります。有名な青いドレスや白いドレスの事件を参照してください。

スペクトルの定義:

スペクトルとは、複雑な波長の光が分散システム(グレーティング、プリズムなど)で分割された後、光の波長(または周波数)に応じて順番に形成されるパターンです。スペクトルの一部可視スペクトルは、人間の目に見える電磁スペクトルの唯一の部分であり、この波長範囲の電磁放射は可視光と呼ばれます。スペクトルには、人間の脳が視覚的に区別できるすべての色が含まれているわけではありません。それは茶色やピンクなどの色は単一の色ではなくさまざまな色で構成されているからです。

-ウィキから

生活では、スペクトルにある単色光があまりに見られません。さまざまな強度と波長の光が混合して豊富な色世界を形成しています。光を表現する方法の一つとして、横軸に波長、縦軸にスペクトル放射発散度(明るさ、強度、フラックス)をとるスペクトルパワー分布(PSD)を使用することができます。

Source: https://agraphicsguy.wordpress.com/2018/11/29/basic-color-science-for-graphics-engineers/

 

簡単にまとめると、「光」は、スペクトルを使用して説明できる物理的な概念です。そして、「色」は、可視スペクトルの電磁放射による錐体細胞の刺激に基づいて人間の脳によって得られる視覚的な感知であり、感性的な色濃いが帯びられています。光と色は、理性と感性の絡み合いのように、離れることができません。


1.3色の量子化:カラーマッチング関数

スペクトルエネルギー分布マップは、実際に光を定量化する方法を提供します。可視光があれば、スペクトル上のすべての単一波長の光を横軸に、各単一波長のエネルギーを縦軸にし、2Dグラフを取得できます。レンダリングなどの多くの分野で、私たちが本当に気にかけているのは、各光の物理的特性ではなく、人間の目にどのような色が見えるかです。スペクトルエネルギー分布マップは、これらのフィールドについて記録する必要があるデータが多すぎます。結局のところ、可視単色光の波長範囲は400nmから750nmまでです。スペクトルエネルギー分布マップが光を定量化する一般的な方法であるというと、色を定量化するためのより簡潔な方法が必要です。

 

光の受信から色の表示まで人間の目はどのように働くかからヒントを得ました。脳の働きを考えると、脳に見えた色は、目の3種類の錐体細胞によって伝達された電気信号です。つまり、光のスペクトルエネルギー分布がどれほど複雑であっても、最終的に人間の脳に到達する信号源は常に3つだけです。さらに、スペクトル分布が完全に異なる2つの多色光があっても、錐体細胞を同じように刺激する限り、私たちの目からみれば、同じ「色」であるかもしれません。つまり、色と光の関係は1対多であり、メタメリズム(metamerism)としても知られている現象です。

 

このようにして、カラーマッチング実験が始まりました。3つの単一波長光を選択し、それらを三元光primariesと呼んでいます。可視スペクトルの単一波長光ごとに、各primaryの強度に対応する3つのパラメーターを見つけて、人間の目が同じように色を認識できるようにします。この方法で可視スペクトルのすべての単一波長光を測定すると、次のテーブルのように、関数r(λ)、g(λ)、b(λ)のセットを取得できます。

https://medium.com/hipster-color-science/a-beginners-guide-to-colorimetry-401f1830b65aから

この一連の関数は、カラーマッチング関数です。歴史的にも、このような等色マッチング実験が多く行われました。最も有名で広く使用されている(1つ)のは、1931年のCIE1931RGBカラーマッチング関数です。 CIE(International Commission on Illumination国際照明委員会、略語がCOIではなくCIEである理由は、フランス語に由来するからである)は、1913年に設立された組織であり、光と色に関連する国際規格の開発に取り組んでいます。 CIE 1931 RGBで使用される三元光の波長は、700 nm(R)、546.1 nm(G)、および435.8 nm(B)です。

 

上記のカラーマッチング関数は負の値であることに注意してください。たとえば、上の図の610nmの波長の場合、その3つの関数値は次のようになります。

λ=610nm

r(λ)= 0.34756

g(λ)= 0.04776

b(λ)= -0.00038

 

つまり、3つの正の値の三元光を使用することで、可視スペクトルのすべての単一波長光を表すことはできません。負の値を導入する必要があります。では、実験で「負の数の光」を取得するにはどうすればよいでしょうか。 520nmの波長での実験の概略図を以下に示します。

https://medium.com/hipster-color-science/a-beginners-guide-to-colorimetry-401f1830b65aから

 

520nmのような明るい緑色を再現するには、「負の赤色光」を使用する必要があることがわかります。これは、Reference Lightの側面とPrimary Red Lightの反対側に特定の強度値を持つ赤色光を使用することで相殺できます。これは赤色光の値が負です。

 

次のアニメーションは、可視スペクトルの等色マッチング実験の完全なプロセスを示しています。

 

https://medium.com/hipster-color-science/a-beginners-guide-to-colorimetry-401f1830b65aから

 

カラーマッチング関数は、単一波長の可視光源の測定を表しますが、光の重ね合わせにより、任意のスペクトルの光源に対してこのようなマッチング関数を実行できます。RGBを3次元空間の3つの座標軸とし、CIE 1931カラーマッチング関数の3つの関数を3次元空間に順番に描画すると、3次元空間にカラーラインを取得できます。この曲線はスペクトル軌跡(spectral locus)と呼ばれます。

https://agraphicsguy.wordpress.com/2018/11/29/basic-color-science-for-graphics-engineers/から

 

この曲線を原点に向かって、または原点から離れてスケーリングすることにより、この空間内のさまざまな強度の単色光の表現を表すことができます。また、この曲線上の各点に原点を接続し、放射線が得られました。各光線を無限大の方向に延長して一つの曲面に形成しました。この曲面はさまざまな波長のさまざまな明るさの単色光を表します。この曲面で囲まれたボリューム空間は、さまざまな波長とさまざまな明るさの光源を混合することで観察できるすべての色を表します。下記のビデオは、このプロセスを非常に鮮明に示しています(出典:Call of DutyのHDR、このPPTはすごい):

 

上記の3次元空間は、CIE 1931RGB色空間(次のCIE 1931 XYZ色空間と混同しないように注意してください)であり、CIE1931RGB色マッチング関数の各データセットによって定義されます。任意の可視光について、その色空間の三刺激値(tristimulus values)を使用してそれを表すことができます(前述の条件付き等色現象を思い出してください。これは、同じ三刺激値を使用してスペクトル的に異なるさまざまな光源を表すこともできることを意味します) :

人間の目に対応すると、スペクトルに対する3つの錐体の感度は、LMS色空間(Lは長い、Mは中間、Sは短い)を形成していると簡単に考えることができます。これは、色空間を簡単に定量化するために使用できます。


1.4最適化の維持:負の値を排除する

前述のように、CIE RGB色空間には負の値があり、これらの負の値はすべてRコンポーネントに表示されます。これらの負の値を排除するために、CIEは、RGB色空間から別の色空間XYZ色空間を拡張するという良いアイデアを思いつきました。3×3空間変換マトリックスを使用して、2つの色空間間で変換できます。 XYZ色空間の3つの基本ベクトルは、RGB色空間のような実際の物理的意味を持って実際の物理的な光ではなく、XYZの3つの軸は完全に想像されているため、XYZは想像色とも呼ばれます。これは、現実の世界でXYZ 3つの物理光を実際に構築し、上記のようにそれらに基づいてカラーマッチング実験を行うことができないことを意味します。しかし、XYZ色空間には多くの利点があります。最も明白なのは、XYZ色マッチング関数がすべて正であるということです。もう1つの重要な機能は、Y軸が意図的に選択されており、その方向が明るさ関数と一致していることです。つまり、Y値が大きいほど、明るさが大きくなります。さて、ここに新しい名詞の光度関数(luminosity function)があります。とりあえずスキップしましょう。

 

これはCIE1931XYZ色空間であり、カラーマッチング関数x(λ)、y(λ)、z(λ)によって定義されます。

https://agraphicsguy.wordpress.com/2018/11/29/basic-color-science-for-graphics-engineers/から

 

このビデオは、RGB色空間からXYZ色空間への変換プロセスを非常に鮮明に表現していることに注意してください(出典:Call of DutyのHDR。)。

 

前述の新しい用語である光度関数について説明します。その定義は以下のように示します。

A luminosity function or luminous efficiency function describes the average spectral sensitivity of human visual perception of brightness.

—— From wiki

 

簡単に言えば、人間の目は、同じエネルギーの条件下では、赤色光と青色光は緑色光よりも暗いと考えており、光度関数は、同じエネルギーで異なる波長の単色光に対する人間の目の光度知覚の変化を表します。 この関数は、色覚異常などの要因の影響を受ける可能性があります。下の図の緑(タンパク眼)、赤(緑の失明)、および黄色(CIE 1931標準)は、さまざまな条件下での光度関数曲線を表しています。

 

https://medium.com/hipster-color-science/a-beginners-guide-to-colorimetry-401f1830b65aから

 

CIE 1931 XYZ色空間のY軸方向は、基本的に上記の光度関数曲線と一致しています(上の図から、CIE 1931 XYZ色空間の光度関数曲線とy(λ)関数曲線が基本的に一致していることがわかります)。つまり、XYZ空間で色のY値を観察することにより、色の明るさ情報を取得できます。

 

また、CIE1931XYZとCIE1931RGBは、同じ色データの異なる表現であることに注意してください。XYZ色空間にはさまざまな利点があるため、通常、このXYZ空間で色を定義して説明しますが、カラーデータをRGB空間に変換するには、3×3空間変換行列が必要です。


1.5次元削減を継続する:明るさを排除する

XYZ色空間は素晴らしいですが、そのような3次元空間で色を議論するのは少し難しいです。多くの場合、実際には色の彩度と飽和度のみを考慮し、明るさは考慮しません。つまり、色の表現を3次元から2次元の表現に減らすことができます。一般に、XYZ色空間から平面X + Y + Z=1に色を投影できます。この2次元色度色空間(chromaticity color space)は、CIE 1931 xyz色空間と呼ばれます(本当に小文字の名前に変更しただけです)。x+y + z = 1という制約がある場合、色度を指定するために実際に必要な値は2つだけです。通常、xyを残してzをドロップすることを選択します。つまり、上記のx + y + z = 1平面をXY平面に再投影して、色度を指定するためにxy値のみを使用できるようにします。

 

これは有名なCIE1931xy chromaticity diagram(つまり色度図)であり、明るさを考慮せずに見ることができるすべての可視色を表しています。 この馬蹄形の境界は、単色光の各波長に対応する色、つまりスペクトル軌跡(spectral locus)に対応します。

スペクトル軌跡線で囲まれた領域は、さまざまな波長の単色光を混合することで知覚できる色を表しています。

色度図は、色について話し合うための基準を提供します。あらゆる分野の人々が、ハードウェアの表示などの要因による曖昧さなしに、色度図の特定の色について話し合うことができます。


UWA公式サイト:https://jp.uwa4d.com

UWA公式ブログ:https://blog.jp.uwa4d.com

UWA公式Q&Aコミュニティ(中国語注意):https://answer.uwa4d.com