物理照明卓で Unity のクリスマスツリーをライティングしてみた
この記事は,Akatsuki Advent Calendar 2021 の21日目の記事です.
昨日は @sejimhp さんの「DCGAN(深層畳み込み敵対的生成ネットワーク)のコードを追ってみる」でした。
はじめに
クリスマスまであと数日。なので、クリスマスツリーのライトアップ をUnity でします。
Unity の Timeline でライトアップのアニメーションを作っても面白くないので、物理照明卓(照明用コントローラー)から Unity のクリスマスツリーのライトアップを制御しようと思います。
舞台やステージの照明では、照明卓から DMX512-A という制御信号で、一般照明や LED ライト、ムービングライトなどの制御しています。
この照明制御の信号読み取って Unity に送り、照明卓から Unity 内の照明も一緒に制御をしようという作戦です。
構成
ハードウェア
マイコン: ESP32 DevKitC
インターフェイスIC: LTC485CN8
照明卓: SCENESETTER48(AMERICAN DJ)
マイコンとインターフェイス IC は秋月電子で仕入れました。コネクタ含めて材料費2000円ぐらいです。 照明卓に関しては逸脱の誤家庭ならあるものなので入手先は省略します。
マイコンは、ESP32 だと UART が3つ使えるのと、Wi-Fi モジュール搭載しているので直接ネットワーク経由で Unity に送れるので採用しました。 Arduino の場合、別途 Ethernet シールドが必要なのと、場合によってソフトウェアシリアルを使う必要があります。
インターフェイスIC は RS485 から RS232 に変換できる IC であれば他のものでも問題ないです。
動作環境
OS: Windows 10
Unity: 2020.12f1 (HDRP)
新しいのを使いたいミーハーな気持ちで物理ベースのライティング技法がサポートされている HDRP 環境で動作確認をしています。
物理照明卓からライトを制御するのに HDRP の環境である必要はありません。Built in render pipeline の環境でも動作します。
照明制御信号の受信
DMX512-A の概要
舞台やステージで使われる照明機器は、DMX512-A と呼ばれる ANSI で定義されたデジタル信号で制御されてます。 DMX512-A の電気信号は EIA-485 の仕様と同じで 250kbit/s のシリアル通信で制御を行ってます。 また、照明卓から照明機器への接続はデイジーチェーンで接続していきます(実際は途中でスプリッターを挟むことが多いです)。
DMX512-A は比較的単純で且つ頑丈なシステムが特徴で、制御に必要な信号を送信するだけで誤り補正や制御機器とのコネクションなどをしていません。つまり、照明卓は照明機器に対して broadcast で制御信号を送信し続けている状態です。
DMX512-A の詳細
DMX512-A では最大 512ch のパラメータを制御できます。また通信は 250kbit/s で行うため、1bit は 4μs 間の High/Low で表します。
DMX512-Aの電気信号の 仕様 を簡単に表にまとめると次の構成になってます
名称 | 長さ | ||
---|---|---|---|
#1 | Breake | 88μs ~ | Low レベル |
#2 | Mark After Break | 8μs ~ 1s | Highレベル |
#3 | Start Bit | 4μs(1bit) | Low レベル |
#4 | Start Code | 32μs(8bit) | |
#5 | Stop Bit | 8μs(2bit) | Low レベル |
#6 | Mark Time Between slots | 0~1s | |
#7 | Start Bit | 4μs(1bit) | High レベル |
#8 | Channel Data | 32μs(8bit) | |
#9 | Stop Bit | 8μs(2bit) | Low レベル |
Start Bit, Channel Data, Stop Bit (#7 ~ #9) の 11bit で 1channel 分のデータを構成しています。
参考
DMX512-Aの仕様書
https://tsp.esta.org/tsp/documents/docs/ANSI-ESTA_E1-11_2008R2018.pdfTamaTechLab さんのホームページ
http://www.tamatech.co.jp/tamada/index.php
DMX512-A の読み込み
DMXの信号は比較的簡単な構造をしているため、信号受信のプラグラムを自作しても良いのですが、今回こちらのライブラリを使用しました。 github.com
Arduino 向けのライブラリだとDMXSerialなどがあります。 github.com
受信回路
制御信号は RS-485 の上で通信が行われているので、マイコンで受け取るには RS-232 に一度変換させる必要があります。
そのため、下の回路図の様にインターフェース IC を使って RS-232 に変換させ、UART2(GPIO16, GPIO17) で受信しています。
(回路図に起こす必要もないぐらいシンプルな構成です)
ESP32 - Unity 間の通信
ESP32(マイコン) から Unity に DMXの信号を送る方法として、JSON 形式で送信する方法もあるのですが、 今回は実際の照明イーサネットプロトコルである Art-Net*1 を使いました。 せっかく照明卓から照明制御の信号を読み取ってるのでネットワーク通信の部分も実際の照明のプロトコルを使いたいという気持ちです。
Art-Net とは
Art-Net は ネットワーク上で DMX512-A の信号をやり取りするためのプロトコルで、UDP (Port: 6454) を使ってデータを送信を行っています。 DMX の信号は Operation Code=0x5000 の ArtDmx でデータの送受信を行い、機器間の通信は Broadcast もしくは Unicast で行います
ArtDmx のパケットの構成は次の様になっています
Index | Description |
---|---|
0~7 | Identification ID |
8, 9 | Operation Code |
10,11 | Protocol Version |
12 | Sequence ID |
13 | Physical |
14,15 | Universe |
16,17 | Length |
18~ | Data |
UDP(Port: 6454) で ArtDmx (OpCode=0x5000) を Broadcast で送信/受信をすれば、Art-Net の形式で DMXの制御信号を送れることになります。
※ 厳密に言うと Art-Net では ArtDmx 以外にも ArtPoll/ArtPollReply で接続されている機器の認識を行っているのに加え、細かい仕様がまた別にあります。
Art-Net のデータ形式の確認方法ですが、WireShark のデフォルトで Art-Net の構造を確認することができます。
Art-Net の送受信
Art-Net の送受信ですが、今回 ESP32 と Unity で下のライブラリを使いました。
また ESP32 のソースコードは以下です
#include <Arduino.h> #include <ArtnetWifi.h> #include <dmx.h> #include <ArtnetWifi.h> #include "./DmxToArtnet.h" int readcycle = 0; ArtnetWifi artnet; const int DMX_LENGTH = 512; void ConnectWifi() { WiFi.begin(WIFI_SSID, WIFI_PASSWORD); Serial.print("connecting"); while (WiFi.status() != WL_CONNECTED) { Serial.print("."); delay(100); } Serial.println("WiFi connected"); } void setup() { Serial.begin(115200); ConnectWifi(); artnet.begin(ARTNET_ADDRESS); artnet.setLength(DMX_LENGTH); artnet.setUniverse(0); DMX::Initialize(input); } void loop() { if(millis() - readcycle > 50) { readcycle = millis(); for (int i = 0; i < DMX_LENGTH; i++) { artnet.setByte(i, DMX::Read(i + 1)); } artnet.write(); } }
余談
DMX 信号から Art-Net に変換する機械は既製品として売っていたりします。
Unity のライトアップ
照明卓の信号を UDP で送れる様になったのでようやく Unity でクリスマスツリーのライトアップの作業ができます。
Unity での作業の前に一番大事なクリスマスツリーのモデルを用意しました。誰がどう見てもローポリのクリスマスツリーです。
Unity 上ではこのクリスマスツリーのモデルとライティングで使うライトとマテリアルを HDRP のシーン上に配置しました
スクリプトで Light と Material の intensity, color の値を変えています。 この返るスクリプト内で送られてきた Art-Net のパケットの値を使うことで、 照明卓で操作したものがリアルタイムで Unity に反映されてクリスマスツリーがライトアップされるようになります。
// Dimmer.cs public class Dimmer : MonoBehaviour { [SerializeField] private int universe; [SerializeField] private int startAddress; [SerializeField] private DmxData dmxData; [SerializeField] private Light light; [SerializeField] private float intensity; private void Update() { light.intensity = dmxData.Dmx[universe - 1][startAddress - 1] / 256f * intensity; } }
// RgbwMaterial.cs public class RgbwMaterial : MonoBehaviour { [SerializeField] private int universe; [SerializeField] private int startAddress; [SerializeField] private DmxData dmxData; [SerializeField] private Material material; [SerializeField] private Light light; [SerializeField] private float intensity; void Update() { float red = dmxData.Dmx[universe - 1][startAddress - 1] / 256f; float green = dmxData.Dmx[universe - 1][startAddress] / 256f; float blue = dmxData.Dmx[universe - 1][startAddress + 1] / 256f; Color color = new Color(red, green, blue); color += Color.white * 0.5f * dmxData.Dmx[universe - 1][startAddress + 2] / 256f; light.color = color; material.SetColor("_EmissiveColor", color * intensity); } }
また、照明卓で Chase (アニメーション) を作れるので、Unity 側でアニメーションファイルを作成しなくて済みます。
照明ソフトからのコントロール
物理照明卓の DMX信号を Art-Net 経由で Unity に送ってるので、直接 Art-Net 出力ができる照明ソフトであれば物理照明卓を使わなくても Unity のライトを制御ができます。 つまり、ESP32 で DMX から Art-Net しなくて済む上に、簡単に試せる。(DMX の信号説明は何だったんだ...)
照明ソフトの QLC+ を使っても同じ様に Unity のライト制御ができますが、物理ボタンが無いのでリアルタイムで操作するなら midi pad とかを使わないと辛い欠点があります。
おわりに
物理照明卓/照明ソフトからリアルタイムに Unity のライトを制御できるようになりました。
ゲームなどに使える技術ではないですが、リアルタイムで Unity のレンダリングが必要な時にライトの制御方法の一つになると思います。
また、照明卓/照明ソフトにあるプリセットやエフェクトなどの機能が使えます。 元々、ライトを操作することを前提に作られているだけあって、楽にそれっぽいアニメーションが作れます。 ただ、照明卓/照明ソフトの操作を覚えるデメリットもあるのでメリットだけではないです
Unity で ArtNet を扱う内容について Qiita にもかいています。また、Unity で ArtNet を扱うためのコードを GitHub で公開しています。