UnityでVJをしよう！

[#VJアドベントカレンダー2024](https://adventar.org/calendars/9943) 9日目の記事です。

# 初めに
どうも、Unityを触るか漫画を読むか寝てるかしかしていない人です。
ブラックフライデーで金を使い過ぎました。破産寸前です。

この記事では、去年、2023年7月終わりくらいに行われた、Unity開発についてのお話をしようと思います。

# この記事の対象
- Unityに興味がある人
- UnityでVJをしてみたい人
- VJに興味がある人
- Unityで何かをしてみたい人
- C#に興味がある人

# 作ったソフトの紹介 (PR笑)
ちょっとだけ、私のソフトの解説を...
読み飛ばしてもらって構いません。

https://zect.booth.pm/items/4976418

こーんな感じのVJソフトを生み出し、販売してます。
今、私が実際の現場で使用しているのが、`mk2 v0.8`。開発開始当初はただの4mixしかできていませんでしたが、今では、実質8mix、ロゴ表示やらエフェクトやらをﾓﾘﾓﾘ！って感じのソフトになりました。
自信の成長を感じます。

## この記事で紹介するもの

https://x.com/Zect3279/status/1684143928386412544

こーんな感じのソフトです。
本当に初期の初期、v0.1のお話をします。

# 事の始まり。
さて、PRはほどほどにして、開発に関するお話をしていきましょう。

去年(2023)3月頃から、エンジニアの知り合いと「VJおもろ」！と言っており、それを外に少しずつ表に出していたところ、[新規 ﾎﾞｶｸﾗ](https://twipla.jp/events/570191 "ハロボカ vol.1")を主催しようとしていた極めて宣伝力の高いクリエイティブな方から、VJとしてのお誘いがあり、本格的にVJを始めることとなりました。
（某主催はアカウントを謎の力によって凍結されてしまったため、当時のDMが無い...涙）

そんなわけで、VJ初学者なりに、VJできないかな～と「free VJ software 2023」とかで言語と地域をアメリカにして調べ、片っ端からフリーソフトを使っていきました。

https://x.com/Zect3279/status/1681993412843823104

フリーソフトを使ったことがある人はわかると思います。
そう、あれらはロゴが定期的に表示されるんです。
そんなものを現場で使用するなど赦されるはずがありません。

結果、自分で作る、という結論に至りました。

https://x.com/Zect3279/status/1682028087889002496

# webで...（笑）
ということで、VJソフトを自作しよう！を考えましたが、いかんせん、そんな ~~(比較的)~~ 大規模なプロジェクトなど走らせたことがありません。

そんな、当時はwebでばっかり遊んでいた私は、webアプリでVJをしようとします。

当時のことなんて完全に忘れたので、結論を出しますが、
「OpenCVでVJなんてやるもんじゃない」
となりました。

そんな中、Unity製の2Dゲームに当時ハマっていた私は、Unityに目を付けました。
「なんか、できる気がする。」

Unityでの自作VJソフト的なsomethingは、TL上で観測していたので、試しに作ってみることにしました。

そんなわけで、無意識に避けていた数年前に挫折を経験したUnityというソフトに立ち向かうことを決意しました。

# Unity

:::note warn
Untiyのインストール、プロジェクトの作成方法がわからない方は、ぜひ、こちらの記事を...

https://qiita.com/Zect/items/ec2bb9aef65bf2555e29#unity%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB

この記事では3Dの解説をしていますが、VJソフトは2Dなので、プロジェクトテンプレートは`2D`を選択しています。
:::


ということで、Unityでソフトを作ることにしました。
開発に先立ち、
- ローカルのファイルを再生
- ファイルのdrag and drop

の2点を必須機能としました。

やはり、Qiitaは優秀、記事が出てきたので、コピペします（笑）

https://qiita.com/ReoNagai/items/7d80b9c0d13190569cea

https://qiita.com/broken55/items/f235497c7b4b2a46b926#unity%E5%A4%96%E9%83%A8%E3%81%AB%E7%BD%AE%E3%81%84%E3%81%9F%E5%8B%95%E7%94%BB%E3%82%92%E5%86%8D%E7%94%9F%E3%81%99%E3%82%8B

## とりあえずの加算合成

そして、複数の映像をmixできたらいいな～の気持ちで色々と調べ、この記事が出てきました。

https://qiita.com/Yothuba3/items/e147f5e6dd10a5031910

これを読むと、`videoPlayer`の映像をTextureとしてmaterialに流し込むことができ、そのTextureをShaderで処理することができる、という話を知りました。
ここから、`Properties`に`_Video1`と`_Video2`を生やし、それらを単純に加算するコードを記述しました。

一応、ここにコードを置いておきます。
ぜひ、参考に

```glsl
Shader "Custom/Output A"
{
    Properties
    {
        _Video1 ("Video 1", 2D) = "black" {}
        _Video2 ("Video 2", 2D) = "black" {}
    }

    SubShader
    {
        Tags {"Queue"="Transparent" "RenderType"="Transparent" }
        Blend SrcAlpha One
        // ZWrite Off
        Cull Off ZWrite Off ZTest Always

        // pass 1
        Pass
        {
            // Tags {"LightMode" = "UniversalForward"}
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_VERTEX_OUTPUT_STEREO
                // {
                float4 vertex : SV_POSITION;
                // };
            };

            sampler2D _Video1;
            sampler2D _Video2;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                float2 uv = i.uv;
                fixed4 colV1 = tex2D(_Video1, uv);
                fixed4 colV2 = tex2D(_Video2, uv);

                fixed4 col = fixed4((colV1.rgb + colV2.rgb), 1.0);

                return col;
            }

            ENDCG
        }

    }
}
```
まぁ、ちょっとだけ解説するとしたら、
大事なのは
- `Properties`
- `vert`の上にあるやつ
- `frag`の中

の3つです。
それ以外はおまじないです。とりあえず無視しましょう。
説明としては、上から順に、
- Textureの受け皿
- `frag`内で使うための変数定義
- Shaderを描く場所

です。

`frag`は、処理をする画像の全ピクセル分呼び出されます。
そして、`uv`には処理をしている座標が格納されています。
なので、`colV1`と`colV2`に`_Video1`と`_Video2`からそれぞれ取ってきて、そのrgbを取って、足しています。

てなわけで、初めてできたVJソフトはこれです！
なんと、2mixができる！！

https://x.com/Zect3279/status/1683100437518618625

## sliderでフェード

UnityにはSliderという便利なものがデフォルトで付いています。
なんと、0から1の小数を返してくれます！！
なので、こんな感じで足したり修正したりしてあげると、、、
```diff_glsl
Shader "Custom/Output A"
{
    Properties
    {
        _Video1 ("Video 1", 2D) = "black" {}
        _Video2 ("Video 2", 2D) = "black" {}
+       _Slider ("Slider", Range(0, 1)) = 0
    }

            ・・・

            sampler2D _Video1;
            sampler2D _Video2;
+           float _Slider;

            ・・・

            fixed4 frag (v2f i) : SV_Target
            {
                float2 uv = i.uv;
                fixed4 colV1 = tex2D(_Video1, uv);
                fixed4 colV2 = tex2D(_Video2, uv);

-               fixed4 col = fixed4((colV1.rgb + colV2.rgb), 1.0);
+               fixed4 col = fixed4((_Video1.rgb*(_Slider - 1) + _Video2.rgb*_Slider), 1.0);

                return col;
            }

            ENDCG
        }
    }
}
```

https://x.com/Zect3279/status/1683448148944093185

こんな感じになりました。
スライダーで2枚の映像を自在に混ぜることができましたね。

## 最終的にできたソフト
そんなこんなで、映像、スライダー、material、shaderの数を増やし、ｺﾞﾆｮｺﾞﾆｮした結果、こんな感じになりました！

https://x.com/Zect3279/status/1684143928386412544

これが、私のソフトのv1となります。

こいつをハロボカvol.1、初めてのVJの現場に持って行きました。
~~（出番寸前にビルトしたのは内緒）~~

# 開発理念
急な開発理念の紹介です。

このソフト、全くのVJ初心者が、他のソフトわからねぇ！って騒ぎながら作りました。
そのため、「操作性」というものが非常に重視されています。
徐々にキーバインドは変わっていますが、全てがキーボードで操作できるように、しかも、かなり直感的に操作できるようになっています。

実際のキーボードを見ていただきたいのですが、
```
[v2.3 README.mdより抜粋]
順にMV1,MV2,FX1,FX2
R,T,Y,U : フェーダーを上昇させる
V,B,N,M : フェーダーを減少させる
F,G,H,J : フェーダーを0,1で切り替える
```
キーボードをそのままフェーダーに見立てて操作できるようにしています。

エフェクト類も全て、数字キーやFnキーで操作できるようにしており、適当にﾎﾟﾁﾎﾟﾁすると、偶然かっこいい映像が生まれる！なども生じるようになってたりします。

自分でソフトを作れるからこそ、**直感的に触れる** という点は非常に大事にしています。

# 今後の発展
ということで、簡単に私が使っているUnity製VJソフトの解説でした！

今後はですね、
持ってるだけで全く使っていないmidiコンをどうにかしてソフトで使えるようにしたいな、と考えています。
後は、エフェクトや中のコード類がｺﾞﾁｬｺﾞﾁｬしてきたので、破壊と再構築を計画しています。
（mk3の誕生）

あとは、ジェネラティブをやりたい！！
レイマーチング！！！！

https://x.com/Zect3279/status/1860929113420353810/photo/1

こんな感じになったけど、それ以上に何かをしたいという気持ちが湧きおこらず、停滞気味,,,

# ただの宣伝
## VJソフト

https://zect.booth.pm/items/4976418

売ってます！

## VJ
VJやってます！

https://zscode.net/works/#_1

新宿を中心に、静岡に行ったり、札幌に行ったり、Twitchに居たりします。
ぜひ～～

# 最後に
皆さんも、UnityでVJをしましょう！！
では ﾉｼ