Imaginantia

思ったことを書きます

基底構造の反転

これは日記です。

5/6にディズニーランドに行ってきました。たのしかったです。

いろいろ見てきて思ったこととかを書きます。


 

元々行くときに「境界を観に行きたい」と思っていました。「夢」と「現実」の境目、「できたこと」と「できなかったこと」の間です。

消火器はそれなんです。

即ち「置きたくない (景観を損なう)」けど「置かなければならない (法に則るべき)」。そして、「隠したい」けど「見つからねばならない」。

如何に「自然に溶け込ませ、それでいて発見したいときには発見できる」ようにするか、はそのまま「力」の見せ所だと思うんです。

色々な溶かせ方を見れて大変よかったです。

このような「境界」は細かいところを観察すると見つかります。消火器はそのきっかけとして良くて、眼の動かし方の指針になるのです。

そうやってのんびりと世界を眺めていました。

しかし、あまりおもしろくないということに気づきました。

 

これは考えたら素直に納得しました。ディズニーランドはもう殆どが「夢」に成っていたのです。

即ち「現実」が消えた世界を目指した結果、「現実」は確かに消え、それによって「現実に備わっているディティール」も全て消えていたように見えました。

「自然」に置いてある柵、岩、なんであれ全てが「夢の物体」なのです。「描かれたもの」だけで出来あがった世界なのだと思います。

触ってもその質感は「実感」を伴わず、それらの配置には「生」が無い。全てが絵で出来ていて、物と物の関係性即ち「構造」が一切入ってないのです。

構造の無い世界です。

だから、観察し甲斐が無いのです。「見たまま」しかないから。

世界の観察ができないので、アトラクションやショップに行くしか無かったのです。そういうシステムなんだと思います。

 

しかし、これは私の信念の一つであるところの「構造を入れると良くなる」ということに真っ向から反しているコンセプトです。

だけどここまで「良い」評判があるということは「構造の無い世界も良い」ということです。この差は何か。

って思って、まず、基底現実バーチャルという差があることを思い出しました。

その上で昔ぼんやり考えていたことがある程度矛盾なく成立しそうだと思ったので、もうちょっと書いてみようと思いました。

即ち、価値観の反転です。

 

私の制作における哲学の半分が、「モノとモノをつなげること」です。

phi16.hatenablog.com

即ち何も「つながって」いない2つの物はお互いに浮いていて、その間を「つなげて」あげることで相互に存在を提示することができるようになる。実在性が高まる。

しかし、これは全てがつながっていないことを前提とした信念です。

対照的に、基底現実では自ずと全てがつながっています。だから、つなげることそのものに価値が生まれないのです。

隣に置いたら影が落ち、長い棒は柵に寄りかかり、紐を引いたらベルが鳴る世界です。

では何に価値があるかというと、つながっていないことなのではないか、と。

 

他者と干渉してしまう環境から逃れて「演者と観客」という構図を作り出し、日常を過ごす家から離れて「非日常の遊園地」を立て、俗世の常識から離れて「自らの信仰」を祈る。そういうものに、この基底現実では価値を与えます。

「絵だけで出来た世界」は、当然多大な価値を持つものなのです。

そのコンセプトを立派に掲げて実現するのはめちゃくちゃすごいと思います。めちゃくちゃ。

2つの異なる世界をシームレスに繋げるよりも、間にあからさまな「境界」を引いてしまった方が「おもしろい」のです。

店には「本当に実在するお店」としての実在性ではなく「描かれたお店」としてのロールだけが期待されているのです。実在してほしくないのです。

結局みんなそういう「夢」を求めてきていて、「現実」を探しているのは私だけだったわけです。

ちゃんと合意形成があるわけですね。

 

「絵」であることは実用上良い面も多々あって。

視界の半分を占める地面が唯の平坦な板で良い理由は、やはりそこが「描かれていないから」ですが、それを「見えない通り道」として扱うことができています。 外見的に異なる複数のお店をくっつけて「大きかったことにする」ことができます。 虫は (世界観的に) 居てほしいけど (現実的に) 居てほしくないので、音で表現するという選択肢をとれます。 歪むべきでない柱を積極的に歪ませて、速度や大きさの表現に流用できています。 外界のディティールに気をとられることなく、アトラクションへ自然に意識を向けさせることができます。 何よりも各施設が既に「絵」として出来ていて、それぞれの世界観を干渉させずに同一区画に収容することができます。

確かに、これは完成された「夢」なんだと思います。

それはそれで良いものなのだと思いました。

 

だけど、バーチャルで制作をやってる側としては、これと真逆の状況が起こっていると思うわけです。

即ち、「置いただけでは何もつながらない」。それは「つながっているという信頼がない」という意味合いを含みます。

だから私たちはライティングを統一し、ライトマップをベイクし、インタラクションによる相互作用で以て「つながり」を示しているのです。

そうやって「世界に構造を入れていくこと」が私達の制作における1つの指針であると思います。

何もつながっていない「夢の世界」は最初からあるので、そこから離れていきたいのです。

基底現実では「非日常を求めていた」ことに対して、バーチャルでは本質的に「日常を求めてしまう」のではないかと思うのです。

それで良いんだと思います。

その点、サンリオピューロランドはなかなか面白いところにある気がしていて。そういう夢への執拗な渇望はあまり感じなくて、わりと俗世と地続きな印象があります。

「おもしろいならやる」みたいな感じなのかな。ちょっと言語化はできてないですが、なんだか世界の落ち着きを感じます。私は。

 

そんなこんなで納得したような感覚になった私ですが、ふらっと立ち寄ったお店でゴミ箱を見つけました。

パーク内にあるゴミ箱の装飾を模した、家庭用ゴミ箱です。NEW ITEM (新商品?) らしいです。

これ、文字が一切入ってないんですよ (底面にはロゴあるけど)。キャライラストとかも無く、ただ純粋なゴミ箱なんです。

それが商品として立派に (いっぱいあったんです) 売られているということは、この「このデザインのゴミ箱がディズニーランドで利用されていたという事実 (=自ずと生まれてしまった構造) 」にも価値があると認識されている、ということだと思いました。

だからかなんだかバーチャル的な感覚があったのです。「在るから複製できる」とか、そういう感覚。

なんだかすごいうれしくなっちゃって。そういう観点が本当に意味あるかはさておき、私はすごいうれしかったので、それで良いと思います。

世間的な価値観そのものがだんだん変容しているのはそうなのかもしれないです。そうだったらおもしろいな。


 

なんかもうちょっと書くことあったような気がしますが、眠いし思い出せないのでとりあえず終わります。

少なくとも前から思っている「バーチャルにおける『良さ』の方向性は他分野と全く違う部分があるのでは?」という問題提起に対してちょこちょこ面白い案が出てきたのでよかったです。

だから、バーチャルにおける「アート」はまだいろんな分野が残ってる気がします。

いっぱいいろいろかんがえていきたいです。

おわり。

VRノードエディタについて考える

Ayanoさんと話していたときに言った「VRChat上でASEっぽいのができる仕組み」、作ろうと思ってたんですが時間がなさそうなので頭の中の設計だけ置いておこうと思います。

特に私の確認なく作って頂いて良いし、好き勝手すればいいと思います (当然)。作らなくても良いです。

まぁ、あと「実装なき設計」をそのまま出力したこと今までなかったので、それはそれで面白いかな、という実験でもあります。

概要

unitypackageの形で、VRChat上でノードを操作 (機能を変更・In-Outを結合/削除・パラメータを変更) してシェーダプログラムを表現・実行する仕組みを提供します。

prefabぽん置きでワールドにとりあえず置ける (ノード生成/削除機能があれば十分) 他、予めUnity内でセットアップしておくことも可能なら尚嬉しそう。

実装ではシェーダ特有の成分 (計算の実行) とそうでない成分 (計算グラフ表現) を分離して、他の用途 (純粋な計算・手続き的表現など) にも応用できると尚嬉しそう。

データ構造

基礎

「ノード」とは、実際にワールドに存在する"板切れ"のことです。「機能」とは、ノードに割り当てられているもので、ノードの処理内容を示します。各ノードは「いくつか (0を含む) の入力」と「1つの出力」を持ちます。

「入力」や「出力」は、実際にノードへ入力/出力されるデータの送り元・送り先のことで、ノード間を「値」が行き来する経路として用いられます。

「値」は 3.0 や float2(1.0, 4.0) などの何次元かのベクトルを表していて、「型」が定まっています。

「型」とは、1次元, 2次元, 3次元, 4次元ベクトルのうちのどれか1つです (簡略化の為にテクスチャ型は扱わないでいいかなと思います) 。

これだと「×」機能は「1次元用乗算」「2次元用乗算」のようにそれぞれ分ける必要があってめんどくさいです。可能であれば機能の型宣言で「n次元」を用いて入力側からunificationさせていくことが出来れば良いと思います。シェーダにおける関数は基本的にcomponent-wise (n→n→nとか) で、唯一珍しいのが dot (n→n→1) くらいです。そういう疑似genericsは (ちゃんとわかっていれば) 意外と簡単だと思います。

例えば上の図の「Brick」ノード (レンガテクスチャのサンプルを想定しています) は「Brick」機能を備えており、唯一の入力には「×」ノードが接続されています。「Brick」機能は「Brick」という名前と「入力は1つあり、2次元ベクトルを受け取る」「出力は1つあり、4次元ベクトルを返す」という情報から成ります (実際にどう計算するかは記述されていません)。

型の自動変換

ノード間結合 (以降「エッジ」) は、送信ノードの該当出力のベクトルの次元と、受信ノードの該当入力のベクトルの次元の対が、以下の表のどれかに該当するとき成立します。またそのとき、付加処理が実行されます。

送信側の次元 受信側の次元 付加処理
任意 送信側と同じ 無し
1 1より大きい数 受信直前の位置に「複製コネクタ」を追加
1より大きい数 送信側の次元より大きい数 受信直前の位置に「ゼロ埋めコネクタ」を追加
1より大きい数 送信側の次元より小さい数 受信直前の位置に「削除コネクタ」を追加

ただし、実装がめんどくさい場合は、これを実装しなくて良いです。(送信側の次元と受信側の次元が一致しているとき、そしてそのときに限り結合を成立させることができるとします) (代わりに各コネクタに対応する機能を追加する必要がある)

ちなみに1つの入力に複数の出力を挿すことはできませんが、1つの出力を複数の入力に繋げることはできます。

 

また、あるノードの出力が巡り巡ってまた入力に戻ってくるとき、循環していることを示す表示を行います。(計算上は循環入力をとりあえず0とみなせば良いと思います)

機能パラメータ

一部の「機能」には「パラメータ」(数値を1つ保持すると期待されるモノ) が設定されています。これには入力依存であるもの (特定入力がある場合にはパラメータが無効化されるケース) と、そうでないものがあります (但し、面倒であれば入力依存をやめて良いです)。

例えば「float4」機能には「浮動小数点数の値を4つ保持することができる」ことになっており、「float4」機能を割り当てられたノードは浮動小数点数の値を実際に4つ保持します。

同様に「Slider」機能では最小値と最大値と現在地の3つの値を保持できます (ただし、面倒であれば最小値は0、最大値は1に固定して良いと思います)。

 

以降、ノードとエッジによって構成された計算式表現を「計算グラフ」と呼びます。

計算の実行

2048x2048のRGBAFloatのCustomRenderTextureを用意し、そのうち256x256領域を1つのノードで使用します。これにより、ノードは最大64個までしか出せないことになります。

計算結果はRGBAとして保存しますが、ノードの出力次元よりも大きい場合は「最後の要素」を複製して保存しておくことにします (1次元なら全コンポーネントにRと同じ値が入る)。

各ノードには0から63までのindexが振られており、実際にノードの入力/出力関係はindexを用いて参照されます。

1フレームにつき「エッジ1つ分」の計算が走ることとします。これにより、毎フレームの計算量は一定に抑えられますが、計算グラフそのものの正しい計算結果が出るとは限らないということになります。

ただし、これでは「Time」機能 (実装は割愛) のようにフレームによって異なる値を返す機能を「出力を複数の入力に繋ぐ」ようなグラフを作成した場合、最終結果が正しく計算できないことになります (最終出力に到達するまでに掛かるフレーム数が異なる可能性がある為)。 残念ながら単純な対処は思い浮かんでいませんが、いくつか候補があります:

  • 高々64ノードなので全部計算してしまう (実際可能なはず!)
  • 速すぎるノードを遅延させる為に別のノードを仮想的に挟む or 強制的に挟ませる (ユーザに委ねるとメモリ確保の手間が減る)
  • 無視する

計算用シェーダにはグラフの情報がfloat4の128要素の配列として渡ります (各ノードにつきfloat4が2つ)。各コンポーネントの成分は以下です:

  • X0: 機能のid (予め割り当てておく)、未使用なら-1
  • Y0: 入力先indexのリストを64進数として解釈した値 (floatは16777216 = 644まで正確に表現可能なので、4入力までなら大丈夫) (それだとremapには足りないので他チャンネルを使っても良い)
  • Z0, W0, X1, Y1, Z1, W1: パラメータ (または入力チャンネル)

出力は不要です (計算するには拾うだけで良いので)。

これを用いて次のように値を計算していきます:

  • 現在位置のローカルUVに対して
  • 各入力に対応するノードの前フレームの出力を取得 (ノードが無い場合はデフォルト値を参照)
  • それぞれに対して機能のidに対応する処理を実際に計算

もしも、全てを1Fで計算するならば、適当に float4 buffer[64]; を作ってトポロジカルソート順に (これは循環判定の際に勝手に出てきそう) 計算していけば良いと思います。そういえば 昔つくったノードエディタ はほぼそんな実装です。

出力結果は各ノードにそのまま表示されます。

ただし、これは入力がUVであることを前提としています。例えばSkybox用にdirectionを取りたい場合はノード上の表示は球であってほしい気もするし、他の表示方法もいろいろありそう。複数の入力方式を利用できる場合には「ノードが何の種類の入力に依存しているか」によってプレビューモデルを差し替えられると嬉しいですね。また、その場合だとテクスチャに綺麗に格納できないので、ぶっちゃけ毎フレーム全計算走らせていいんじゃないかと思います。というか多分そうするしかない、いろいろと。

UI

ノードは「機能名」と「現在の計算結果」、また「入力群」「出力群」を表示していれば良いと思います。本当の板切れだと軽すぎるのでフレームだけちょっと厚いと良さそう。裏から見ても綺麗に見える (UVが反転する) と嬉しそう。

入力/出力を区別するためにコネクタには何らかのマークのようなものがあると良いかもしれない。できれば入力と出力が噛み合うもの (凸と凹みたいな)。

また、エッジは次元の情報を持っているので、これもまた何か表現方法があってほしい (例えば次元の数だけ線を引く?だけどまず空間に線を平行に引くのがめんどくさい、曲線に「標構」の情報を持たせなきゃいけない)。

根本的にエッジをどう描画するかも問題で、例えばBezierに乗せて曲線にしても良いし、ちょっと伸ばしてから直線という方法もあります。この辺は趣味かな。

まずエッジが無ければ良いのでは?というのも1つで、例えば最初から2次元グリッドを前提として常に「出力は右に進む」ことにするとか (出力位置操作用の機能を別で立てる)。定められた板の上でわちゃわちゃ選択していくのは色々と楽そう (運搬もできる) ではあるけど、細かい位置調節 (によるプログラム構造の可視化) は出来ない。ただ、当然いろいろと楽にはなります。正直そっちのほうが好きかも。

ノードはpickup出来てひゅるひゅる動かせる他、「持っているノードの入力(または出力)部分が、他のノードの出力(または入力)部分に重なったとき」にエッジ接続を行おうかなと思います。この段階では型検査が通らなくてもエッジの生成だけはしちゃっても良い気がします。

入力/出力を直接つかんで繋げる方式も別に良いような気はする。ノードでぺちんってするほうがなんか繋がった感あるかなって思ったくらい。

繋がっているエッジの端点をつかんでpickupUseDownすると削除とか?出力部をつかむと複数に入力されてるときに困っちゃうので、これは入力部だけでできるべきかも。

 

ノードをpickupUseDownすると機能選択パレットみたいなのが出てきて、機能を変えられるようになります。平面上のポインタみたいな感じで選べそう。

また、ノードのパラメータ部をつかむとスカラー値選択UIが出てきます。数直線なんだけどひねると移動に対する変化量が増えるみたいなのをほんのり考えていました。

数字表記は指数表記のほうがいいのかな。でも正直見にくいから併記とかあるといいのかもしれないけど。

スライダーはいい感じに実装すればいいと思います。pickupでもUnityUI式でも…?一貫性的にはpickup。

同期

基本的に全てを同期します (ノードの機能選択パレット・パラメータのスカラー値選択UIの出し入れは同期しなくて良さそう)。

ノードの位置は普通にVRC_ObjectSync、なのでこれはContinuousSync。機能やパラメータのデータは全て1つのUdonBehaviourで管理したほうがいいかも (こっちをManualSyncにする)。

ノードはSpawnさせたいのでVRC_ObjectPoolでも使えば良さそう。

おわり

こんなんでできるんですか?

 

正直UIを作るのがつらそうなだけで、計算部分はすごい簡単だとおもいます。

ノードっぽくなくても良いなら、なんかいい感じの表現能力のある形式を思いついたらまぁそれでやりたい。かも。

個人的にはグリッドは好きなんすけどね…。VRっぽくないか (?)

もうちょっとmotivation (動機) があると絞れたかもしれないですが、とりあえずこれくらいで…。

記録 220502

はい。

いくつか情報をおいておきます。

言うにあたって

なんやかんやでそんな感じになってしまった私達ですが、そのままそれを公開するのは面白くないと思いました。

というのは、この広い界隈、「その言葉」の重みがだいぶ弱くなっている気がするわけで。

気軽であることは善いと思いますし、それはその形態として正しいと思いますが、"そうじゃなかった"ので。

であればもっと重みのある出力を狙おうと思って。こうなりました。

明らかな「覚悟」を提示できるようになるまで何も言わない。

即ち「情報は一切出さずに一気に畳み掛ける」方式です。

何度か書いたように私はそういう秘密を作るスタイルがあまり得意ではないんですが、今回はしょうがない。お陰で重みは出たんではないでしょうか。

重すぎたかも。

 

対し、一切何も出さない状態で急に「はい!」ってされても多分意味わからないと思うんですよね。重みがあるが故に今の状態との乖離が激しいと「受け入れられない」のです。

なので、これをどうにかする為に当日、「段階的な情報」を出す必要がありました。

マックの写真によく見ると居るのはそうで、ケーキっぽいのは逆にあからさま(だけど理解可能)、その後で敢えて「一緒に居ない」という情報を提示してクールダウンさせてから、あとはとんとん、という感じですね。

これは元々考えてたわけではなく、当日ノリでいろいろやってました (めっちゃ悩みながら)。結果的にはよかったと思います。まぁそんな丁寧に見る人ほぼ居ないとは思うんですが。

何をやってるんだという感じですが、二人共まぁそういうタイプなのでそれでいいんだと思います。

変わらないこと

まぁその。極論多分言わなきゃバレないわけで、お互い変わらず制作とかぶいちゃとかやってくのは変わらなくて。

今回言ったのは「周知の事実」にしたかったからで、これは即ち「この情報の価値を0にしたい」という目的です。

…実際そうではあるけど、まぁ言いたいは言いたかったよね。「情報」を抱えてるの好きじゃないし。

だから今この状態ではもうそこまで気にする必要はないのでは、っておも…っています。そうとも言えない気持ちはわかりますが。

 

一つ思っているのは、今は確かにそういう感じではありますが、万が一そうじゃなくなったとしても一緒に居られるだろうということで。

どうせ何か作ってる人間として、類似たことをやっている人と一緒に居るのはまぁ楽しいじゃないですか。それは多分ずっとそう。

作らなくなったらどうか、はよくわかんない。でもどうせこれは呪いみたいなものだしずっとこうな気がする。

だからあまり心配はしていないです。むしろ喧嘩とかしなさそうすぎて怖い。最近小さなミスをやらかしすぎて怒られたりはしてますが。

…そういえばまぁ、何よりも「会話できる人」なのは大きいですよね。これって結構厳しい条件なんですよね。

 

この辺のことを考えるとまぁ普通に友人同士の云々と大差ないし実際そんな感じでいいんじゃないかと思います。協力度めっちゃ高いくらいで。

プロジェクタとか置いて遊びたいね~とか言ってる。

云々

いちおう書いておくんですが、こう。

再現不能なプロセスというか。

全体的に一切参考にならないというか。

奇跡というか。

なんかもうどうしようもなくこうなっちゃったので。

その辺の話は私はよくわかんないです。うん。

二人共まぁそうなるとは思ってなかったので。人生は難しいですね。

いろいろとね、長い間お話して考えてたんです。その結果としてなんとかなりそうとなったのです。

でも本当にそこそこの時間が必要だったのです。それでよかったんだと思います。

私について

えー、私はまぁなんかいろいろやってる人間として見られてるとは思うんですが、それはそれとして、実は(?)だいぶひどい人間です。

いろいろと。ご存知な人はご存知だと思うんですが。いえ、最近の人は知らないと思うんですが。

過去にいろいろとやらかしているタイプで、まともになったのは最早ぶいちゃ期からくらいで。正確に言うと「まともじゃない成分」が同時に居たんです。

本当にその節はたくさんの人に迷惑を掛けました。こんなところに書いて伝わるとは思っていないですが。はい。

少なくとも思いつく人が8人います。

なんとかすることができるようになってぶいちゃで穏やかで居られたわけですが、でも結局そういう自分の中身みたいなものは結局変わっていません。

そういう話もfotflaさんとしてて、まぁ、色々と制御はしつつもなんとかなるかも、いえ、正確に言うと「迷惑は掛けることになると思うけど一緒には居られる」という感じになりました。

結局「お互い何でも言える状況」というのが必要だったんかな、とは思っています。

「fotflaさん」について

えー、今までの話はまぁそれはそれとして。

これはめちゃくちゃ大事なことなんですが、ぶいちゃにおける「fotflaさん」という概念は引き続き不可侵で、特に私の態度も変わりません。

というか変わってません。

なので。なんというか。引き続きよろしくお願いします。

はい。

 

ちなみに、ふぉとふらさんからはなんか好かれてる感 (?) はめちゃするんですが、でろでろなのはわたしのほうです。

謝辞

こっそり色々やるにあたって、複数人にお世話になっていました。

  • おはぎさん: (作業の都合もあって) 予め伝えていました。みまもっていただきました。はい。(様々ありがとうございました)
  • ロジックさん: 家探し・引っ越しについて色々と相談させて頂きました。お陰様でスムーズに色々とやってみることが出来たと思います。
  • なるもどきさん: 義理を立てるべきだと思ったので伝えていました。暖かく見守ってくださいました。絵ほんとうにありがとうございます…。

また、ねるまえちゃ・きゃのりんちゃにも。いつも良いわね~~~と眺めさせて頂いております。よく「あーーこのふたりはもうーーーー」って二人でやってます。

なんとかやっていけそうです。本当にありがとうございます。

おわりに

確かこの辺の時期からだんだん私がおかしくなってて。その後作業通話の頻度があがったりしてからは半年くらいはずっと (Discordで) 一緒にいました。

なので ShaderFes も ShaderShowdown も CUE やってたときも色々お話したりしてました (私達がお互いの作品にあまりTwitterで反応しなくなったのはもう十分喋っちゃってたからです)。たくさん助けてもらっていました。(面白さの為に) 本当に隠すべきことはきっぱり隠してやってましたけど (fotflaさんにもびっくりしてほしいですよね、もちろん)。

(ShaderShowdownでマジのツイッター断ちが出来たのはfotflaさんのおかげです)

FORGOTTENの文句をめっちゃ直接言ったりもしました (おはぎにも)。

その辺はいろいろと良い影響になってるんじゃないかと思います。

これからもいい感じにいい感じのものをつくっていきたいです。

 

以上、読んでくださってありがとうございました。

これからものんびりよろしくおねがいします。

CUE 解説

この度なんかやりました。4年記事に間に合うかな~って思ってたんだけど間に合わなかったですね。

毎度の如くで制作解説をなんやかんや書きます。

コンセプト

大枠はここに書いてあるとおもいます。

styly.cc

要は「コスパ良くGCを別のとこに持っていくにはどうすれば良いか」で、私としての答え (𝑨𝒓𝒕𝒊𝒔𝒕成分) が「単管と布でディティールを確保する」ということなのでした。 GCそのものではなく「GCあの成分」を持っていくことを考えたので、それならなんとかなるかもしれない、という気持ちです。

あと、大事なこととして楽しい作品にするというものがありました。逆張りをさせない。Stylyにあるものはきっと「アート」が多いのでしょうけれど、私たちは「エンターテイメント」であろうとしたのです。何故なら、純粋にたのしいのでね。

だから、あまり演出そのものに「意味」とか「解釈」とかはなくて。ライブとして、エンタメとして、みんながうきうきになってくれれば良いなと思っていたのです。いい感じになっていた気がします。

ついでにまぁ、勿論ではありますが「ちゃんと音に合わせる」という成分。私が普段やっているCRT弄りは完全な音合わせが出来ないわけで少し寂しいところがあって、いつかこういう「合わせようと思って合わせるもの」を作りたかったのです。そういうコンテンツが実在してほしかった。それはそうよね。

「何を音に合わせるか」は悩み所なわけではありますが、やっぱり音は物理的振動です。物理的振動がそのまま伝われば、それは即ち「音の実在」になるのではないか、と思いました。これが布と、あの水っぽいやつですね。

低音系は物理現象として。対して周波数高めの音は"蛍光灯"による「光」を使いました。多分「鋭いから」なのかな。そういう認識は結構音と色と、似通っているところありますよね。そして全体的な雰囲気を制御するのがあのポイントライトとなります。

これくらいの要素があれば「適当にミニマル」で「適当に表現力を持った」構造になるということがわかりました。良いですね。私の「抽象」成分と0b4k3さんの「具象」成分がいい感じに混ざっていた気がします。多分。

 

コンパクトな形になったことによって「パッケージ」としてGCのあの感じ (特に私が持っている部分) を取り出して形にできるようになって。それが外に出る。素晴らしいことですね。

そういえば「CUE」というタイトルはCUE打ちのCUEで、「いつでもここに帰ってこれる」みたいな気持ちだったと思います。確か。

実装

GPGPU

フラグメントシェーダでGPGPUシミュレーションをする方法は色々あって:

  • カメラで「次の状態を計算するMaterialを貼ったQuad」を撮って毎フレーム回す
  • CustomRenderTextureで_SelfTexture2Dを拾って次フレームを計算する

があります。しかし、WebGLで動かすことを考えると色々制約が出てきて:

  • WebGLではCustomRenderTextureが動かない
  • WebGLでは asuint asfloat が動かない

というわけで「パック系を使わずにカメラで浮動小数点テクスチャのフィードバックループを作る」必要がありました。

で、ぬるっと書いたら動きませんでした。が、もしやとおもって自前でダブルバッファリングしたら動きました。そういうことらしいです。

つまり。

  • 状態テクスチャ (R16G16B16A16_SFLOAT にしました) を2つ用意して
  • シミュレーションの入力 (Materialに割り当てられたテクスチャ) と出力 (カメラのTargetTexture) を毎フレーム入れ替えつつ
  • Camera.Renderを毎フレーム呼ぶ

ということを行っています。これが布と水それぞれに対してあります。

blog.oimo.io

とても参考にしました。むしろこれが全てと言っても過言ではない。ちょっとだけ「縦糸は強め、横糸は弱め」になるように調節は入れてます (カーテンっぽい揺らぎが出やすくなった)。

反復計算するところがちょっと問題なんですが、GrabPassで計算結果を拾い直すことでやってます。これに書いてありました。

ただあまり負荷を掛けられなかったので、色々試した結果として solve→step→solve→solve→step を1Fで実行することにしました。solveでは速度の更新だけをやって、stepで実際に移動を行う感じです。

なんとか安定しました。

 

描画はSurfaceShaderをベースにしているんですが、ちょっと変なことをしています。(そのために「ベースをSurfaceShaderとして書いて、Show generated code機能を使ってvert/fragとして直接中身を弄る」ことをしました。)

まず布は「半透明であってほしい」わけですが雑にやると汚くなります。そこで:

  • まず ForwardBase で ZWrite Off, Blend SrcAlpha OneMinusSrcAlpha で、黒色で描画 (布の裏側となる背景部分をalpha付きで暗くする)
  • 続いて ColorMask 0 で普通に (ZWriteありで) 描画 (布のdepthを書き込む)
  • 最後に ForwardAdd で ZWirte Off, Blend SrcAlpha One で布の色を描画 (AlphaBlendingが完成)

ということをしました。ほんのり背景が暗くなりすぎたりする場所があるんでしょうが、特に気にならなかったのでOKだと思いました。

ついで、布は「影を落としてほしい」ので、ShadowCasterを普通に追加しました。便利ね。

surf関数の中身ではとりあえずバンプマッピングをしつつ (法線はシミュレーションのついでに計算してます)、「布の縁に段差を入れる」処理を書いています。

あと布の透明感を出すために「入射角が浅くなる濃くなる / 正対するほど薄くなる」処理とか入っています。よくありそうな感じ。

いい感じになってよかった。

これはよくある波動方程式のやつがベースです。8近傍にして、角の子たちは重みを 1/√2 にしています。

が、それだとよくあるふにゃふにゃの水ができます。なんか違う。

そこでみんな大好き FFT Water の Choppy wave を入れました。もはやこれがメインだろっていうやつですね。

やりすぎるくらいにいれたのでちょこちょこ破綻しますが、まぁどうせ一瞬だしいいと思います。

また、もっとキモくしたかったので、「bump用テクスチャの参照位置を勾配によって変える」ということをしました。

キモいね。良い。

ちなみにちゃんとでこぼこする水は中央部だけで、他のエリアは平面 + バンプマッピングだけで出来ています。シミュレーション結果も中央部分のタイリングになっているだけです。

単管

一応気持ちだけ Geometric Specular Antialiasing 入ってるんですが、今回のシーンには効果が薄かった (どうしようもない) かもしれない。

単管には蛍光灯としての役割も付加されているわけですが、こっちの計算がちょっと大変でした。

全体が一様に光るのではなく中央が強めに光ってほしいな~っておもったので最初「逆リムライト」をやったんですが、視線と単管の方向が近いとみんな暗くなってしまいます。そうじゃない。

というわけで「視線方向を、単管の方向を法線に持つ平面に射影」してから逆リムライト (?) をしました。

「単管の方向」はモデルデータのtangentとして直接書き込まれています。ちなみにこれは適当にスクリプトで計算しました (全部ただの円柱なので、こう、計算が簡単)。

ついでになんやかんやあって「単管の中心座標」を持っているので、「単管毎に色を変える」ことも「ワールド座標によって色を変える」こともできるようになってます。

もともとは単管毎の色だけでやろうと思ってたんだけど、ワールド座標依存にしてみたらめちゃくちゃ表現力が上がって楽しかったので、もういいやっていうことにしちゃいました。

存在が許されるかはちょっと微妙なラインだったので、CUE本編では段階的な導入をしていて、「最初は一瞬だけ光って、詳細を観察できなくする」「単管だけぶわーっと光る (Otomoの始まりのとこ)」「めちゃ重い音に合わせてもうワールド座標ベースで光らせちゃう」みたいな流れがあったりします。

Ambient Occlusion

今回ベイクとかは一切やってないんですが、適当にAOくらいは欲しかったのでシェーダで描いてます。

柱と単管にも入ってます。どうせ位置が変わらないのでこういうことができる。

そういえばそういう意味ではシミュレーションにも「布は柱を貫通しないように」「水は柱が固定端になるように (意味不明)」処理を入れていたと思います。こういうのがほんのり入ってるとなんだか「つながってる感」がする、気がします。

演出作成

「場」が出来たのでメインとなる演出を考えます。使えるものは「ポイントライトの位置と色」「布に当たる風」「水の高さ」「シミュレーション速度」「単管/蛍光灯の色」です。

えーと。

全部プログラムで書きました。

まずTimelineで制御されていて、自前のPlayableBehaviourに現在時刻が渡ってくるので、それに沿ってポイントライトの位置を動かしたりしています。

ix が拍数 (index) で lt が拍開始からの割合 (local time) かな。基本的にすべてそれで出来ています。拍合わせは頑張りました。

で、同様に時刻がシミュレーション系 (シェーダ) に渡るので、そこで布に与える力・水に加える力・シミュレーション速度・蛍光灯の色を計算し、返します。

なので演出の7割はシェーダに書いてあります。

読めないですね。まぁTimelineで再生しつつ作っていきました。基本的には好き勝手やっていただけなのであまり解説できることはありません。

 

全体的な演出テーマとしては、やっぱりこの「場」で出来ることをいろいろと提示したい、というものがあって。順番に:

  • 光と影
  • 蛍光灯
  • 布と水
  • 華やかな感じ・綺麗な感じ
  • ポイントライトの移動のみ
  • ゆるやかな終わり (+布の皺とか)

という構成になってました。これはまぁ曲に合わせていったら自ずと出来ていったものです。そんなものですね。

ポイントライトは弄っててすごい楽しかったですね。「良い影が出る場所」みたいなのを探っていく感じでした。対照的に蛍光灯は自由に絵が出せるので自分の中から出すものを探さなきゃいけなかった。それはそれで楽しかったですけど。

こう、やっぱりベースとなる場をちゃんと立てるといろいろと良くなる、ということを何度も実感しました。

そういえば元々は視界ジャックによる画面揺らし (Amebientの雷で起きるやつ) を入れようかとか思ってたんだけど、ちゃんと布が揺れたらもう要らなかった。

 

さて。

色々作ってPlayableBehaviour上で動作するようになったとしても、それをStylyに直接持っていくことは出来ません。一応Timelineの制御は timeline-playmaker が使えた (undocumented?直接聞きました) ので大丈夫なんですが、スクリプトそのものはアップロードできないので。

なので。がーっと書いたコードを全てAnimationClipにベイクする処理を書きました。

ベイクする要素をリストにしておいて、毎フレーム値を拾ってそれぞれをちまちまAnimationCurveとして再構成していく、という処理です。

500MBくらいになりました。

困るので、これを参考にしてAnimationClipの自動キー削減を行うスクリプトを書きました。

29MBくらいになりました。

これをちゃんと使えるようにするのがだいぶ大変だったところがある。やりすぎるとぐにょんぐにょんになるし。

対して、まぁシェーダ側は何もせずにそのまま上げられたので、便利だな~とか思ってました。呑気に。

 

しかし。

めちゃくちゃ重くて。本番直前まで結構やばかったと思う。

で、色々と探っていったらシェーダの演出部分がめちゃくちゃ重いということがわかりました。ウケる。

これは実は当然で、大量に分岐があるので、多分大変なことになっているはずなんです。

で、ちょっと対処が必要だなと思ったので、えー、演出を大量に区切って、それぞれを multi_compile で振り分けて、シェーダキーワードで選ぶようにしました。

こういうことです。

あまりにも筋肉解法だなと思ったんですが、わりとこれがうまくいき、負荷はだいぶ抑えられました。携帯でもわりとちゃんと動くらしい。

ただ、代わりにシェーダ時切り替え時にシェーダコンパイルが走って固まってしまうようだったので、シーンロード時に全通り予め表示させてコンパイルさせる、ということを行っていました。これがあのロード画面です。

 

さて、これによって「Styly上で、シェーダキーワードをリアルタイムに適切に設定する」必要が出てきたんですが、そういう制御はStylyでは全てPlayMakerで書く必要があります。…ギリギリなんとかなりました。

…単管、36個に分割されてるんですが、いろいろあって (GPU Instancingの影響かな?) 単一マテリアルの更新だとシェーダキーワードがちゃんと反映されないみたいだったので、全オブジェクトへの割当を手動で書きました。えんえん。

やったことは正確には「用いたいシーンのインデックスの値をZ座標に持つGameObjectを用意 (アニメーションで移動していく)」「位置を毎フレーム監視、変更されていたらインデックスを読み出して新たなシェーダキーワードとなる文字列を生成」「影響を受ける全GameObjectに対してちまちまキーワードを登録していく」です。まあ。動く。

なんやかんやで完成――。

Web版がしんどい

色々作っていった中で、Web版が変な挙動をすることが多くて。

  • expにでかい値を突っ込むコードを書くとシェーダ全体がおかしくなる (expを使わない分岐のはずなのに単管が真っ黒になったりした)
  • 「ビット演算に最適化できそうなコード」(2x+1とか)を書くとシェーダコンパイルに失敗する (bitfieldなんとか関数とか、and関数とかを発生させて、存在しない関数なので失敗する)

めちゃくちゃやばかったのが、「現在のシーンをintで返す関数 (0,1,2,3のどれかで、開始前だと-1を返す)」を作ったら、32bit整数値を32bit浮動小数点数として解釈した値としてコンパイルされたというのがあって。

確かに 1.40129846e-45 (f32) はバイナリ表現としては 1 (i32) と一致するんですね。で、最悪なのが -nan (f32) で、こいつは -1 (i32) のことなんすね。

で、nan なんて無いって言ってコンパイル失敗して、結局全てが終わるっていう。最悪みたいな現象がありました。

対策はfloatにするというだけです。ちなみにデバッグにはシェーダのGLES向けコンパイルをめちゃくちゃ使っていました。しんどい。

あとWeb版だとPoint Lightのshadowがデフォルトだと出ないです (RenderModeをimportantにすると出る)。

意外とモバイルはちゃんと動いていて感動しました。

本番の運用

時間同期

さて、これを当日 (1月22日) の9時丁度に各環境で再生しなければなりません。ただ、この9時丁度って難しいです。

VRオンリーだったらまぁローカルタイムでもいいかなという気がしますが、今回は現地があり、そこでは携帯を掲げているユーザ、プロジェクタに投影する映像を出すアプリケーション、モニタとスピーカーに繋がっているアプリケーションがあります。全部がほぼ同時に再生される必要があるわけです。

信頼できるのは外部サーバくらいだと思ったので、外部サーバを用意しました。適当にnode.jsで書きました。

これは設定された「開始時間」から現在時刻の差分をミリ秒単位で返すだけのサーバです。PlayMakerには幸い Get Http Request があったのでこれで値を拾ってこれます。

頻度高めにpollingすると怖いなと思ったので1分に1度チェックするようにしています。1分以内になったらその最後の値を元に開始までのdelayを計算する感じ。同時接続100個くらいはあったかな、まぁまだ行けたかもしれない。

ちなみにWeb版Stylyから自鯖にアクセス出来るようにする為にhttpsにしなきゃいけなくて地味にめんどくさかったです (Let's Encryptを手動で動かしました)。あまりやったことなかった。

これでまぁ、多少のズレはあるもののなんとかまぁ概ね「同じ」と言えるくらいの精度で再生できるようになりました。

late-join対策もしました、teaserをいい感じに終えていい感じに始まるように。PlayMakerは大変ですね。いつ実行されるのかが隠蔽されててよくわからなかったです。なんとかなったけど。

そういえば当日は9時5分に開始するように設定しました。これは9時って聞いて9時にページを開く人が居るかもって思ったのと、なんであれteaser部分1周期 (2分半くらい) 分は見てほしかったからです。でもちょっと長かったですね。心配掛けました。

現場設営

現場では、モニタとスピーカー用のPCと、プロジェクタ用のPCが4台、計5台を動かす必要がありました。元々Styly上のアプリではなく自前ビルドならいろいろ融通が効く (なんとスクリプトが使えます) のでそうしようとは決めていたんですが、同時再生とかについても考えたところもういっそ全部遠隔操作できるようにしちゃおう、って思って。

Webコンソールと、それに繋いで制御を受けるスクリプトを入れました。確か websocket-sharp を使っていたと思います。サーバ側は ws かな。コンソール画面は手書きのHTML/CSS/JSです。

証明書は最近切れました。

こいつはPlay/Stop/Pauseはもちろん、カメラスイッチングやカメラの位置移動 (position, rotation) もできます。検証用に組んだものなので (スイッチング以外は) 実運用では使ってませんが。

というわけで万全の態勢を整えつつ、当日は私が現地に行く予定だったんですが…。

いろいろあって (あれです。コ関連の漢字5文字のやつです。私は元気だった。) 行けなくなってしまって。

プロジェクタの配置とか諸々は全て現地の方 (NEWVIEWのスタッフ・PARCOさん側のスタッフ) に任せることになってしまいました。ううむ。

万全な態勢を整えた甲斐あって特に制御では困らなかったんですが、ちょっともったいなかったとは思っております。

まぁ、でも良かったは良かったと思うので、これはこれで終わりの話です。現実は大変ね。

その他いろいろ

動く0b4k3さん

HUMR で45分間踊ってもらいました。いい感じになったね。

相変わらずアニメーションデータがバカデカくて大変なことになっていたので、前述のキー削減ちゃんでぐっ (900MB → 200MB) と削ったりしています。

削りすぎるとぬるぬるすぎて「生」感が薄れるというのもちょっとおもしろかった。できるだけ鮮度を保ちました。

Warning

…ぶっちゃけ読んでないでしょ?

多分読んでなくても「こういうコンテンツで」「こういうタイミングで」「でかでかと出る赤字」って、どうせアレじゃないですか。

だからまぁ。英語だけでもいいかなって思った。

PPS

ポスプロどうしようかなと、いろいろいじっていた時期がありました。0b4k3さんと私とで。

PPSv1のColorGradingのConstrast、0b4k3さんは1.7にしようって言ってたんだけど私は1.2が良いって言って「戦って」いました。

…最終的に、ポスプロ掛けすぎるとAndroidでバグることが判明して、Contrastはいじらないことになりました。

ReflectionProbe

開発初期、単管を生やして色々試していたとき、私が「なんか締まらないなぁ」って思っていた時期があって。でも0b4k3さんは良いって言ってたからなんなんだろう~って思っていたことがありました。

よくよく確認してみると0b4k3さんはさらっとReflectionProbeを消していました。

あぁ、そういうことなんだなぁって思った。

心斎橋PARCOの展示

そういえばここにあった謎のARコンテンツの制作もやってました。

立体的に飛び出る (観察できる) よりも奥に見えるほうが期待煽るので (GCの存在的にも) 良いんじゃないかな~と思って。

GCのモデルそのものを切り取るのはちょっと大変だと思ったので、depth/colorからそれっぽく再構成するやつを作りました。あと窓。

とりあえず作ったらメッシュがでかくなりすぎた (600000tris) ので久々にHoudiniを起動してPolyReduceに投げるなどしました (BlenderのDecimateだと固まっちゃった)。

 

最初はカメラ1個から撮った平面の画像を使ってやろうとしていたんだけど、FoV足りないな~と思ったのでちゃんとCubemapにしたりしています。なんと Camera.RenderToCubemap という便利関数があって助かった。まぁこれだとdepthが吐けないのでdepthは別で処理しなきゃいけなかったんですけど。

で、これを描画時にサンプリングする為に、各メッシュ頂点のnormalに「中央からの方向」とかいう情報が入ってます。カメラが回転してたからCubemapを回さなきゃいけなかったのよね。

まぁなんか意外と大変でした。このpackage配布してもおもしろいかもね。

 

機構は用意したのでそれを0b4k3さんに渡して好きな場所でキャプチャしてもらって、あとはいい感じに配置、という形で。

ちなみにこのGCのモデルは2~6倍に縮小したりしています。AR的にはそういうのも大事なんだな~というのもわかった。スケールで結構印象変わるのよね。

 

本編周辺についてはこんなものかな…。

Archive

えー、やっと出ました。実は2月末にはほぼ出来上がってたんですが、インタビュー記事に合わせて出そうということでだいぶ温めていたのです。おかげでカセットの整備が出来てよかったね。

元々作ることは決まっていて (PARCO賞的には「残るもの」を作らなきゃいけなかった) いろいろ考えた結果としてああいう形になったというものになります。

最初の最初は新たに演出組むか、と思っていたんですが、曲がものすごいことになっていたのと、Archiveとしてそれはありなんじゃないか、と思って、こうなりました。

つまり、曲が切り刻まれていたので、演出も切り刻んで再構成しました。編集っていうやつですね。

ちゃんとディティールがあると切り貼りしても大丈夫なんだなぁ、ということを作ってて深く感じていました。

 

実装は簡単です。元々Timelineでの制御は時刻tに対する関数として組まれていたので、実時間からtを出力する関数を作ってしまえば良かったのです。

160300とか62000とかいうのがオリジナル側でのフレーム数ですね。ひどいねこれ。

で、これだけだと0b4k3さんのモーションがそのままになっちゃうので、これも再構成させます。各Curveに対して AnimationCurve.Evaluate を実行して新たなCurveを作っていく感じで。

というわけでできました。

 

ちなみに最後のぶわーーーーって出るところは、「CUE本編の中で特徴的な部分を128個かき集め、それを雰囲気に沿って6通りに分類、それぞれを曲に合わせていい感じに配置」したものです。8拍目系 (とん↓とーん↑) が特に好きです。

なので本編の主要な部分はほぼちゃんと残っています。0b4k3さんが左右にぶるぶる震えているところのは確かShockwaveの早回しです。原型を留めているとは言ってない。

ぶわーーー直前の「ちゃっかっかっちゃかちゃかっちゃっ」の部分も大好きです。前振りとしても完璧だし普通に合わせがめちゃくちゃ上手く行ったと思う。

曲が良いからね。

StylyとVRChatの差異

実はポスプロが妙に厄介で。元々のプロジェクトはColor SpaceがGammaなのです。Stylyが。あーあ。

というわけでVRChat用にはGrabPassを使って自前のgamma処理が入っています…。

ついでにPPSv1をPPSv2にしなきゃいけなかったのでそれの調節も。ほぼ同じ見た目になるまでいろいろ弄りました。

 

あと、実は世界のスケールが違います

Styly版では現実サイズに合わせているので、もともと0b4k3さんを1.1倍に拡大していたんです。だって私達がでかいので。

だけどVRChatに戻ってきたので、世界全体を1/1.1倍するなどしました。

ワールド座標依存で書かれていたシェーダの部分を見つけてちまちま直す必要があったりした。まぁ概ねは大丈夫でした。

 

マルチプラットフォーム、本当に大変です。CUEが良い例になっていたらいいな。

MV

www.youtube.com

これ、好き勝手やった感がものすごくて良いなと思う。これは0b4k3さんに任せつつ結局ちょっとお願いしたりとかした感じのものです。

固定カメラの予定だったんだけどズームしたらウケるくない?って言ってやってみてもらったらウケたのでそのまま通りました。ウケる。

でもずっとそういうノリの制作だったと思います。始終たのしくて良かった。

カセット

これはちょっとした面白い因果があって。

まず ow (2022-edit) には最初カセットの音が入ってなかったんです。だけどなんか始まりと終わりの音があったらいいなって思って、カチって音を入れてもらったんです。

で、VRChat版として出すにあたって、「再生のUIが必要」という問題がありました。Styly版は一人なので自動再生で良いとして、VRChatでは複数人集まってみんなで見たいっていうことが多いと思います。

抽象的に再生マークの三角形とか置いても良いは良いけどなんか違うよね、ってなって。そうするといろいろ整合するしカセットプレイヤーを置いちゃえ、ってなって。

そうすると現実にほしいね、っていう話になって。わんちゃん行けるんじゃない?となって。行けちゃった。

「文脈を拾った責任を果たせた」感じになっておもしろかったです。満足です。

 

ワールドに置いてあるあのプレイヤーは私がぐっと生やしました。カセットテープ本体は 熊野屋さんの です。回るようにしたのはシェーダです。

ラベルの文字は0b4k3さんとTanabeさんでやってくださりました。「らしい」感じになってめちゃくちゃ素晴らしきです。

ちなみに巻き戻し (リプレイ) もできます。したかったので。

 

現実のカセットに関しては私はほぼ関与していませんが、なんやかんやあってらくとさんのowのピアノが聴けて私はすごく嬉しかったです。

聴いてね。

digitalghost.booth.pm

度々即興を聴く機会はありましたが、やっぱりこう、パッケージングされたものとして生まれた演奏はまた違う感じで良いですよね。美しい「無の冷たさ」でした。

たいへんによいです。

名前

実は上下反転すると phi16 っぽくなる。EDITのEDIまでが対称なのもちょっと綺麗。

この文字は私がせっせとパスで書きました。というか実は本編のクレジットの名前の小文字も私が作りました (フォントに小文字がなかったので)

どう表記しようかは悩んだんだけど、お互いEDITしたんだしついでに二人の名前もEDITしちゃおwってことでやりました。

まぁちゃんとしたやつは説明文にあるのでだいじょうぶだいじょうぶ。

こういうバカみたいなこといろいろ出来てよかった。

 

制作の話はこんなところでおしまい。

コードを書くこと

ちょっとだけ思想の話。

私は「コードが書ける人間」で、現にコードで全ての演出をつくるなどしているわけですが、要はこういうものを作るにはコードは不可欠ではないのか、という話。

ここでのコードはまぁノードでもよくて、なんであれ「何らかの自動化が正当に行える機構」のことです。繰り返しなんか手でやってられないのですよ。

繰り返しの中でも微妙に差異を入れるというのがまた大事な点もあって、そうするとそういう詳細な制御が出来るだけできるほうが、当然良いものに (見たいものに) なる。

特にコード的表現で演出を組むと「修正がいくらでも効く」というのは大きいかなと思って。直すこと、破壊することに関するコストがめちゃくちゃ低くなる。試行錯誤をたくさんできるようになる。

あと何が起きているかを「読む」ことができるようになる、っていうのもある。人間が繰り返しだと認識するものは、繰り返しだと記述したいと思う。

 

で、それを包括する話として。

結局、この世界に関連するコンテンツを作ることに於いて、エンジニアリングからは逃れられないと思う。

アートだけじゃ、思想だけじゃやっていけない領域が残念ながらある。私だって好きでコードを書いているわけじゃない。しかたなくかいてるの。

だから、アーティストはある程度のエンジニアリングができなくてはならない。これは別に今更な話ではなく、まぁ例えば画材の選択もエンジニアリングだろう。

それと同様に、アーティストは、自分の表現を詰める為に、表現を行うこの世界のことを知らなくてはならない。

だから今回の私の肩書はテクニカルアーティストではなくアーティストにしてもらったのです。アーティストが全てを包含するべきという気持ちで。

自分で選ぶこと、が必要なのだと思うのです。

別に「自分」が複数人であっても良いです。ちゃんと意思疎通が取れる、「ひとり」としてカウントできるほどの主体にエンジニアリング能力が備わっていれば良いと思うのです。

…ここまでちゃんと読んでくれた人は、ちゃんと「選ぼうとしている人」なのでしょうけどね。

 

やっぱり足し算ばかりやってるだけじゃ足りなくて。もっと「繋げる」ことが必要だと思うんですよ。モノとモノを。世界と世界を。

その為に私たちはこの世界を制御するしかないんですよ。

救いは無いので、みんなで苦しんでいくのが良いと思うんですよ。

がんばっていこうね。

ディレクションについて

今回は0b4k3さんDirector、私がArtistという役割でやっていたわけですが、恐らく本当に文字通りその役割をやっていたのだと思います。

0b4k3さんは終始「向き」を指定し、私がそれに沿って好きにモノを展開する。ある程度ベースとなる空間が出来るまでは直接対話で細かく話してましたが、演出作成になってからはDJMixという強力なDirectionに沿って制作を行ってました。Archiveでも文字通り曲に沿って作っていったわけで、広い意味で「良いDirection」だったのではないでしょうか。

制作されたシーンはほぼ私の手がこねたものだとは思うんですが、この「向き付け」無しにはこうはならんのですよ。ね。アートの外側の領域がね。

本当に良い機会でした。

終わりに

長いことやっていたプロジェクトですが、やっと全てが無事に終わってとても安心しています。

ちゃんと歴史に残ったら嬉しいね。即ち誰かの何かに繋がったら嬉しいね。

これからもいろいろやっていきます。

おわり。

正しい描画を行うための

ワールドを作りました。レンダリングパイプラインと、テクスチャサンプリングについてのある程度の可視化があるところです。

ニッチなコンテンツだとは思うんですが、この世界においては意外と普遍的に知られるべき事柄だと言えるとおもいます。

こういうのは文章だとやっぱりわかりにくくて、その実際の挙動を観察するのが一番理解にはつながると思うのです。なので。

経緯

実はここの歴史?は長くて。確かきっかけは Virtual Market 6 (2021年夏) じゃないかな。

いや、まぁ、ずっとではあるんですけど。ポスターにミップマップが無いんですよ。あそこのコンテンツ。

ものすごいジラつくじゃないですか。特にVRだと常時視点移動するからものすごい顕著に出るんです。

これは Z-Fight と同じくらい存在が悪だと思うんですが、平然と居るわけです。

これが認められている理由は、きっと「名前が無いから」だと思います。名前がない現象は認識できないので。

だから、これを否定する為には、「私たち」は知らなければならないのです。

そうすることで、にこやかに「ミップマップなし、よし!!!」と言えるようになるわけです。

 

そこで「アンチエイリアスの博物館」を作ろうと思いました。これがこの記事のおまけの「なんか2」というやつです。

一般層に来てもらう為にはワールドとしてまともである必要があったので、建物から作りはじめ、置くものとかちまちま作っていました。

あと折角なので一人でやりたかった。なんやかんや共同制作が多い最近なので、自分でどれくらいできるかをちゃんと確認しておきたかった、というのもあって作ってました。

実はあの1pxの線分とか完全な球体とかはここに置く予定だったミニ作品だったり。

まぁ、構想全体の1割も出来てなかったんですけど。

そんなワールドにのんびりと人が来て、穏やかにミップマップという概念を知るような場があれば良いなと思っていました。

 

が、これ、今の自分の手に負えないほど大きくなってしまって。色々やることがある中で、当分放置するしかないなと思っていました。

なので放置されていたわけですけど、こう、ワールドを全然作っていない現在、なんか作っておきたいなという気持ちと。あのワールド全体は辛くてもちっちゃくパイプライン部分だけ抜き出してもまぁ面白いんじゃないかという気持ちで。

Pipelineというワールドが出来ました。

元のワールド案の、軸となっている部分を取り出して、色々と操作可能にしたもの、がコレです。

アンチエイリアスの為に

「雑」なレンダリングでは基本的にバキバキで見るに堪えない絵が出ます。これに対策すべく行われる行為がアンチエイリアスです。

ぶいちゃ (というかUnity) では常識的にミップマップが用いられる他、MSAAが有効に使われています。MSAAは Performance Options で弄れるやつなのでちょっと身近ですね。

というわけで、「如何にその2つが実行され、結果に影響を与えているか」をちゃんと示す、ということを目的として、あのワールドは設計されています。

なので頂点バッファとかMVPとかは飾りみたいなもんです。まぁあれはあれで面白いところありますが。

 

この2つのテクニックは本質的に積分のことで、それ以外の何者でもありません。

何度か書いたように「1pxに含まれている描画範囲は点でなく、2次元領域」なのです。それを正しく表現する為の計算技法がこれらです。

そして、これはどちらも低レイヤAPIの段階で用意されているものです。それだけこの問題は普遍的であり、人類はこれまでちゃんと立ち向かってきた事柄なのです。

そういう美しい描画、正しい描画をする為の人類の歴史を、折角なので顕在化させたかったのです。

特にこれは過去ではなく、今使われているモノですから。

今後

…という、啓蒙を目的として作られたワールドですが、今のところ、あまりその目的を果たせません。

何故なら感情や因果が一切語られていないので、何も知らない状態での理解が困難だからです。

というわけで、そのうち、ちゃんと解説は入れようかなと思っています。が、いつになるかはよくわからないです。

とりあえず、ずっと長く燻っていた何かを多少は外に出せたので良かった、くらいの気持ちです。

 

ありがとうございました。

おわり。

私とVRChat 4年目

phi16.hatenablog.com

えー、今更ですが、「1年」が終わったので、またこれを書きます。

微妙にタイミングを逃してしまったあれがあって。まぁ。

今年はアレですね。数は減ったけど、密度が上がりました。

5.0

前半はずっとこれをやっていたのでは…。

解説はなんやかんやと書いているので…って思ったけど技術的?な話が多いですね。

そうね。そうねぇ…

3.0で一旦めちゃデカになった (ワールド容量もな) 印象のGCですが、5.0は逆にある意味で縮小的なのです。歩ける領域とか。あと置かれているものたちとか (3.0はずるいやりかたをしていましたからね)。

なのでこう、"見やすい"ですよね。良い塔です。住む場所ではなくなったけど、居る場所としては良いのだと思います。

現在も継続的に運用されていて (ワールドは一向に修正されていませんが…) いろいろと嬉しい意見を見たりするので嬉しくなります。

「ちゃんとつくるとよくなる」かどうかについては私はなんだかんだ懐疑的なんですが (必要条件だとは思っている)、今回はそれに合致するケースと思えます。

 

ついでにCRTの話…って思ったけどあまり書くことがないな。

うちのこの「元ネタ」は前に言った通りフーリエ変換のつもりで、好きな方向への波を作れるという機能が基本です。

離散群上なので見かけ上エイリアシングみたいなことにもなって、これが視覚的に丁度良いというか。連続だと出来ないこと。

それを鋭くしたりゆるくしたり、色々と外から弄るパラメータがあるわけですが、基本的にはたった8つで出来ています。

本当に多彩な動きが出来てすごくかわいいです。うまくいってよかったです。

代わりに上下左右移動はあまり使われていませんが、まあ、たまにこう。たまにいじってるので許してほしい。

本来のポテンシャルはもうちょっとあるはずなんですが (左右移動の速度を上限解放すれば) まぁそれはいつかのお楽しみ、みたいな気持ちでとっといたりはしてる。

その辺が全て融通聴くようになったら「白と黒のモニタだけで (外部映像ありの) VJ」やりたいなぁとかふんわり思っています。

思っているだけです。

 

そしてfotflaさんのVideoSynthesizerとの連携がね。すごくよくてね。

私のは、原則としてテンポに合わせることを前提として組まれています。考えてみればド時代から私はそうでした。

対してfotflaさんのあのこはテクスチャというか、質感そのものを組む感じになります。構造的な私の方と対照的です。

音楽というのはそのまま受け取れうるリズム的情報とはまた別に感情的情報がある雰囲気がしますが、そういう役割分担としてあのCRTVJは完璧なのです。

…この話どこかでしたっけ。まぁいいか。

GCは原則としてどんな音楽でも鳴りうるわけで、それによってどっちをどれくらい使うかを変えたりできて。

少なくとも今の所「表現能力には」不満がないです。

時間方向の操作解像度・精度に不満はありますけど。タイミングぴったり合わせたいねー…

そういえばドは「各々が作ったものを物体的に重ね合わせる」ものでしたが、コレは「同じ物体の違う性質を各々で操作する」ものです。落ち着いた正当進化としてふさわしい感じなのです。

はい。

 

GhostIlluminationの話は…いつからだっけな。RealtimeGIがしんどいという話はずっとあって、簡易的なものなら作れそうというぼんやりしたアイディアもずっとあったと思います。やればいいだけだし。

もう覚えてないし、今となっては、というのをすごく思っています。えへ。

少なくともこの大きく成長しているぶいちゃ環境であってもまだ耐えているというのは褒めて良い気がする。

というかそう考えると5月末にこれが存在していた、というのはなんだか面白い気がしてきますね。それだけ先にいたんですね。今は並ばれてしまいました。うれしいですね。

私は「ちゃんとやる」ことの価値をちゃんと全体で高めてほしいと思っているので、ぶいちゃは本当にそれが行われていて良い環境だなあと思います。

良いものはね。たいへんなんです。

みんなすごいです。

…さらっとアレに書けたのはうれしかったですね。

 

永遠に修正がされていない5.0ですが、一応修繕計画はいろいろあって。みんな忙しくて動けていないのだけど。

CRTVJももうちょっといじりたい部分もあるし。はい。すいません。

申し訳ないんですが気長に待ってください…

 

さて。時間を多少遡ります。

シェーダ会

www.youtube.com

www.youtube.com

そういえばこんなのもあった。

これはどっちもbutadieneさんに唆されてやることになった記憶です。たのしかったです。

1年前か…。いや5.0も1年前か、という気持ちではあるんですが。この1年なんか長かった気がするんだよな…。

あまり書くこと無いな。私解説だしな。

まぁ、某の通り、私はプレイヤーになるのは苦手なんですが、解説はわりと好きらしいです。ぶっちゃけああやってお話するのもちょっと好きです。

ただ、「お話するのが好きな人」は現世では概ね危険人物だと思うので、あまりそうはならないようにと振る舞っています。できていない気もする。

ゆるやかにおはなしをするのってむずかしいです。何か喋ると思想が乗る。

自分のチャンネルでやっているというのはその責任取りでもある気がしてきました。なんでもいいかまぁ。

リンドの夜探し

そういえばそうでした。

どうしようかなとは色々考えたものでしたが、これでよかったのだと思います。書いたし

私は記録という行為が好きらしいですし。

フルトラ

フルではなくなってしまったが。

何故か (よく読むとわかります) 手元に存在することとなったトラッカーさんですが、最近は案の定寝るために使われています使われていません。

一時期はクに行くときにはつけていた覚えがあるんですが、5.0でVJ業をやっているせいで「休む」か「演る」かになってしまい、マジで踊る機会というものが減ってしまっているのです。

たまに真ん中らへん行ってますけど、そのたびにトラッカーつければよかったなと思っています。やっぱあると楽しいですから。

んー。そんなにコスト高いわけでもないんだけどね。

まぁ、まず最近VRChat自体あまりやってないので仕方ないところではあるんでしょう。

写真撮ったりするときにはいいですよね。またなんか良い服見つけたいです。

日記一周年

phi16.hatenablog.com

そういえば。一年経ったので毎日日記を書くのをやめたんでした。これについてはさらに「やめたことによる影響」なども文章にした記憶があります。

これによって、代わりになんか重い記事が増えるようになった気が…しますね。一応します。

ただだからこそ軽い文章があまり書けなくなって困っています。こう。軽い願いとかが。

まぁ最近はなんか作業で全て時間が消えている感覚はあり…いや、まぁいろいろあります。

たまにほんのり書きたいことがあると書いています。この感じ自体は悪くないです。

一時的な感情で文章を書いて消したことも何度もあります。書くと気が晴れるので、これは良いことです。

またこれからものんびり書いていきます。日記もかきたいね。

Half Line

なんと今年度作った唯一のpublicワールド。この動画良い。服が良い。

これは同時に制作の思想とかをどばどば書いたので自分の中では綺麗に閉じた作品です。

そういえばここの「白黒性」のオリジナルはマネさんちもそこそこ入っているなぁ、というのを書いてなかった。

ここはとても私らしくて好きです。色味も好き。わたしはだいぶコレです。

もしかしてこの辺からだんだんピンク系になっていたのかしら…

機材

そういえば大きくなんかお買い物をしたというのもありました。PCとPushですね。

3090ちゃんには毎日頑張ってもらっていますが、あまりにも3090が頑張りすぎる為に他のスペックだとどうかわからないという弊害があります。知ってた。

少なくともGCに居るためとしてはとても良い働きをしており。まぁ処理負荷は別に元々気をつけろという話でもある。あるが、あるけどな…。

CUEのせいで散々な環境を色々試す羽目になったので、まぁ頭の方を改善していく感じでやるしかないんじゃないんでしょうかね…。根本的に開発環境が重いと話にならないしな。

さて、Pushですが、あまり使っていません。

それは音弄りをする暇がないからです。余裕があるならやりたいです。代わりに実質的なmidiパッドとしてCRTVJに利用されたりしています。

LiveもPushも嫌いではないし、なんだか馴染む感覚自体はあるので、時間があればやるとおもいます。

うー。いつになるんだろう…。

あとなんだかんだ実はQuest2も買ってしまいました。デバッグ用途です。まぁVDもあるし一応ぶいちゃはできそうだったけども。

Q対応はしなきゃなあみたいなことをしばしば思いますが、色々としんどいね。Bloomが使えないのが一番しんどい。

今のところ特に使い道が無いので部屋の片隅においてあります。

ShaderFes2021

さてもう年末です。本当に今年は…。もっといろいろやりたかったね。

既に書いたものたちはまぁいいとして (解説として十分かは知らない)、かな…。

なんかShaderFesに出すとしたら、(そこまでバカをする余裕はないけど) 変なものをちゃんと出したいよね、という気持ちがあって。

今年は素直に参加しようと決めていたので (昔の作品出したり)、素直に面白そうなものとして、レイトレを考えました。

最初からコースティクスを考えていたんだっけな?まぁ計算すれば出るディティールのはずなので、𝑨𝒓𝒕𝒊𝒔𝒕みたいなことはしないで済む。よさそう。

ということで、うちのパン屋ソースコードをがばっと拾ってきて、ぐっと書いて、ぐっとやりました。

なんだかんだそこそこ時間が掛かりました。はい。列挙すると:

  • 水面を平面と仮定して、bumpだけでcausticsを出すとこまではすぐできた
  • 平面だと面白くないので、ちゃんと頂点を揺らすようにする (しかも屈折して水面が見えることがあるのでここはraymarchしなきゃいけない)
  • ノイズまみれなので仮でノイズ除去系を入れるが、微妙
  • とりあえず箱を持って回転させる処理を入れたけどいろんなものが同時にぶっ壊れる
  • 全部直してノイズ除去系も組み直す (NEEもどきも入れる)
  • 今に至る

みたいな感じです。いくらでも解説するしなんならprefabごと投げても良いくらいですが、実用性が0。ShaderFesに置くのにふさわしいものだと思います。しらんけど。

ちょこちょこ嬉しい反応を観測しているのでとても嬉しいです。というか某所でこれの話されるとは思いませんでしたが。

人生で一度は作ってみたかったシリーズ。

TokyoDemoFest - ShaderShowdown

ぶいちゃではないけど…これは大きいものだったので。

phi16.hatenablog.com

言うことは全部書きました。よかったです。

そういえばこれは見ての通りBlenderレンダリングした絵です。

クリスタル内部の絵は普通に写真で取って適当に二値化したやつを使っています。クリスタルは普通に適当に生やしました。

本物はもっと色味がちゃんと複雑に出て…これは何の効果なんだろう。

所謂旅行先のお土産屋さんとかにあるあのガラスのあの複雑な虹色、昔から好きでした。

あの綺麗さは今回出せなかったね。うーん。本物は本当に綺麗です。ガラスが。

本当はぶいちゃにも持って行きたかったんだけど流石にな。距離関数にするのもめんどくさいしな…。

なんだかんだこれまで色々やってきてあまりこうやって「物理媒体としてのトロフィー」をもらったことがなかったので、なんというか。嬉しいです。

物理媒体のいいとこはやっぱりこれですね。質量です。

うんうん。

CUE

で、はい。

これが1月22日です。11月くらいからやってたんだっけな。

TDFの日はSANRIO Virtual Fesともろかぶりだったわけですが、微妙に書いたようにあの時はもう「みんなめちゃでかいもんに関わっとる、かかわってないのはうちだけ」みたいな気持ちでした。

CUEの制作はその頃既にやってましたけど、でもそんな気持ちでした。まぁ、これは方向の違いです。

そして、だからこそ、「ああいう」のではない「私らしさ」及び「GCの欠片」みたいなものをこっちで全力で出そうと思ったのです。

端的に言えばこれは「電ド5.0」だと思います。完全に地に足ついた空間ではなく、世界と世界の境界を覗きに行くようなモノ。

細かいことは近いうちに書きます。書きたいことは山程あります。もうちょい待っててね。

最近のいろいろな流れといい、「良い方向」に向かっていそうで幸いなことです。

私ももうちょっとがんばりますよ。

おわり

色々と書いてないこともありますが、"イベント"としてはこんなところでしょうか…。

「服」の話とか結構大きいとは思いますけど。これは書いたし。

書いてないけど大きいこと、いくつかあるんですが、まぁそのうちね…。

ワールド制作ほぼやってない… そういえばneortに作品出したりもしてない。なんかちいさなものつくってない…。

小さいものを作れなくなったのはとても悲しいですが、もうそういう時期ということなのか…。

 

まぁ、きっと大きい不満があるわけでは無いのです。ただ動きが重いのがちょっと寂しいくらい。

代わりにちゃんとぶつけていこうね、というのは正しい姿勢だと思いますが、なんかこう、もにょは残っちゃいますね。

この記事書いたところで微妙な消化不良感もありましたし。まぁ、そのうち解決する気もしますが。

いろいろやっていくしかない…。

 

あんまりtwitterには書いてないんですがいろんなワールドこっそり巡ったりしています。いろいろといいところは観測しています。

やることは変わらずいろいろあるので相変わらずみたいな様子なんですけど。のんびりぶいちゃがしたいです。

はい。

ありがとうございました。

いつものおまけ

  • 2021年
    • 3月 5.0
    • 4月 5.0
    • 5月 5.0
    • 6月 音弄りつつのんびり
    • 7月 なんか1
    • 8月 なんか1, なんか2
    • 9月 なんか1
    • 10月 なんか1, ShaderFes
    • 11月 CUE
    • 12月 TDF, CUE
  • 2022年
    • 1月 CUE
    • 2月 なんか3, なんか4, なんか5

謎の部分が多くてウケる。

なんかもはや一年ごとに書いてられない気がします。

去年の記事 では「穏やかな日々」とか書いてありますけど、これは5.0をやっていたからだとおもいます。はい。

まぁ、まとめるタイミングとしては丁度いいので来年もやろうと思います。今度はちゃんと2月末に出そうな。

パズル 220320

  • 「提示と解決」は万物の根底にあるthemeだと思っていて、私はそれを叶えたい。
  • 例えば「可能性の提示」は、「具現化による解決」と対応する。
  • 「質感の提示」は「安定性への暗示」として使われていた。
  • 但し、そうして解決しきったと思われる構造であっても、「視点」によってそうでないことがあると思っていて。
  • 即ち「提示と解決」はそれ自体が提示であり、ならばそれを解決しなければならないと。
  • つまり、「具現化によって生まれたその表現と、提示段階における表現の、何が異なるのか」を提示しなければならないのではと。
  • 私は例えばそれを「近さ」だと解釈するけれど、その解釈が合致したタイミングはほとんど無かったと思う。
  • 横方向への広がりではなく、縦方向が無いと「先」にならない。

だから、結局名前がついてしまうのでは。