はじめに
Depth Video Player VRは深度付きの動画を視聴、確認する Windows用の簡易メディアプレイヤーです。デスクトップアプリケーションですが、OpenXR対応なのでSteamVR等を使ってVRデバイスで視聴することもできます。
- Depth Video Player VR
- 深度付き動画
通常の2D動画の画像と 深度推定の結果を並べたもの
深度付き動画は Depth Anything等を駆使して作ることができますが Python用の専用ツールを近日公開します。
動作条件
項目 | 内容 |
---|---|
OS | Windows 10 / 11 |
ビデオファイル再生 | AVPro (Media Foundation) |
VRモード | OpenXR |
- VRモードは以下の環境で動作確認しました
項目 | 内容 |
---|---|
OS | Windows 10 / 11 |
VRプラットフォーム | SteamVR (OpenXR) |
VR機種 | Meta Quest 2 / 3 |
そのほか | Meta Quest版の Virtual Desktop使用 |
ダウンロード
使い方
インストール作業はありません。解凍してできるDepthVideoPlayerVR.exeを実行してください。
動画ファイルをエクスプローラーなどからドラッグ&ドロップするか playlist.txtへ動画ファイルを列挙して使います。
VRモード
vr.batから起動するか、Vキーを押すとVRモードで動作します。
右のコントローラーで操作します。左は使えません。
操作 | 内容 |
---|---|
トリガーを押しながらBボタン | アプリ終了 |
グリップ | スクリーン移動と回転 |
グリップを押しながらBボタン | 位置や向きをリセット |
グリップを押しながらスティック | スケールとZ座標の調整 |
スティックを押す | 一時停止 |
スティック左右 | 10秒送り |
トリガーを押しながらスティック | 1分送り |
Aボタン Bボタン | 次のファイルを再生 |
- シークバーの操作はできません。 どうしてもという場合はデスクトップに表示されているシークバーをマウスで操作してください
- ボリューム調整はできません。キーボードで操作してください
- Dキーを押すと 2D映像と並べて表示します
Meta Questの場合にハンドトラッキングが有効だと コントローからハンドに(勝手に)切り替わって誤動作するので Questの設定からハンドトラッキングを無効にしてください。
動作原理
方眼状メッシュの各頂点の位置を右側の深度画像の輝度を使って調整します。
そうやって凸凹になったメッシュへ 左側の画像を張り付ければ完成です。
この処理は下記シェーダープログラムで完結します。
-
シェーダープログラム
Shader "AmaRecVR/depth"
{
Properties
{
_MainTex ("Base (RGB) Trans (A)", 2D) = "black" {}
}
SubShader
{
Tags { "RenderType"="Transparent" "IgnoreProjector"="True" "Queue"="Transparent" }
LOD 100
ZWrite On // 手前のものに奥のものが隠れるように Zバッファを使う
ZTest LEqual // 既に書き込まれたZ値より手前の場合に 描画する(奥のものは描画しないので 隠れる)
Blend One Zero
Lighting Off
Cull Off
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 3.0
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
float2 uv : TEXCOORD0;
};
// 動画の画像
uniform sampler2D _MainTex;
// 頂点シェーダー
v2f vert (appdata v)
{
v2f o;
//頂点に該当する テクスチャの座標(uv)を計算 一般的な処理
float2 uv = (v.uv * float2(0.5, 1.0)); // 左半分だけ使う 横座標を半分にするだけ
uv.y = 1.0 - uv.y; // 上下を反転させる
o.uv = uv; // フラグメントシェーダーへ伝える
// 画像の右側のピクセル(深度)を取得 uv座標へ0.5足して 画像からサンプリングする
fixed4 col = tex2Dlod(_MainTex, float4(uv + float2(0.5, 0.0), 0, 0));
// 赤の値を使って メッシュのZ座標を調整 押し出し具合が変わる
v.vertex.z = -col.r/2;
o.vertex = UnityObjectToClipPos(v.vertex); // 調整した頂点の座標を計算する 一般的な処理
return o;
}
// フラグメントシェーダー 画像を張り付ける 一般的な処理
fixed4 frag (v2f i, fixed facing : VFACE) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
col.rgb = (facing > 0 ) ? col.rgb: col.rgb / 4.0; // 裏面を暗くする
return col;
}
ENDCG
}
}
Fallback "Diffuse"
}
頂点シェーダー v2f vert (appdata v)で上記の処理を行っています。