HoloLens×Graphics入門
Tokyo HoloLens Meetup vol.2 - 2017/03/15
hecomi
はじめに
はじめに
• HoloLens で見られる面白い表現の解説
• 本発表のサンプルのコードは以下で公開:
• https://github.com/hecomi/HoloLensPlayground
• 詳細な解説は別途ブログにまとめます(一部まとめ済み)
自己紹介
凹(hecomi)
@hecomi
http://tips.hecomi.com
HoloLens に見られる表現
HoloLens に見られる表現
• VR や普通のゲームとは違う表現の仕方・工夫が色々とある
• こういった表現のうち基本的な幾つかを紹介・解説
• バーチャルなオブジェクトを実在感を高める
• バーチャルなオブジェクトの実在感を損なわないようにする
実在感を高める
• リアルなものでオブジェクトを遮蔽
実在感を高める
• 壁に穴をあけて別の世界を表示
実在感を高める
• 空間マッピングの提示
実在感を損なわない
• ニアクリップの表現の工夫
実在感を高める
別の世界への入り口をつくる
Unlit/Color で (0, 0, 0, 1)公式チュートリアル Holograms 101
• HoloLens では黒色が透明になる
• 穴の空いた黒いモデルを用意すれば穴空き表現が可能
別の世界への入り口をつくる
// a = オブジェクトのアルファ
(現実の色 × (1 - a)) +オブジェクトの色 × a
(現実の色 × バイザの黒半透明)+ オブジェクトの色
目に見える情報
キャプチャの情報
簡単な説明(※正確ではないので注意)
※ https://developer.microsoft.com/ja-jp/windows/holographic/case_study_-_looking_through_holes_in_your_reality
• ただし黒を描画するとキャプチャ時に黒になってしまう
別の世界への入り口をつくる
Shader "HoloLens/Occlusion"
{
SubShader
{
…
Pass
{
ColorMask 0
ZWrite On
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
ENDCG
}
}
}
色は出力しないが、
デプスは出力する
• これを回避するには ColorMask 0 をする
リアルなものでオブジェクトを遮蔽
• 同じマテリアルを空間マッピングで認識したモデルに割り当てれば、現実のもの
でバーチャルなオブジェクトを遮蔽できる
• HoloToolkit-Unity の Occlusion マテリアルがそれに該当
• = 認識した空間のデプス情報だけをゲームに書き込む
壁に穴をあけて別の世界を表示
• 決め打ちの穴空きモデルではなく動的に穴をあけてみる
壁に穴をあけて別の世界を表示
• ステンシルバッファを利用
• 見えないバッファ領域にマスク情報などを書き込める
• 詳細はこちら: http://tips.hecomi.com/entry/2017/02/18/190949
ステンシルバッファ
最終的な出力
ステンシルバッファにマスクを書き込み
画は出力しない
マスクされた場所を調べる
マスクされた場所に描画
マスクされた場所以外を調べる
マスクされた場所以外に描画
OR OR …
マスク用オブジェクト 描画オブジェクト
Stencil
{
Ref
[_Mask]
Comp Equal
}
Stencil
{
Ref [_Mask]
Comp NotEqual
}
Stencil
{
Ref [_Mask]
Comp Always
Pass Replace
}
壁に穴をあけて別の世界を表示
壁に穴をあけて別の世界を表示
• 方法1:次の順で描画
1. 窓をマスクにしたオブジェクト
2. マスク領域以外に壁
壁に穴をあけて別の世界を表示
• 方法2:次の順で描画
1. 窓をマスクにしたオブジェクト
2. マスク領域にオブジェクト 壁の穴あけとハイブリッドにしても OK
空間マッピングの提示
• デフォルト(HoloToolkit-Unity)の方法
• 認識した壁をワイヤーフレーム表示
• ジオメトリシェーダで処理
• ジオメトリシェーダで各ポリゴン内の各頂点から対
辺までの距離を求め、フラグメントシェーダでその
距離を参照して線になる場所を色塗り
HoloLens は シェーダモデル 5.0 が使える!
空間マッピングの提示
• ワールド座標を使えば色々と面白表現ができる
• ここでいうワールド座標はゲーム内だけでなく現実の座標とも考えられる
struct v2f
{
float3 worldPos : TEXCOORD0;
...
};
v2f vert(appdata_base v)
{
...
o.worldPos = mul(unity_ObjectToWorld, v.vertex);
...
}
inline float toIntensity(float3 pos)
{
return frac(length(pos) - _Time.y);
}
fixed4 frag(v2f i) : SV_Target
{
float3 worldIndex =
floor(i.worldPos.xyz * _TilesPerMeter);
float3 boxelCenter = worldIndex / _TilesPerMeter;
float intensity = toIntensity(boxelCenter);
return _Color * intensity;
}
ワールド座標を使って空間をボクセルに区切る
空間マッピングの提示
• ワールド座標を使えば色々と面白表現ができる
• ここでいうワールド座標はゲーム内だけでなく現実の座標とも考えられる
空間マッピングの提示
• スクリプト連携で壁にエフェクトを出す
Physics.Raycast
r = speed * time
center
実在感を損なわないようにする
ニアクリップ表現の工夫
https://developer.microsoft.com/en-us/windows/holographic/Hologram_stability.html より
• HoloLens では 0.85 m という比較的遠目のニアクリップが推奨
• 現実のオブジェクトとの整合
ニアクリップ表現の工夫
https://developer.microsoft.com/en-us/windows/holographic/Hologram_stability.html より
ここの表現が大事
• HoloLens では 0.85 m という比較的遠目のニアクリップが推奨
• 現実のオブジェクトとの整合
ニアクリップ表現の工夫
• ホーム画面では近づいたとき黒くなる
• Fragments ではポリゴン分解
ニアクリップ表現の工夫
• 再現してみる
ニアクリップ表現の工夫
• 頂点シェーダでカメラまでの距離を頂点ごとに取得
• 頂点カラーに開始・終了距離から算出した度合いを掛ける
• 透明にしても良いが透明オブジェクトはコスト高なので注意
float4 worldPos = mul(unity_ObjectToWorld, v.vertex);
float3 dist = length(_WorldSpaceCameraPos - worldPos);
fixed darkness = clamp((_Start - dist) / (_Start - _End), 0.0, 1.0);
o.color *= darkness;
ニアクリップ表現の工夫
[maxvertexcount(3)]
void geom(triangle appdata_t input[3], inout TriangleStream<g2f> stream)
{
for (int i = 0; i < 3; ++i)
{
...
float4 worldPos = mul(unity_ObjectToWorld, v.vertex);
float3 dist = length(_WorldSpaceCameraPos - worldPos);
fixed destruction = clamp((_Start - dist) / (_Start - _End), 0.0, 1.0);
...
v.vertex.xyz = (v.vertex.xyz - center) * (1.0 - destruction * _Scale) + center;
v.vertex.xyz = rotate(v.vertex.xyz - center, random * destruction * _Rotation) + center;
v.vertex.xyz += v.normal.xyz * destruction * _Position * random;
o.vertex = UnityObjectToClipPos(v.vertex);
...
stream.Append(o);
}
stream.RestartStrip();
}
• ポリゴン分解はジオメトリシェーダを経由すると簡単
自動で頂点がバラバラになってくれる
まとめ
まとめ
• HoloLens 特有の表現をいくつか解説
• シェーダを使えると表現の幅が広がる
• 本発表のサンプルプロジェクトは以下からダウンロード可:
• https://github.com/hecomi/HoloLensPlayground

HoloLens x Graphics 入門