Appearance
LKG Bridge 不要レンダリング
概要
Looking Glass ディスプレイは通常 Looking Glass Bridge というデスクトップアプリ経由でキャリブレーションやレンダリングを行います。しかし iPad では Bridge が動作しません。本調査では、Bridge を介さずにレンチキュラーレンダリングを独自実装するために必要な技術情報をまとめています。
レンチキュラーレンダリングの原理
Looking Glass はレンチキュラーレンズを使った裸眼立体視ディスプレイです。画面上の各サブピクセル(R/G/B)に、見る角度に応じた異なるビュー(視点)の画像情報を割り当てます。
表示パイプライン
多視点画像(Quilt)
↓ サブピクセルインターリービング
レンチキュラー画像(画面に表示される最終画像)
↓ レンチキュラーレンズ
裸眼立体視(見る角度で異なる画像が見える)レンチキュラーシェーダーのアルゴリズム
- 各画面ピクセルの UV 座標から、R/G/B サブピクセルそれぞれが見るべき「ビューインデックス」を計算
view = (screen_uv.x + screen_uv.y * tilt) * pitch - center(各サブピクセルで subp 分ずらす)- ビューインデックスからキルトテクスチャ内のタイル座標を計算
- R, G, B を別々のビューからサンプリング(サブピクセルインターリービング)
キャリブレーション JSON(visual.json)
ファイルの場所
Looking Glass デバイス本体のストレージ内に保存されています:
LKG-XXXXXX/LKG_calibration/visual.json- iPad/iPhone: USB-C 接続 → ファイルアプリで直接アクセス
- PC: USB 接続 → ストレージとしてマウント → コピー
フィールド一覧
json
{
"configVersion": "string",
"serial": "string",
"pitch": { "value": 45.0 },
"slope": { "value": -5.0 },
"center": { "value": -0.5 },
"fringe": { "value": 0 },
"viewCone": { "value": 40 },
"invView": { "value": 1 },
"verticalAngle": { "value": 0.0 },
"DPI": { "value": 338.0 },
"screenW": { "value": 3840 },
"screenH": { "value": 2160 },
"flipImageX": { "value": 0.0 },
"flipImageY": { "value": 0.0 },
"flipSubp": { "value": 0.0 },
"CellPatternMode": { "value": 0 },
"subpixelCells": [
{
"ROffsetX": 0.0, "ROffsetY": 0.0,
"GOffsetX": 0.0, "GOffsetY": 0.0,
"BOffsetX": 0.0, "BOffsetY": 0.0
}
]
}シェーダーユニフォームへの変換式
生のキャリブレーション値からシェーダーで使う値への変換が必要です:
// pitch の変換
screenInches = screenW / DPI
pitch_shader = pitch_raw * screenInches * cos(atan(1.0 / slope))
// tilt の変換
tilt = screenH / (screenW * slope) * (flipImageX >= 0.5 ? -1 : 1)
// subpixel の変換
subp = 1.0 / (3 * screenW) * pitch_shaderTypeScript版(WebXR ライブラリより):
typescript
get pitch() {
return (calibration.pitch.value * calibration.screenW.value / calibration.DPI.value)
* Math.cos(Math.atan(1.0 / calibration.slope.value))
}
get tilt() {
return (calibration.screenH.value / (calibration.screenW.value * calibration.slope.value))
* (calibration.flipImageX.value ? -1 : 1)
}
get subp() {
return (1 / (calibration.screenW.value * 3)) * (calibration.flipImageX.value ? -1 : 1)
}AI補完
pitch / slope / center の意味:
- pitch: レンチキュラーレンズのピッチ(1つのレンズの幅に対応するピクセル数)。デバイスのDPIとレンズの物理寸法から決まります。
- slope: レンチキュラーレンズの傾斜角。レンズが画面の垂直軸から微小角度傾いているため、この補正が必要です。
- center: レンズとサブピクセルの位相オフセット。個体ごとにわずかに異なる製造上のズレを補正します。
これらの値はデバイスごとに異なり、正確な立体視のために個体別キャリブレーションが必要です。
Unity Plugin のレンチキュラーシェーダー
シェーダーユニフォーム
Lenticular.shader(Assets/Looking Glass Plugin/Shaders/)で使用される主要ユニフォーム:
| 変数名 | 説明 |
|---|---|
p_pitch | 処理済みピッチ値 |
p_slope | 処理済みスロープ値 |
center | センターオフセット |
screenW, screenH | 画面解像度 |
rotated | 回転フラグ |
subpixelCells | サブピクセルセル配列(OLEDデバイス用) |
ビュー計算の核心ロジック
glsl
// 各画面ピクセルのUV座標からビューインデックスを計算
n_views = uv.x + uv.y * p_slope
// サブピクセルごとに異なるビューをサンプリング
views[0] = screen_uv.x + subp * 0.0; // R
views[1] = screen_uv.x + subp * 1.0; // G
views[2] = screen_uv.x + subp * 2.0; // B
views[0] += screen_uv.y * slope;
views[1] += screen_uv.y * slope;
views[2] += screen_uv.y * slope;
views *= vec3(pitch);
views -= vec3(center);
views = vec3(1.0) - fract(views);GLSL レンチキュラーシェーダー(簡易版)
mpv プレーヤー等で使える最小限のGLSLシェーダーです:
glsl
const float tilt = -0.12039111681976107;
const float pitch = 370.66407267416486;
const float center = 0.13695651292800903 + tilt*pitch;
const float subp = 1.0 / (3*2560) * pitch;
const vec2 tiles = vec2(5,9);
vec2 quilt_map(vec2 pos, float a) {
vec2 tile = vec2(tiles.x-1,0), dir=vec2(-1,1);
a = fract(a)*tiles.y;
tile.y += dir.y*floor(a);
a = fract(a)*tiles.x;
tile.x += dir.x*floor(a);
return (tile+pos)/tiles;
}
vec4 hook() {
vec4 res;
float a;
a = (HOOKED_pos.x + HOOKED_pos.y*tilt)*pitch - center;
res.x = HOOKED_tex(quilt_map(HOOKED_pos, a)).x;
res.y = HOOKED_tex(quilt_map(HOOKED_pos, a+subp)).y;
res.z = HOOKED_tex(quilt_map(HOOKED_pos, a+2*subp)).z;
res.w = 1.0;
return res;
}モデル別キルト設定
| モデル | シリアルプレフィックス | キルト解像度 | 列×行 | 総ビュー数 |
|---|---|---|---|---|
| Looking Glass 8.9" | LKG-2K | 4096×4096 | 5×9 | 45 |
| Looking Glass 15.6" | LKG-4K | 4096×4096 | 5×9 | 45 |
| Portrait | LKG-P | 3360×3360 | 8×6 | 48 |
| 16" Gen2 | LKG-A | 4096×4096 | 5×9 | 45 |
| 32" Gen2 | LKG-B | 8192×8192 | 5×9 | 45 |
| 65" | LKG-D | 8192×8192 | 8×9 | 72 |
| Go | LKG-E | 4092×4092 | 11×6 | 66 |
| 16" Spatial OLED (Portrait) | LKG-H | 5995×6000 | 11×6 | 66 |
| 16" Spatial OLED (Landscape) | LKG-J | 5999×5999 | 7×7 | 49 |
| 32" Spatial Display (Portrait) | LKG-K | 8184×8184 | 11×6 | 66 |
| 32" Spatial Display (Landscape) | LKG-L | 8190×8190 | 7×7 | 49 |
Bridge 通信プロトコル(参考)
通常の Bridge 経由のフローです(iPad では使えません)。
HTTP API
- デフォルトポート: HTTP 33334, WebSocket 9724
- エンドポイント:
http://localhost:33334/{endpoint} - 主要メソッド:
enter_orchestration: セッション開始available_output_devices: ディスプレイ一覧取得(キャリブレーション含む)update_devices: デバイス情報更新
キャリブレーション取得フロー
BridgeConnectionHTTP.Connect()で WebSocket 接続TryEnterOrchestration()でセッション開始UpdateDevicesAsync()でavailable_output_devicesを呼び出し- レスポンスから Display オブジェクトを解析
Display.calibrationにCalibration.Parse()でパース
Bridge なしでの代替手段
| 方法 | 説明 | iPad対応 |
|---|---|---|
| USB ストレージから直接読み取り | USB-C接続 → ファイルアプリで visual.json にアクセス | ✅ |
| 手動キャリブレーション | テストパターンを表示しながら tilt/pitch/center を手動調整 | ✅ |
| Looking Glass Studio for iOS | 公式iOSアプリが visual.json を直接読み込み | ✅ |
iPad での制限事項:
- iPad ではネイティブの Looking Glass Bridge が動作しない
- USB-C 経由で visual.json を取得する方法が主要
- Go デバイスの場合、ファームウェア v1.0.59 以上が必要
重要なファイルパス(Unity Plugin 4.0-alpha)
シェーダー
Assets/Looking Glass Plugin/Shaders/Lenticular.shaderAssets/Looking Glass Plugin/Shaders/QuiltCopy.shaderPackages/com.unity.render-pipelines.core/ShaderLibrary/LookingGlass/LookingGlassSettings.hlsl
C# スクリプト
Assets/Looking Glass Plugin/Scripts/CalibrationLoader.csAssets/Looking Glass Plugin/Scripts/BridgeInterface.csPackages/com.unity.render-pipelines.core/Runtime/Looking Glass/MultiviewData.csAssets/Looking Glass Plugin/Plugins/LKG-Toolkit/Toolkit-API/Device/Calibration.csAssets/Looking Glass Plugin/Plugins/LKG-Toolkit/Toolkit-API/Bridge/BridgeConnectionHTTP.cs
オープンソース実装(参考)
| プロジェクト | ライセンス | 内容 |
|---|---|---|
| looking-glass-webxr(公式) | Apache-2.0 | WebXR Polyfill |
| holoplaycore.js(公式) | 独自 | Bridge通信 + Shader生成 |
| lonetech/LookingGlass | - | mpv用GLSLシェーダー |
| surf-visualization/looking-glass | BSD | Python実装(キャリブレーション含む) |
関連記事
- AM3D 概要 — プロジェクト全体像
- iPad Unity アプリ仕様 — iPad アプリでのレンダリング実装
Author: 山本颯一郎 | Source: 0226LKGBridgeを介さないレンダリングの独自実装について AI Enhanced: Claude — 2026-03-06