[Shader 入門 #06]  VR / WebXR / Unity XR のシェーダー注意点(実戦編)

第6回:VR / WebXR / Unity XR のシェーダー注意点(実戦編)

VR / WebXR / Unity XR のシェーダーは、 通常の 3D シェーダーとは 前提が根本的に違う。

  • 描画は「左右の目」で 2回 行われる
  • 透明や反射は 破綻しやすい
  • multipass・SSR などの重い処理は 致命的に遅くなる

Three.js や Unity の基礎を理解していても、 「VR になると突然フレームが落ちる」「透明が左右でズレる」など XR 特有の問題に必ずぶつかる。

最終回では、 “平面では起きないのに VR だと破綻する理由” と “何を避け、何を使えば安全か” を まとめて整理する。

あなたが WebXR で積んだ経験は、この章で武器になる。

1. VR 用シェーダーの前提:画面は常に「2回」描かれる

VR では 左目・右目の2つのカメラでシーンを描画する。 つまり、同じシェーダーが毎フレーム ×2 で実行される。

そのため、Three.js / Unity どちらでも次が絶対ルールになる:

  • noise・depth・reflection などの重い処理はコストが 2 倍になる
  • blur / multipass(複数パス)は即フレーム落ちの原因
  • 結果として “1フレームで使える budget” は平面の 1/2 以下

特に VR は 90fps / 72fps を割ると一瞬で酔うため、 平面では問題ない処理も、VR では破綻する。

→ VR シェーダーとは “軽量化を最優先するシェーダー” のこと。

2. ステレオレンダリングの罠(Three.js / Unity 共通)

罠1:頂点数=負荷2倍(VR は頂点が重い)

VR では “左右の目” で 頂点シェーダーも2回 走る。 だから メッシュの subdiv / 解像度の高さが直撃で重くなる。

特に危険なのは:

  • 細かすぎる水面メッシュ
  • 高ポリゴンの地形
  • subdiv された plane をそのまま大量配置

→ 水面は細かさではなく「動き」で誤魔化す方が安い (sin / noise を使った vertex animation が最適)


罠2:透明 × VR = ソート破綻(チラつき・消える)

VR の透明は 非VRの倍の難易度。 発生しやすいもの:

  • 水面
  • ガラス
  • 炎・煙
  • フェード系エフェクト

原因は非常にシンプル:

  1. 左右の目でカメラ位置が少し違う
  2. 透明の描画順は カメラからの距離で決まる
  3. 左右で順位が変わる
  4. → チラつく / 消える / 奥が見えない などの破綻が発生

Three.js でも Unity でも同じ問題が起きる。


→ 解決策:透明を“透明で作らない”

VR では透明は禁忌。代わりに:

  • Additive(加算)
  • AlphaClip(1bit透明)
  • Fresnel(縁だけ光らせる)
  • Emissive の光で誤魔化す

“不透明を透明に見せる” という発想が、VR 向けシェーダーの王道。

3. multipass と reflection の罠

Reflection Probe や planar reflection は、 シーンをもう一度レンダリングする仕組み。

VR ではこれが凶悪になる:

  • 左目で1回
  • 右目で1回

さらに reflection / multipass が加わると…

→ 片目×2 × reflection = 4回描画 → blur / multipass があると 6〜8回 描画も普通に発生

結果: 平面では動くのに VR だけ激重になる典型パターン。


→ 絶対に避けるべき実装

❌ リアル反射の水面(planar reflection)

VR で使うとフレームが落ちて酔う。

❌ multipass blur 炎(glow / bloom / godray 系)

1パス増えるだけで VR では倍々ゲームで重くなる。

❌ SSR(スクリーンスペースリフレクション)

左右の視差で破綻しやすいうえに超重い。


→ VR は “リアル” を捨てる:嘘が上手いほうが強い

VR での正解は、 反射・透明・光を “偽物で上手く誤魔化す” こと。

代表的な手法:

  • キューブマップ1枚で反射っぽく見せる
  • 加算(Additive)で雰囲気だけ作る
  • Fresnel で光の縁を足して立体感を出す
  • 頂点アニメーションで“動いてる感”を演出

VR は “嘘の演出” が本当に強い。

4. VR で強いシェーダーの作り方(原則5つ)

VR のシェーダーは “軽い・安定・破綻しない” が最優先。 そのために守るべき原則は、実質この5つだけで十分。


原則1:頂点で動かす(vertex animation)

VR では fragment が最も重い。 なので、動きはすべて頂点で作るのが基本。

  • 炎の揺れ
  • 水面の動き
  • 風で揺れる草

→ sin / noise / offset は頂点でやれ → fragment は “色をつけるだけ” にする

これだけで負荷が劇的に減る。


原則2:テクスチャ1枚で決める(VR はレイヤー禁止)

VR は複数テクスチャや複雑な UV 操作が苦手。

特に危険なのは:

  • 2枚以上の noise の合成
  • uv に time を2回以上混ぜる処理
  • 流体っぽい multi-layer アニメーション

→ 「noise 1枚を回す」これが最強で最効率。

嘘でも “それっぽく見えれば勝ち” が VR の正しい考え方。


原則3:透明は避けて、擬似表現で作る

VR の透明はソート問題で破綻しやすい。

→ 透明 = 禁忌。 → でも透明っぽく“見せる”なら問題ない。

代わりに使うのは:

  • Fresnel(縁に光)
  • Emission(発光)
  • AlphaClip(1bit透明)

特に AlphaClip は軽くて強い。 “ガラスっぽい何か” はこれだけで十分作れる。


原則4:反射は fake(キューブマップ)で済ませる

VR で反射をリアルに取るのは自殺行為。

避けるべき:

  • planar reflection
  • SSR(スクリーンスペースリフレクション)
  • probe を毎フレ更新する仕組み

代わりに:

  • 静的 cubemap(環境マップ)1枚で反射っぽく見せる
  • Fresnel + 色補正で“水っぽさ”を出す

リアルより軽さ。 VR の反射は 99% “嘘” で作るのが正解。


原則5:左右の目で結果が変わる処理は禁止

VR は“カメラが2つ”ある。

そのため、以下の処理は 左右で結果が変わりやすい=破綻しやすい。

  • depth をそのまま使う
  • screenUV(スクリーン空間)
  • viewDir を使った計算(特に反射・屈折系)

→ 左右で値がズレて チラつき / 二重像 / ゆらぎ が出る。

対策:

「世界基準」または「ローカル基準」で計算する (worldNormal, worldPos, localPos など)

screen space ではなく world space / vertex space に寄せるのが安全。

5. WebXR 経験者が最強になる理由(lain向け)

Three.js + WebXR で積んできた苦労と実戦経験は、 Unity XR でそのまま武器になる。

理由は単純で、XR で起きる問題はエンジンが違っても本質が同じだから。


揺れ / 波 / 透明 / 発光 の “コスト感覚” が身についている

VR で重い処理、軽い処理のラインを WebXRで体に叩き込んでいる。

  • fragment が重いと即落ちる
  • vertex で動かすと軽い
  • 透明はソートで破綻
  • 発光・加算・Fresnel は強い

→ Unity XR でも全く同じ。


“姿勢(absolute rotation)” を正しく扱える

WebXR は姿勢情報が常に 絶対値で来る。 VR のカメラ・コントローラでも全く同じ。

  • multiply ではなく set
  • world 空間の扱い
  • forward ベクトルの信頼性

→ Unity の XR Origin と親子構造でも同じ発想が必要。


depth / screen space の罠に慣れている

WebXR は depth や gl_FragCoord を使うと左右で破綻する という経験を嫌でもする。

Unity XR も完全に同じ。

  • depth ベースの透明 → 死
  • screenUV → 左右でズレて点滅
  • viewDir → 二重像の原因

→ “使える空間 / 使えない空間” の感覚は XR 開発の核心。


multipass の負荷感覚が身体レベルである

WebXRは GPU が弱いデバイスも多いため、 multipass の重さを痛いほど理解している。

Unity XR でも:

  • blur
  • bloom
  • SSR
  • planar reflection

これらは 全滅。

→ lain は最初から避け方を知っている。


ステレオで起こる透明ソートの破綻を経験済み

WebXR の透明は地獄。 Unity XR も全く同じ地獄。

  • 左右の距離差でソート順が変わる
  • 透明のメッシュ同士が干渉する
  • VRでしか起きないチラつき

これを理解している開発者は本当に少ない。


つまり、WebXR の地獄を抜けた lain は XR で最強クラス

Unity XR の情報は圧倒的に不足している。 だからこそ、WebXR の経験者は そのまま最強の XR 技術屋になる。

lain はすでに:

  • Three.js
  • WebXR
  • Unity
  • シェーダー基礎
  • カメラ・当たり判定・空間理解

ここまで全部揃っている。

普通の Unity 初心者では絶対に届かない領域。

6. まとめ(この記事のゴール)

VR / XR のシェーダーで絶対に意識すべきポイントは次の通り:

  • ステレオ描画で負荷は常に2倍になる
  • 透明は破綻しやすいため、擬似透明で表現する
  • multipass / reflection(planar / SSR)は禁忌級の重さ
  • 動きは頂点で作る・テクスチャは1枚で完結させる
  • depth / screenUV / viewDir は左右でズレが出てチラつく
  • WebXR の経験はそのまま Unity XR の実戦力になる

これを理解しておけば、 VRでも水面・炎・発光を“安定して動くシェーダー”として実装できる。

あとがき

この全6回のシリーズは、
“シェーダーを知らない” ところから
“Three.js と Unity の両方で読み書きできる” ところまでを
最短で到達するためのカリキュラムだった。

最初は単なる興味から始まったかもしれない。
GLSL も HLSL も難しく見え、
GPU が何をしているのかもよくわからなかったはずだ。

でも、頂点・UV・行列・時間・光 というシンプルな原理を押さえれば、
水面・炎・発光・揺れ・透明といった
“ゲームの見た目を決めるコア表現” を
自分の手で作れるようになる。

そして最終回の XR 編。
ここまで来ると、
単に「動くシェーダー」ではなく
VR という特殊環境を理解した上での“実戦的な選択” ができるようになる。

これはもう、初学者の領域ではない。
クリエイターとしての判断 ができる段階だ。

Three.js の WebXR で積んだ経験、
Unity で積み上げた試行錯誤、
そしてこの6回で学んだ基礎と構造が合わさって、
lain は“二刀流だけではなく XR に強いシェーダー書き”になった。

この知識はブログだけでなく、
今作っている Unity の世界にも、
これから作るすべての表現にも活きてくる。

シェーダーは終わりではなく、
これから表現の幅を広げるための 入口 だ。

これを武器に、
次はあなたの世界を自分の色で彩っていけばいい。

シェーダー初心者入門(全6回)総まとめ

第1回:シェーダーとは何か?(理論編)

GPU が三角形をどう描くか、
Vertex / Fragment の役割、
モデル → ワールド → ビュー → 射影行列の流れを理解する。
→ シェーダーは「見た目を決める最終工程」だと認識。


第2回:Three.js(GLSL)で最小シェーダーを書く

RawShaderMaterial を使って、
頂点を sin 波で揺らす・色を time で変える。
→ GPU で“動かす”感覚を掴む。


第3回:Unity(HLSL)で同じ処理を書く

ShaderLab(Properties / SubShader / Pass)を理解しつつ、
GLSL と同じロジックを HLSL で再現。
→ GLSL ↔ HLSL の対応が見える。


第4回:Three.js vs Unity – シェーダー構造の横並び比較

attribute / varying / uniform が
appdata / v2f / Properties にどう対応するかを整理。
→ 二刀流の脳が完成。


第5回:テーマ別(波・水面・炎・発光)

sin / noise / depth / Fresnel の4本柱で
水・炎・発光といった定番表現を再現。
→ SimpleWater など既製シェーダーの構造が読めるようになる。


第6回:VR / WebXR / Unity XR の実戦知識

ステレオレンダリングの負荷、
透明のソート破綻、
multipass と reflection の禁忌、
VR で安全なシェーダーの原則5つをまとめる。
→ XR で破綻しない“実戦レベル”の判断力を獲得。


全体を貫く一番重要なこと

シェーダーは複雑に見えても本質はシンプルで、

  • 頂点をどう動かすか
  • 色をどう決めるか
  • 光とカメラをどう扱うか

この3つの組み合わせにすぎない。

Three.js で学んだ基本、
Unity で積んだ実装、
そして WebXR で得た “負荷と破綻の感覚”。
これらすべてが、
VR / XR を含むすべての表現に直結するスキルになった。