開発者向けリソース

Unreal Engine + Steam Frame + Arcturus Vision Camera

Unreal Engine のパススルー設定

Lepton と OpenXR のアルファ合成で、Steam Frame 上でローカル実行する Android ARM64 アプリを作成します。

Steam Frame 上の Unreal + Lepton。不透明な色付きキューブと半透明カウンターを実際の部屋に合成した映像
Steam Frame 上の Unreal + Lepton。ヘッドセットのコンポジター画像で、不透明なキューブの背景と半透明カウンター越しにカメラのパススルー映像が見えます。

カメラ背景は OpenXR ランタイムが合成します。XR_ENVIRONMENT_BLEND_MODE_ALPHA_BLEND はコア仕様のブレンドモードであり、生のカメラ映像を取得する SDK や追加のパススルー拡張は不要です。この構成の出力は Linux ARM64 パッケージではなく Android APK です。

必要な環境

項目バージョン / 設定
エンジンUnreal Engine 5.8.3 · ソースビルドと対応するホストツール
Java / NDKJDK 21 / r27c · 27.2.12479018
SDK / ビルドツールandroid-30・android-36 / 36.0.0
デバイス API最小・ターゲット・NDK API 30
ターゲットAndroid ARM64 · Vulkan ES3.1 · ASTC

コンパイル用に SDK プラットフォーム36をインストールし、デバイスの最小・ターゲット API は30に設定します。

01

エンジンと Android ツールをインストール

Epic Games Launcher の Installation Options → Target Platforms で Android を有効にします。上記の SDK、NDK、JDK、platform-tools をインストールし、Project Settings → Android SDK でパスを設定します。

連携した Epic・GitHub アカウントから対応するエンジンソースを取得します。公式依存ファイルをインストールし、ホストエディターとクック用ツールをビルドします。以下のアロケーターと描画の変更には、Android エンジンモジュールの再ビルドが必要です。

02

Binned2 を選択

C++ プロジェクトを作成します。Steam Frame 起動時のメモリ割り当てクラッシュを回避するため、ゲームの Target.cs コンストラクターにこの Android 設定を追加します。ソースから再ビルドできるエンジンを使ってください。プリコンパイル済み Binned3 ライブラリは再利用できません。

// In your game's Target.cs constructor:
if (Target.Platform == UnrealTargetPlatform.Android)
{
    BuildEnvironment = TargetBuildEnvironment.Unique;
    StaticAllocator = StaticAllocatorType.Binned2;
}

03

Android と OpenXR を設定

OpenXR、XRBase、Enhanced Input を有効にし、OpenXR のプラットフォーム許可リストに Android を含めます。Android File Server は無効にします。各ブロックを先頭に記載したファイルに適用し、com.example.yourproject をプロジェクトの Android パッケージ ID に変更して、Game Default Map を Maps to Cook に追加します。

標準の OpenXR では汎用コントローラーバインディングを使用します。Steam Frame 固有のキーや性能機能には、Valve の Steam Frame OpenXR Extension プラグイン手順を参照してください。

; Config/DefaultEngine.ini
[/Script/AndroidRuntimeSettings.AndroidRuntimeSettings]
PackageName=com.example.yourproject
bBuildForArm64=True
bBuildForX8664=False
bSupportsVulkan=True
bSupportsVulkanSM5=False
bBuildForES31=False
bDetectVulkanByDefault=True
bPackageForOpenXRImmersive=True
bPackageForMetaQuest=False
bSkipLibCpp=True
MinSDKVersion=30
TargetSDKVersion=30
SDKAPILevelOverride=android-30
NDKAPILevelOverride=android-30
BuildToolsOverride=36.0.0
bPackageDataInsideApk=True
bEnableBundle=False
bShowLaunchImage=False
bUseExternalFilesDir=True
bAllowIMU=False

; Config/DefaultGame.ini
[/Script/EngineSettings.GeneralProjectSettings]
bStartInVR=True

04

アルファを有効にしてパススルーを要求

背景を透明にし、不透明なスカイボックスは置きません。透けないオブジェクトには不透明、透ける部分には半透明のマテリアルを使用します。モバイル描画経路でアルファを保持するため、以下の設定を適用します。

Android モジュールの依存関係に OpenXRHMD と OpenXR を追加します。XR セッション開始後に、ゲームスレッドで RequestPassthrough(true) を呼び出します。ランタイムの対応を確認し、要求した状態を保持してセッション再作成時にも再適用します。false で呼び出すと Opaque を要求します。

; Config/DefaultEngine.ini
[/Script/Engine.RendererSettings]
r.Mobile.PropagateAlpha=1
r.PostProcessing.PropagateAlpha=True
r.MobileHDR=True
r.Mobile.ShadingPath=0
r.Mobile.AntiAliasing=3
r.MSAACount=4
r.DynamicGlobalIlluminationMethod=0
r.ReflectionMethod=0
r.DefaultFeature.Bloom=False
r.DefaultFeature.AutoExposure=False
r.DefaultFeature.MotionBlur=False
r.DefaultFeature.AmbientOcclusion=False

[ConsoleVariables]
OpenXR.AlphaInvertPass=1
xr.OpenXRInvertAlpha=0
xr.OpenXREnvironmentBlendMode=0

; Config/Android/AndroidEngine.ini
[/Script/Engine.RendererSettings]
vr.MobileMultiView=True

#include "CoreMinimal.h"
#if PLATFORM_ANDROID
#include "OpenXRBlueprintFunctionLibrary.h"
#endif

// Call on the game thread after the XR session starts.
bool RequestPassthrough(bool Enable)
{
#if PLATFORM_ANDROID
    const auto Mode = Enable ? EOpenXREnvironmentBlendMode::AlphaBlend
                             : EOpenXREnvironmentBlendMode::Opaque;
    if (!UOpenXRBlueprintFunctionLibrary::GetSupportedEnvironmentBlendModes().Contains(Mode))
        return false;
    UOpenXRBlueprintFunctionLibrary::SetEnvironmentBlendMode(Mode);
    return UOpenXRBlueprintFunctionLibrary::GetEnvironmentBlendMode() == Mode;
#else
    return false; // OpenXR is enabled here only for Android.
#endif
}

05

UE 5.8.3 のモバイルアルファ resolve を修正

モバイル HDR・マルチビュー・MSAA のトーンマップサブパスは、アルファを1に固定します。以下の3か所を変更し、シーンのアルファを保持して、未使用の SceneColor resolve ではなく最終 resolve で反転させます。Android の Renderer を再ビルドし、シェーダーを再クックしてください。

Engine/Shaders/Private/PostProcessTonemap.usf

// MobileCustomResolve_MainPS: keep the fetched SceneColor.a.
// Remove the assignment SceneColor.a = 1.0;
// Replace OutColor.a = 1.0; with:
OutColor.a = ColorScale0.a > 0.0
    ? (ColorScale0.a > 1.0 ? 1.0 - SceneColor.a : SceneColor.a)
    : 1.0;

Engine/Source/Runtime/Renderer/Private/PostProcess/PostProcessTonemap.cpp

// In the FMobileCustomResolvePS parameter setup:
const float AlphaMode = IsMobilePropagateAlphaEnabled(View.GetShaderPlatform())
    ? (View.Family->EngineShowFlags.AlphaInvert ? 2.0f : 1.0f) : 0.0f;
PSShaderParameters.ColorScale0 = FVector4f(
    Settings.SceneColorTint.R, Settings.SceneColorTint.G,
    Settings.SceneColorTint.B, AlphaMode);

Engine/Source/Runtime/Renderer/Private/MobileShadingRenderer.cpp

// In RenderForward, guard the separate AddAlphaInvertPass call:
if (ViewFamily.EngineShowFlags.AlphaInvert && !bTonemapSubpass)
{
    AlphaInvert::AddAlphaInvertPass(GraphBuilder, MainView, SceneTextures);
}

06

Android (ASTC) をビルド・パッケージ化

エンジン、プロジェクト、SDK、JDK のパスを設定します。YourProject は C++ ターゲット名に変更してください。最初にネイティブモジュールをビルドし、対応するホストツールでクックして Development APK を作成します。

以下のシェルコマンドは RunUBT.sh と RunUAT.sh を使います。Windows では同じビルド引数を Build.bat と RunUAT.bat に渡してください。APK は Builds/Android に出力されます。

export UE_ROOT="/path/to/UnrealEngine-5.8.3"
export PROJECT="/path/to/YourProject/YourProject.uproject"
export ANDROID_HOME="/path/to/Android/sdk"
export ANDROID_SDK_ROOT="$ANDROID_HOME"
export NDKROOT="$ANDROID_HOME/ndk/27.2.12479018"
export NDK_ROOT="$NDKROOT"
export JAVA_HOME="/path/to/jdk-21"
export PATH="$JAVA_HOME/bin:$ANDROID_HOME/platform-tools:$PATH"

"$UE_ROOT/Engine/Build/BatchFiles/RunUBT.sh" \
  YourProject Android Development -Project="$PROJECT" -skipdeploy -NoUBA

# Package after the native build succeeds.
"$UE_ROOT/Engine/Build/BatchFiles/RunUAT.sh" BuildCookRun \
  -project="$PROJECT" -noP4 -unattended \
  -targetplatform=Android -cookflavor=ASTC -clientconfig=Development \
  -skipbuild -cook -stage -pak -package -archive \
  -nocompileeditor -nocompileuat -nocompile \
  -archivedirectory="$(dirname "$PROJECT")/Builds/Android"

07

Lepton 経由でインストール・起動

Steam Frame の Developer Mode を有効にして USB を接続し、ヘッドセットの Steam ライブラリから Lepton Development を起動します。USB adb の接続先は SteamOS です。5555 番ポートを転送して Android に接続し、以下の USB シリアル、APK パス、パッケージ ID を変更してください。

開発コンテナーが再作成された場合は再インストールします。Steam ライブラリへの登録には Valve の Devkit Client で APK をアップロードし、Runtime → Android を選択します。

adb devices -l
# Replace frame with the USB serial shown above.
adb -s frame forward tcp:5555 tcp:5555
adb connect localhost:5555

adb -s localhost:5555 shell getprop ro.build.version.release
adb -s localhost:5555 install -r /path/to/YourProject-arm64.apk
adb -s localhost:5555 shell am start -W \
  -n com.example.yourproject/com.epicgames.unreal.GameActivity

08

パススルーを確認

背景と半透明部分越しに部屋が見え、不透明なオブジェクトは透けないことを確認します。両眼、パススルー切り替え、セッション再起動を確認してください。映像が不透明な場合は、ランタイムのブレンドモード対応と最終画像のアルファを調べ、描画の変更を再ビルド・再クックしたことを確認します。

adb -s localhost:5555 logcat -d | \
  rg 'OpenXR|Vulkan|AlphaInvertPass'

リファレンス