夜風のMixedReality

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

MRGT GraphicsToolsStandardShaderに影を受け取る機能を追加する。 その②GraphicsToolsのライト機能の継承

本日はMRGT枠です。

前回に引き続きGraphicsToolsStandardShaderで影を受け取る機能を追加します。

redhologerbera.hatenablog.com

〇MRGTとは?

MixedRealityGraphicsTools(MRGT)はMicrosoftによってオープンソースな形で開発、提供されているMixedRealityデバイス向けのSDKである第三世代のMixedRealityToolkit(MRTK3)で提供されるグラフィック関連のパッケージを指します。

 MRTKのコア機能に当たるGraphicsToolsStandardShaderは多くの機能をサポートしていますが、もともとがHoloLensで使用される想定であったことと軽量化のためにほかのオブジェクトとの影の相互関係の機能がありません。

github.com

 今回は影を受けるようにしていきます。

〇GraphicsToolsLighting.hlsl

MRGTのGraphicsToolsStandardShaderではUnityのシェーダー本体のファイルであるGraphicsToolsStandard.shaderを中心にいくつかの機能ごとに割り振った.hlslファイルをIncludeして構成されています。

代表的なものはGraphicsToolsInput.hlslファイルで、ここでは変数の定義や頂点シェーダー、フラグメントシェーダーで使用される構造体が定義されています。

struct Attributes
{
 ・・・

    UNITY_VERTEX_INPUT_INSTANCE_ID
};

/// <summary>
/// Vertex attributes interpolated across a triangle and sent from the vertex shader to the fragment shader.
/// </summary>
struct Varyings
{
・・・
}

同様にライティングに関する機能もGraphicsToolsLighting.hlslという別のhlslファイルに定義されており、こちらもIncludeして使用しています。

#include "GraphicsToolsCommon.hlsl"
#include "GraphicsToolsStandardInput.hlsl"
#include "GraphicsToolsLighting.hlsl"

シェーダー内でライトを使用する場合GTMainLightとしてGTGetMainLight()を取得しています。

    GTMainLight light = GTGetMainLight();

GTGetMainLight()GraphicsToolsLighting.hlslで定義されている関数でURPの場合はURPで提供されているLighting.hlsl"GetMainLight()を継承しています。

ビルドインの場合も一般的なライト情報を取得してGTMainLight構造体にデータを格納しています。

  GTMainLight GTGetMainLight()
    {
    GTMainLight light;
#if defined(_DIRECTIONAL_LIGHT) || defined(_DISTANT_LIGHT)
#if defined(_DISTANT_LIGHT)
    light.direction = _DistantLightData[0].xyz;
    light.color = _DistantLightData[1].xyz;
#else
#if defined(_URP)
    Light directionalLight = GetMainLight();
    light.direction = directionalLight.direction;
    light.color = directionalLight.color;
#if defined(_RECEIVESHADOW)
        light.shadowAttenuation = GetMainLight(shadowCoord).shadowAttenuation;
#endif
#else
    light.direction = _WorldSpaceLightPos0.xyz;
    light.color = _LightColor0.rgb;
#endif
#endif
#endif
    return light;
}

GTMainLight構造体ではdirection(方向)、color(色)を格納しています。

struct GTMainLight
{
    half3 direction;
    half3 color;
};

RealtimeLighting.hlslで定義されているこのGetMainLightの処理を追うとここでshadowCoordを引数として用いてUnityのリアルタイムシャドウに関する処理も用意されています。

Light GetMainLight(float4 shadowCoord)
{
    Light light = GetMainLight();
    light.shadowAttenuation = MainLightRealtimeShadow(shadowCoord);
    return light;
}

以前行ったほかのオブジェクトの影を受けるシェーダーのチュートリアルでは、GetMainLight(input.shadowCoord)として頂点シェーダーで処理して取得したshadowCoordを引数として渡すことで影の情報をhalf4 light.shadowAttenuationに格納していました。

redhologerbera.hatenablog.com

そのためGraphicsToolsStandardShaderで影を受け取る機能を実装するためには次の手順を踏む必要があります。

  1. 頂点シェーダーからフラグメントシェーダーへ渡す構造体(一般的にv2f)にshadowCoordを定義

  2. GTMainLightの構造体に影のデータとしてshadowAttenuationを定義

  3. GraphicsToolsLighting.hlslGTGetMainLight()に引数としてshadowCoordを定義

  4. GraphicsToolsLighting.hlslGTGetMainLight()で引数として定義したshadowCoordRealtimeLighting.hlslで定義されているGetMainLight(shadowCoord)として処理を渡す。

次回から進めていきます。