Skip to content

軽量化について

Naoaki-Y edited this page Jan 26, 2020 · 1 revision

500個の方位磁針の個々の物理計算を毎フレームおこないながら、FPS 58を実現しています。

具体的には、シェーダをインスタンス化せずに、シェーダで物理計算をおこなって負荷を大幅に減らしています。

なお、軽量化が必要な理由については次項の「UI・表現」で説明します。

シェーダをインスタンス化しない

以下のように、マテリアルをスクリプトから操作せずに、シェーダに外部変数を受け取る変数を設定し、スクリプトからマテリアルを介さずにシェーダに直接値を代入しています。

CompassesManagedlySimultaneouslyUpdater.cs

void AssignMagnetPosition()
    {
        var np = barMagnet01NorthPole.transform.position;
        var sp = barMagnet01SouthPole.transform.position;
        var nv4 = new Vector4(np.x, np.y, np.z, 0);  //Vector4 に変換
        var sv4 = new Vector4(sp.x, sp.y, sp.z, 0);  //Vector4 に変換

        // 方位磁針の N 極側のマテリアルのシェーダに座標をセット
        CompassesModel.Instance.MatNorth.SetVector("_NorthPolePos", nv4);
        CompassesModel.Instance.MatNorth.SetVector("_SouthPolePos", sv4);
        // 方位磁針の S 極側のマテリアルのシェーダに座標をセット
        CompassesModel.Instance.MatSouth.SetVector("_NorthPolePos", nv4);
        CompassesModel.Instance.MatSouth.SetVector("_SouthPolePos", sv4);
    }

これによりシェーダがインスタンス化されず、単一のシェーダとして処理されるため、計算負荷を大幅に減らすことができます。

シェーダ内で物理計算を行う

以下のように、シェーダ内で物理計算を行っています。

MyCompassShader2.shader

// 自身(方位磁針)の位置ベクトルvecPを作成
float3 vecP;
vecP = IN.worldPos;

// N極の位置ベクトルvecNを作成
float3 vecN;
vecN.x = _NorthPolePos.x;
vecN.y = _NorthPolePos.y;
vecN.z = _NorthPolePos.z;

// S極の位置ベクトルvecSを作成
float3 vecS;
vecS.x = _SouthPolePos.x;
vecS.y = _SouthPolePos.y;
vecS.z = _SouthPolePos.z;

// 自身から棒磁石に対する変位ベクトルvecDisN、vecDisSを作成
float3 vecDisN, vecDisS;
vecDisN = vecP - vecN;
vecDisS = vecP - vecS;

// 極からの磁力ベクトルvecF_N, vecF_Sを求める
float3 vecF_N, vecF_S;
vecF_N =        vecDisN / pow(length(vecDisN), 3);
vecF_S = -1.0 * vecDisS / pow(length(vecDisS), 3);

// 磁力の合力ベクトルvecFを求める
float3 vecF;
vecF = vecF_N + vecF_S;

これにより、物理計算をGPU内で完結させることができ、CPUへの負荷を大幅に減らすことができます。HoloLensのCPUはとても非力なため、必要な処理をどれだけGPUに回せるかが重要です。