2023年4月28日(金)から4月30日(日)まで、テクニカルクリエーションイベント「SESSIONS in C4 LAN 2023 SPRING」がツインメッセ静岡とオンラインのハイブリッドで開催された。

本記事では前編として、全3日間のイベントの中から、4月29日(土・祝)に行われたセミナー「VRクラブ空間におけるDJパフォーマンスとイベント運営 by DJ SHARPNEL」「レイマーチング0から1 by 0b5vr」の模様をレポートする。

記事の目次

    関連記事

    数キロバイトのプログラムに心血を注ぎ込む! デモシーンの魅力とコンペティション受賞作を紹介〜SESSIONS in C4 LAN 2023 SPRING(1)

    Information

    SESSIONS in C4 LAN 2023 SPRING

    開催日時:2023年4月28日〜30日
    場所:ツインメッセ静岡
    sessions.frontl1ne.net

    VRDJのパフォーマンスが届くまで

    「VRクラブ空間におけるDJパフォーマンスとイベント運営」にはDJ SHARPNEL氏が登壇。近年ではVRイベントが盛り上がりを見せる中、バーチャルな肉体でDJをするためのテクノロジーや運営手法を解き明かした。

    ▲DJ SHARPNEL氏は2017年に現実での音楽活動を終了し、現在はVRDJで活動中。セミナーはVRDJと同様にアバターで出演した

    本セミナーでは「VRDJ」という言葉について「仮想空間の中にクラブを作って、アバターを使ってDJをすること」と定義。DJ SHARPNEL氏によるとVR空間でDJイベントが開かれるようになったのは2018年頃からだという。

    それ以前にもオンラインDJイベントは行われており、MMORPGなどのオンラインゲーム内でも賑わっていたが、そのムーブメントがVRChatやclusterなどのVRSNSプラットフォームへ広がっていくかたちで一般化した。

    さらに2020年の新型コロナウイルスの流行による音楽イベント禁止の影響を受けて参加者が急増。同時にVRSNSだけではなく、Twitchなどのライブ配信プラットフォームでの映像出演も増えていった。

    DJ SHARPNEL氏はVRDJの長所について、気に入ったアバターでDJができるためモチベーションが上がることや、場所の制限なく世界中から参加できることなどを挙げた。

    短所としては、参加するために機材や知識が必要でハードルが高いことや、参加者の通信環境やマシンの性能によって体験に差が出ることなどに触れたが、それらの課題は技術的な進歩を遂げれば解決できるはずだと展望を見据える。

    VRDJをオーディエンスに届けるためには、3つのプロセスを踏まなければならない。

    DJのパフォーマンスをデジタルに置き換える「量子化」、モーションデータをデジタルな身体で表現する「アバター化」、そしてイベントを楽しむ場所である「クラブ空間」を構築してVRDJを開催するまでに使われるテクノロジーを、それぞれ解説していこう。

    まず「量子化」のプロセスでは、DJの動きをデータに変換するためにモーショントラッキング技術を用いる。セミナーでは代表的な3つのシステムを取り上げた。

    Lighthouseは赤外線を発射する固定式ステーションを部屋に設置し、装着したセンサの反射によって動きを読み取る形式だ。空間全体で位置測定ができるため、演者は室内を動き回れる自由度の高さが特徴で、データの精度も高い。

    インサイドアウトトラッキングはヘッドマウントディスプレイ(HMD)から出る赤外線を用いており、外部のステーションを設置しないためコストは比較的手頃。Meta Quest 2やPlayStation VR2で採用されている。

    モーションセンサは体に装着した小型センサによって、動きのデータを取得する方式だ。VRの普及と共に「自分の体の動きをデジタル化したい」というニーズが増え、それに従ってモーショントラッキング技術の選択肢も広がってきた。演者は必要な精度や部屋の環境、予算などの諸条件を踏まえて、適切な技術を選ぶことができる。

    ▲HMDの種類も紹介。DJ SHARPNEL氏はValve Indexを使用している

    VRDJではHMDとコントローラによる頭と両手の3点トラッキングが一般的。VRSNSでパフォーマンスをする際にはDJ自身もVR空間に入るため、HMDの装着が推奨される。

    ただHMDを付けると視界がふさがれて、DJ機器の操作が難しくなってしまう。そんな「VRDJ手元見えない問題」の解決策として、DJ SHARPNEL氏は4つの方法を提案した。

    解決策1は「HMDをずらして着用する」。物理的な方法ではあるが、HMDをかけ直せば即座にVR空間へ戻れるという手軽さがメリットで、とくにVRSNSの出演時に役立つという。

    解決策2は「内蔵カメラで現実を見る」。HMDの前面には外の様子を確かめるためのパススルーカメラが付いており、そちらに切り替えればHMDを外さずにDJ機器を扱える。

    解決策3は「視界にVRDJソフトの画面を重ね合わせる」。HMDに映ったVR空間上にVRDJのソフト画面を表示させて、つねに見える状態にしておく方法である。楽曲選択はVR空間のソフト画面から行うというスマートな解決策だ。

    最後は「HMDではなくヘッドトラッカーを装着する」。ヘッドトラッカーをHMDの位置として認識させ、目の前に設置したディスプレイを見ながら操作をする。この場合はHMDを装着しないためDJ自身の没入感には欠けるが、現実のライブに近い環境のためパフォーマンスに集中できる。それゆえにVRDJライブ動画の撮影時にオススメの手法となっている。

    ▲なおDJ SHARPNEL氏は解決策4であるヘッドトラッカーを付ける方法でセミナーに出演した

    また、DJパフォーマンスでは繊細な指の表現が欠かせない。指を使ってカウントダウンをしたり、オーディエンスを沸かせたりと、様々な場面で手が活躍するため、できれば指1本1本の動きまでアバターで再現したい。

    その際にはフィンガートラッキング付きVRコントローラを使えば、指表現のデータ化が可能。近年登場したフィンガーセンサ付きグローブであれば指の曲げ角度まで認識し、より細やかな表現に対応できる。

    DJ SHARPNEL氏は「量子化」のまとめとして、VRDJでは音楽はもちろん、演者の身振り手振りも含めたパフォーマンスをデータ化することがポイントになると伝えた。

    VRイベントならではの魅力

    「アバター化」は、取得したデータをVR空間で活動するためのデジタルな身体に置き換えていくプロセスである。

    実際にアバターとして活動しているDJ SHARPNEL氏は「アバターは単なるキャラクターではなく、姿そのものが自分のアイデンティティになっていきます」と語り、アバターを見て自分自身だと思うようになる瞬間がやってくると実感を述べる。

    ▲アバターはBlenderやMaya、3ds MaxなどのDCCツールによって作られているが、近年ではVRoid Studioのように既存のパーツをカスタマイズするソフトウェアも登場してきた

    アバター制作はクリエイターが販売している3Dモデルをベースに、演者が独自のカスタムを加えていく手法が一般的だ。

    DJ SHARPNEL氏のアバターも、オリジナルアバターモデルを基に、Unity上で色やテクスチャ、衣装をカスタマイズして制作された。最終的には3Dアバター向けのファイル形式であるVRMや、各プラットフォームの形式に設定して利用する。

    DJのパフォーマンスをアバターに適用させるテクノロジーも複数存在する。

    VRSNSの場合はモーションをアバターへ変換する機能が各プラットフォームに標準搭載されており、自分自身の身長や何点でトラッキングされているのかを入力すれば、そのまま動かすことができる。

    VRDJライブ動画やUnityやUnreal EngineによるVR空間映像の撮影では、VirtualMotionCaptureというアプリケーションが便利である。頭や手、腰などで異なるデバイスを適用できるため細やかな制御が可能で、UnityやUEとの連携も容易。モーションのアバター反映に必要な機能が一通り揃っている。

    パフォーマンスを届けるための「クラブ空間」では、VRDJがどのような場所で開催されるのかを解説。VRSNSが一般的ではあるが、ライブ配信プラットフォームを通じての映像出演や、現実のクラブで映像を投影するケースなども増えてきた。

    VRSNSの場合は、Unityのワールド作成機能を使ってオリジナルのクラブ空間を構築。そのデータをアップロードして参加者たちを集めて、全員で一緒に盛り上がっていく。

    プラットフォームによっては独自のワールド作成機能をもち、例えばオーディエンス自身がオブジェクトを持ち込んでワールドに変更を加えるなど、様々な楽しみ方ができる。ただしいずれも多くのユーザーが異なる環境から接続するため、ワールド作成時には負荷や互換性を考慮しなければならない。

    映像配信ではゲームエンジンを用いてクラブ空間を構築をローカルPCに構築。空間内にカメラを配置して、スイッチングして撮影することで、よりダイナミックな映像をユーザーに届けられる。こちらはVRSNSとは異なり、自分のPC環境でさえ動けば問題ないため映像クオリティに注力できる。

    セミナーの後半ではVRクラブ空間ならではのイベント運営についても言及した。DJ SHARPNEL氏はVRで行われるイベントは必ずしも現実の代替ではないことを意識した方が良いと語る。

    例えば現実のクラブではイベント開始直後にオーディエンスが帰ってしまうと、DJとしてはショックを受けてしまうものだが、VRクラブの場合はむしろそれが普通なのだという。VRクラブのイベントは無料であることが多く、移動の制約もないことから、オーディエンスは様々なイベントを気軽に渡り歩くことができるからだ。そういったVRクラブならではの特性を把握しておく必要がある。

    開催されるイベントの種類も様々。コンサート型はDJのパフォーマンスや演出を楽しむことを、パーティ型はオーディエンス同士の交流を主眼に置いている。

    アミューズメント型はオーディエンスにも表現や演出に加わってもらう形態であり、例えばVR空間で全員が一緒に物を作り上げるなど、VRだからこそ実現できる楽しさが詰まっている。イベントの主催者がどのような雰囲気を目指すのかを明確に決めておくことが重要だ。

    最後にDJ SHARPNEL氏は「皆さんと一緒に楽しんでいただけるようなイベントをやっていますので、興味がありましたらぜひ参加していただいたり、DJをしていただけると嬉しいです」とメッセージを伝えた。

    レイマーチングのコードを公開&解説

    「レイマーチング0から1」にはライブコーディングVTuberの0b5vr(オブザーバー)氏が登壇。デモシーンで人気の高いテクニックであるレイマーチングを駆使して、華麗な3Dグラフィックスを表現する方法を、初心者に向けてわかりやすく伝授した。

    今回は球体を描画することを目標に、プログラミングがわからない人でもレイマーチングの概念が理解できるように解説。まずはレイマーチングに必要なものとして、「Webブラウザ」「ベクトルの知識」「プログラミング」「GPU」の4つを取り上げた。

    レイマーチングは描画負荷がかかるため、GPUの性能は高ければ高いほど良いが、0b5vr氏は「ノートパソコンのオンボードグラフィックであってもある程度はできてしまうので、一回試してみてください」と背中を押す。

    本セミナーではWebブラウザ上で無料で使用できるtwigl.appでコードを書いた。コードはプログラミング言語のGLSLを用いており、シェーダ言語あるいはプログラマブルシェーダのカテゴリに属することなども丁寧に説明した。

    ▲コードを料理に例える一幕も

    レイマーチングでは「画面上にあるピクセルから飛ぶレイが物体と交差しているか否か」によってグラフィックスを描画していく。ピクセルは画面上にある1点の色情報であり、レイは始点と向きという2つの情報がペアになったものだ。

    各ピクセルはそれぞれレイをもち、それが物体と交差しているかを判定。レイが物体と交差する場合は物体を、交差していない場合は背景を描き、全ての交差判定が終わると3Dグラフィックスが完成する。

    ▲レイマーチングの作品を多数手がけるkaneta氏によるチュートリアル。左上から右下まで順番にレイが飛んでいくアニメーション

    セミナーでは0b5vr氏が書いた65行のコードを読み、それぞれがどのような効果をもたらすのかを解説した。その中でも肝となるレイマーチングのテクニックについて紹介しよう。

    precision highp float;
    
    // 開始からの時間(秒)
    uniform float time;
    
    // 画面の解像度。例えば、 `vec2( 1920.0, 1080.0 )`
    uniform vec2 resolution;
    
    // プログラムが終了時、ここに最終的に入っていた色が出力されます
    // RGBAで [0, 1] の範囲
    // 例えば、 `vec4( 1.0, 0.5, 0.0, 1.0 )` でオレンジが出力されます
    out vec4 outColor;
    
    // 「距離関数」
    // 空間上の位置を渡すと、空間内の物体までの最短距離を返す関数
    float distFunc( vec3 pos ) {
      return length( pos ) - 1.0;
    }
    
    // 距離関数を用いて法線を算出する関数
    // いろいろな方法がある中の1手法です
    vec3 normalFunc( vec3 pos ) {
      vec2 d = vec2( 0.0, 0.0001 );
      return normalize( vec3(
        distFunc( pos + d.yxx ) - distFunc( pos - d.yxx ),
        distFunc( pos + d.xyx ) - distFunc( pos - d.xyx ),
        distFunc( pos + d.xxy ) - distFunc( pos - d.xxy )
      ) );
    }
    
    void main() {
      // 画面上のピクセルの位置を (0, 1) の範囲で格納した2次元ベクトル
      vec2 uv = gl_FragCoord.xy / resolution;
    
      // 上で定義したuvを、画面中心を原点に・縦横比が1:1の座標系に変換する
      vec2 screenPos = 2.0 * uv - 1.0;
      screenPos.x *= resolution.x / resolution.y;
    
      // レイ(光線)の始点と向きを定義する
      vec3 rayOri = vec3( 0.0, 0.0, 5.0 );
      vec3 rayDir = normalize( vec3( screenPos, -1.0 ) );
      
      // レイマーチングを行う
      float t = 0.0; // 現在のレイの始点から探索位置までの距離
      float dist; // 直近の距離関数の結果
      
      for ( int i = 0; i < 100; i ++ ) {
        // 現在の探索位置を使って距離関数を実行、distに結果を格納する
        dist = distFunc( rayOri + t * rayDir );
        
        // 距離関数の結果を使って、探索位置を更新する
        t += dist;
      }
      
      // もし、直近の距離関数の結果が十分にゼロに近かった場合
      // レイが距離関数で表現された物体表面と交差したと判定する
      if ( dist < 0.01 ) {
        // 交差した場合、法線を可視化して描画する
        vec3 normal = normalFunc( rayOri + t * rayDir );
        outColor = vec4( 0.5 + 0.5 * normal, 1.0 );
      } else {
        // 交差しなかった場合、背景色として黒を描画する
        outColor = vec4( 0.0, 0.0, 0.0, 1.0 );
      }
    }
    ▲0b5vr氏が書いたコード

    レイマーチングでは距離関数(distFunc)を用いてレイを進行方向に探索し、物体と交差しているかを判定する。距離関数は空間位置を渡すと、最も近い物体の表面までの距離を返すという性質を持つ。

    ▲距離関数の結果を色で表したもの。ピンクの線は物体の表面に相当し、距離関数の結果は0。そこから離れるに従って値が大きくなる

    まずレイの始点に探索位置を定義する。そこから最も近い物体の表面までの距離だけ、探索位置をレイの方向に進ませる。これを繰り返して、最後の距離関数の実行結果が十分に小さい場合は、レイと物体表面が交差していると判定。逆に距離関数の結果が大きくなっていけば、レイと物体表面が交差しないと判定する。

    // レイマーチングを行う
    float t = 0.0; // 現在のレイの始点から探索位置までの距離
    float dist; // 直近の距離関数の結果
    
    for ( int i = 0; i < 100; i ++ ) {
    // 現在の探索位置を使って距離関数を実行、distに結果を格納する
    dist = distFunc( rayOri + t * rayDir );
    
    // 距離関数の結果を使って、探索位置を更新する
    t += dist;
    }
    
    // もし、直近の距離関数の結果が十分にゼロに近かった場合
    // レイが距離関数で表現された物体表面と交差したと判定する
    if ( dist < 0.01 ) {
    // 交差した場合、法線を可視化して描画する
    vec3 normal = normalFunc( rayOri + t * rayDir );
    outColor = vec4( 0.5 + 0.5 * normal, 1.0 );
    } else {
    // 交差しなかった場合、背景色として黒を描画する
    outColor = vec4( 0.0, 0.0, 0.0, 1.0 );
    }
    ▲0b5vr氏によるレイマーチングのコード
    ▲球の距離関数は、球の中心からの距離を球の半径で引くことによって求められる。今回は半径を1とした
    // 「距離関数」
    // 空間上の位置を渡すと、空間内の物体までの最短距離を返す関数
    float distFunc( vec3 pos ) {
      return length( pos ) - 1.0;
    }
    ▲0b5vr氏による距離関数のコード
    ▲これによって球体が描画できた。セミナーではそのほかにも、球体に色をつけたり、球体の数を増やしたりと、様々なコードを紹介した

    セミナー終了後にはイベント「Shader Jam」を開催。世界中から総勢18名の参加者がレイマーチングの手法なども扱いながら、ライブコーディングを披露し、大きな盛り上がりを見せた。

    ▲「Shader Jam」の様子

    配信アーカイブ

    TEXT_髙橋克則 / Katsunori Takahashi
    EDIT_小村仁美 / Hitomi Komura(CGWORLD)