夜風のMixedReality

xRと出会って変わった人生と出会った技術を書き残すためのGeekなHoloRangerの居場所

MixedRealityToolkitGraphicsToolsのDistantLightを理解する その② DistantLightのコア処理

本日は昨日に引き続きMRGTのDistantLightを調べていきます。

昨日はDistantLightの抽象クラスであるBaseLightクラスとDistantLightの初期化を見ていきました。

redhologerbera.hatenablog.com

今回はもっと深掘りした処理を読み解いていきます。

〇DistantLightのUpdate処理

DitantLighrのコア部はUpdateLights()によって行われています。

これは継承元のBaseLightクラスで定義されており、LateUpdateで実行されています。

前回は初期化の処理を追ったので今回はよりコアな処理を追っていきます。

  for (int i = 0; i < distantLightCount; ++i)
            {
    ・・・
            }

distantLightCountの数for文の処理が実行されます。

 private const int distantLightCount = 1;

次の行ではDistantLightを定義しています。

                DistantLight light = (i >= activeDistantLights.Count) ? null : activeDistantLights[i];

条件演算子ではactiveDistantLightsの数に応じて複数のDistantLightが存在している場合順番に対応するようにライトが指定されLightに代入されています。

 このactiveDistantLights.Count はライトを追加した際に発火されるAddLight()で処理が実装されています。

 AddLightは初期化と同時にライトごとに1回実行されています。

    protected override void AddLight()
    {
        if (activeDistantLights.Count == distantLightCount)
        {
            Debug.LogWarningFormat("Max distant light count {0} exceeded. {1} will not be considered by the Graphics Tools/Standard shader until other lights are removed.", distantLightCount, gameObject.name);
        }

        activeDistantLights.Add(this);
    }

activeDistantLightsはデフォルトで初期化されていますのでcountは0になります。

distantLightCountはデフォルトで1となっておりもし複数のライトを使用する場合は以下の警告文が出力されるようになっています。

最大遠方ライト数distantLightCountを超えました。
 gameObject.nameは、他のライトが削除されるまで、グラフィックツール/標準シェーダによって考慮されません。" 

これによってライトの数を取得し現在のライトをlightとして渡すようにしています。

次に内部変数dataIndexを定義します。

 int dataIndex = i * distantLightDataSize;

distantLightDataSizeはデフォルト値で2となっており、デフォルトで2の倍数でインデックスが行われているようになっています。

       private const int distantLightDataSize = 2;

dataIndexが2の倍数であるのは、dataIndex(=ライト情報)ごとに格納するデータが向き、色の2種類であるためです。

次がいよいよコアな処理になります。

lightに正しく値が入力されている場合、if文の中が実行されます。

  if (light)
                {
                    Vector4 direction = -light.transform.forward;
                    distantLightData[dataIndex] = new Vector4(direction.x,
                                                              direction.y,
                                                              direction.z,
                                                              1.0f);
                    distantLightData[dataIndex + 1] = new Vector4(light.Color.r * intensity,
                                                                  light.Color.g * intensity,
                                                                  light.Color.b * intensity, 
                                                                  1.0f);
                }

 ライトの向きの逆ベクトルをdirectionとして代入しています。

 ライトの向きをdistantLightData[dataIndex]に格納しています。

 ここでTransform.xyzなのでw値には1を入れています。(ダミーでしょうか)

distantLightData[dataIndex + 1]つまり向きの次のデータにはライトの色を代入しています。

distantLightData[dataIndex + 1] = new Vector4(light.Color.r * intensity,
                                                                  light.Color.g * intensity,
                                                                  light.Color.b * intensity, 
                                                                  1.0f);

〇シェーダーへの適応

シェーダーにデータを渡している処理は次の一文です。

  Shader.SetGlobalVectorArray(_DistantLightDataID, distantLightData);

SetGlobalVectorArrayはVector型で渡すShaderのグローバル変数になります。

docs.unity3d.com

ここでMRGTStandardShaderと接続してDirectionとColorの情報を渡しています。

本日は以上です。

DistantLigtの処理に関して把握できたため次回一度まとめていきます