こんにちは、クラスター社のスタジオチームのn_mattun(まっつん)です。
普段はclusterを用いたイベントの快適な体験環境とイベント進行環境を作るためであれば
人力/ハード/ソフトと技術領域は問わず、お助けになれるようなことは色々と何でもやってるマンです。
この記事はクラスター「Advent Calendar 2025」 18日目の記事で、昨日の記事「連載:ClusterMUSICJAMの照明演出はどうやっていたのか(実装編)」の続きにあたります。
※今日は「検証・運用編」としたかったのですが、検証分までしか書ききれませんでした...
検証方法
さて、いよいよ道具が出そろったので検証していきます。
改めて手元にある道具を記しておくと
- Artnetの任意のindex要素に対して0~255の好きな値を送れる照明制御アプリ
- 1に反応して任意の色データを発色してくれるお手製アプリ
- 色データに反応して舞台照明のような発色をしてくれるシェーダー
があります。
基本的な検証フローは
1からデータを送る
↓
2の座標上に1のデータが期待通りの座標に期待通りの色で発色されていることを確認
↓
3の照明シェーダーが仕込まれているワールドデータをcluster上にアップロードし、
そのワールドで実際に画面共有を行って期待通りの発色や動きがなされることを確認
という感じなのですが、注意しておかなければならないポイントとして、期待している制御通りに動いてくれるかどうかはもちろん大事なのですが、さらにその制御結果が本物の舞台照明のように動いているように見えるかが最も大事なことです。そこの品質担保も気を付けつつ検証を進めていきます。
実物の舞台照明はじわっと光る、じわっと動く
何色でもいいのですが「無灯状態の照明を最大まで光らせる」みたいな操作を行った場合、実物の舞台照明はLED照明のように一瞬で最大発色にはならず、0.x秒くらいの時間をかけてじわっと光っていきます。(もちろんLEDだって厳密には一瞬ではなく、最大発色になるまではミリ秒単位で変化しているはずです)
同様に、照明の首振り機構を使って光源の向きを正面から上方向に動かす、みたいなケースがあった時に、実物の照明はモーター駆動なので「初速は遅い」「スピードが乗ってだんだん速くなる」「目的の位置に近づいたらからだんだん遅くする」「目的の角度に達したら止まる」という変化になっているはずです。
一方、照明制御アプリから「最小値から最大値にする」みたいな操作を行った場合、
その値は 【0 →(次フレーム)→ 255】 で一瞬で変わってしまうので、ここに何も対策を打たないままだと、例えば首を左右に振り続けるような照明の動きを出したい場合に明らかにカクついた動きになってします。
で、この問題に関してはあらかじめ想定できていたので、色データ発色アプリ内でArtnet値を受信したらそのデータを即時で色に変換して出すことはせず、間にトゥイーンライブラリを噛ませることで演出要素に応じて自然に見えるような調整ができるようにしています。
色の誤差と戦う
色データ発色アプリ内で作った色は画面共有機能を通じてclusterに送られるわけですが、画面共有機能で映っているものは一般的なストリーミングで送出している動画データです。で、動画データということは当然、何らかの動画フォーマットに即して変換が行われており、その変換結果や、見ている端末の回線状況やスペックに応じて画質が変わります。
画質が変わるということは、それはつまり色が変わるということです。
ということは何が起こるのかというと、、、そうです。状況によってデータ送出時点とデータ受信時点で欲しい値が変わるということです。
というわけでここからの解説は、この色の変化(データ変化)に対しての対策を書き連ねていきます。
ちなみにこの色誤差は肉眼では判断ができないので、出てる色が期待値かどうかを判断するには、色テーブルを画面共有してる状態のcluster画面を用意して、clusterスクリーンにマウスを当て、さらにマウスカーソル上の色を#RRGGBBで表示してくれるアプリを駆使して色コードを拾って、正しいかどうかを見定める...というもはやデジタルなんだかアナログなんだかわからないような検証アプローチを行っていました。
色がタイル外に滲んでくる
まずわかりやすい色変化の例。隣合っている色タイルがある場合、そのタイルの境界付近はお互いの色が混ざり合っているような色味になります。なので「これくらいの大きさのタイルだったら色はにじんでこないだろう」という安全圏を見定めて、シェーダー側で色を拾う際はタイルのド真ん中の色を拾うようにしています。
なんか色の変化量がリニアカーブじゃない
色をスポイトで拾いながら送出値の変化を試していると、真っ黒や真っ白など、極端な色に近い値付近で変化を出そうとすると変化量が少なく、逆に中間色に近い値付近で変化かけると変化量が大きくなったりと、どうも色の変化がリニアカーブじゃない状態であることに気が付いたのですが、これはどうやらシェーダー側で色を拾った時点でタイル色にガンマ補正がかかった結果の色になっていることがわかったので、色を拾ったらシェーダー内その値をリニア補正をかけて送出時のRGB値に戻す処理を仕込んでいます。
白が強い、黒は弱い
これはわりと検証後半で気付いたのですが、発色は黒(#000000)に近ければ近いほど他の色の影響を受けやすかったり、黒のままでも値が#0100001とか#020102..みたいな感じで微妙にブれたりしていたので、送出する時の色データのデフォルト値は#000000から加算するのではなく、#FFFFFFから減算する作りにしています。
また、送出する演出データによっては0-255のすべてではなく0-200くらいの範囲でも役割を果たすような場合は、色生成アプリ側でそもそも黒に近くなるような値を使わないようにするなど、動画化された際に勝手に変化が起こりにくい色をなるべく使うようにしています。
色がブれても大丈夫な状態にしておく
照明の角度調整のような光線が伸びれば伸びるほど角度の変化量は目に見えてわかってしまうものなど、色誤差が許されないパラメータに関しては、色がブれても狙ってる値を取得できるような状態が必要です。
で、色誤差に関しては#000000が#555555になる、というよう大きな振れ幅はさすがに起こりえないので、その手の値が1でもズれたら困るパラメータに関しては色生成アプリ側とシェーダー側とでそれぞれ
- 色データアプリの段階で色を256諧調ではなく32諧調(0,7,15,23...255)など、粗い諧調で発色できるようにもしておく
- シェーダー側では
・0x00~0x07:すべて0として扱う
・0x08~0xFF:すべて1として扱う
・0x10~0x17:すべて2として扱う
という、色のにじみ幅で想定できる範囲の値だったらすべて同じ値として扱うような処理を入れたりしました。
ただ、この処理系統はvol1の頃には気付けなかったので、未実装の頃のライブの動画を見返すと、静止していなけれればならない照明がプルプルと震えるような動きになっていることが確認できたりします(当時の出演者の方々にはやや不完全な形での提供になったことをこの場をお借りしてこっそり謝罪させていただきます...)

これは「光線の太さ」という値が色誤差によって変わった結果、実際にプルプルしてしまっている照明の様子です。前述の通りストリーミング時の回線品質によってこの問題をゼロにすることはムズいのですが、Vol.4あたりではこの問題はほぼ気付かないレベルにまでは抑え込めてたんじゃないかとは思っています。
明日はまとめ
ということで、このように様々な問題点を検証で見つけるたびに修正をするという感じで伴奏で回を重ねておりました。最後の章では「運用と次に向けて編」ということで、このスタイルの作り方をすることのメリットやデメリットなどの話を中心にしながらまとめに入れればいいかなと考えております。
というワケで次回、最終回、お楽しみに!!