feature image

2022年5月4日 | ブログ記事

ビジュアライザ2022を支えた技術(Fogrex版)

 どうもこんにちは、Fogrexです。これは5/1に開催された新歓イベント、CPCTFにて使用されたビジュアライザの制作秘話について語るブログです。

 ついでに本来4/12に公開されるはずだった新歓ブログリレー35日目も兼ねてます。マジで出してなくてすまんかった...

ビジュアライザ概要

 ここで話すビジュアライザとは、先述のイベントCPCTFにて参加者のスコアを†いい感じ†に表示することを目的として作られたWebサイトです。traP部員のグラフィック系プログラミングが好きな部員によってつくられており、traPの技術力を新入生に見せつける意義もあります。今年のビジュアライザ解説記事は以下です。このブログではその中でも特にわたくしFogrexが担当した箇所のこだわりポイントについて解説します。

CPCTF22を支えたビジュアライザ
この記事では4/25に開催された、traP主催のCPCTFという大会で使用されたビジュアライザについて紹介します。 製作者はFogrex,Renard,Uzakiの3人で行いました。 目次 ビジュアライザとは? 完成品 開発日誌 テーマ決め 開発開始 開発進行におけるトラブル 完成 各担当者による解説 Fogrex Renard Uzaki ビジュアライザとは?CPCTF22 当日レポート参加ありがとうございます本日はたくさんのご参加ありがとうございます。 本記事では、CPCTF22の開催中の様子や各種統計を紹介します! 参加者当日の12時ごろから参加者が増えていますね。今年は、問題登録が3日…

 ダミーデータを使ったデモは↓

CPCTF22 Visualizer
CPCTFは視覚化されます。ようこそ。

 権利的に微妙なのを取り除いてリポジトリも公開しました。興味ある人はどうぞ。かなりコードは汚いしコメントも入ってないです。

GitHub - CPCTF2022/Visualizer: CPCTF2022 のビジュアライザーのリポジトリ
CPCTF2022 のビジュアライザーのリポジトリ. Contribute to CPCTF2022/Visualizer development by creating an account on GitHub.

テーマと僕の担当

 まぁお気づきの方もいらっしゃいましたしビジュアライザ2022まとめブログでも言及されているでしょうが、テーマは(広義)VaperWaveでした。2000年前後のインターネット黎明期にあった混沌を再現するためにいろいろやってました。

 僕の担当はビジュアライザのベースシステムと細かい表現とウインドウ全般で、ビジュアライザの回路生成やユーザーの配置はRenard君、デザインとか3DモデルはUzaki君がやってくれました。

こだわりポイント

インスパイア元ネタ

 インスパイア元としてNEEDY GIRL OVERDOSEというゲームがありました。このゲームにも内容とは全く関係ないのに無駄に自由に動かせるウインドウがあり、さらに画面にエフェクトがかかります。

Steam:NEEDY GIRL OVERDOSE
『NEEDY GIRL OVERDOSE』は、最強のインターネットエンジェル(配信者)を目指す承認欲求強めな女の子(超絶最かわてんしちゃん)との生活を描くマルチエンディングADVです。

 こっそりインスパイア元のネタを埋め込んでおきました(気付いたかな?)

↓の歌の歌詞由来です。

 ゲーム内でも聞けるので、ゲームやる予定の人は聞かないほうが良いです。ゲーム内で聞くとエモさ倍増ですよ。

Visualizer背景

 Visualizerの背景である謎ウェーブと太陽がありました。カメラワークの都合であまり見えなかったかもしれませんでしたが、あったんです。

 VaperWaveというとこの謎ウェーブと太陽のイメージが結構強く、Uzaki君からこれを背景にしたいということで制作に取り掛かりました。

vaperwave - Google 検索
画像検索するとめっちゃ出てくる

 山です。丘かもしれない。まず100x100に分割された板ポリを用意しました。そしてシェーダーを使い山の形を成形しつつ、紫の線を描画しました。

 山の形は安定のfbmノイズでの変形です。中央部のほうは高さが低く外側に行くほど高くなっています。こういうメッシュ変形系の作業はシェーダーではなくメッシュの頂点データに対してやった方が何かと都合がいいのですが、時間でウェーブの形を少しづつ変えるというアニメーションを入れようと思っていたため、頂点シェーダーでの変形を行っています。(結局時間での変形は入りませんでしたが)

 空は半径50の球体表面上にこれまたシェーダーで描かれています。シェーダーでやる意味はどこにもないのですが、テクスチャを用意するのが面倒だったのと太陽の位置や形を時間変化したかったので全部シェーダーで書いています。

 球体表面のワールド座標系で太陽の位置やグラデーションの変化を定義しています。空の絵柄はベースのグラデーション、太陽、太陽のブルームの三つの要素からなっており、太陽のブルームを入れることでいい感じのエモさを演出しています。

 限界開発なのもあり、こういう系はマジックナンバーが大量に出現したり、コメントもなく謎処理をしていたりしていて見れたもんではないです。

ウインドウシステム

 ビジュアライザはThree.js、ウインドウはReact-Pixiで作っていました。WebGLラッパーが二つ挟まってて最悪みたいな構成してますね。Three.jsは3D、Pixi.jsは2Dが得意なので分業です。さらにReact-PixiのおかげでReactのレンダラも入っており、バンドルサイズは爆発しました。

 ウインドウシステム自体はもともとDOMで作っていました。

DOM版ウインドウ

 でも気付いちゃったんですよね。ポスプロがかけられないって。ブラウン管エフェクトや歪みを入れたかったので、DOMだとそれができませんでした。html2canvas というライブラリがあり、これはDOMをCanvasで描画することを可能にするんですが、スクリーンショット想定で連続で変換するのには向かなかったり、イベントとかが取れなくなるのはわかっていたので止めました。DOMである必要はないので、Canvasで一から実装し、WebGLでフィルターを掛けました。

 React-PixiはPixi.jsをReactから使えるようにしたライブラリで、Reactの書き味でPixi.jsを使えます。もともとDOMを組んでいたので、それをそのまま同じ感じでPixi.jsで書き直せたのは非常によかったです。今回みたいなゲームというよりアプリケーション寄りなものを作るときはこういうReact実装のライブラリのほうが良いですね(個人の感想です)

Reactのようにコンポーネントに切り分けられる

 Three.js用にもreact-three-fiberというライブラリがあり、ビジュアライザはそれで作ろうかと思ったんですが、僕以外の人がReact使えないので止めました。

 ウインドウ情報をReact contextで管理し、それに基づいてウインドウの描画、アイコンの羅列、タスクバーのタブの描画などを行っています。React contextでほぼすべてのコンポーネントの更新が走るので、ウインドウのリサイズでかなり負荷がかかっていました。パフォーマンスするとしたらここでしたが、時間が無くて後回しになっていました。

ポストプロセシング

 ↑の変更を入れたのはこのためでした。初めはCRTFilterというPixiが用意してるフィルターを使おうと思ったのですが、これはスキャンラインや色ずれを後付けで掛けているだけで、ブラウン管の再現ではなくブラウン管っぽく見える複数フィルターなだけだなぁと思ったので止めました。

 ブラウン管をなるべく実物っぽく再現するにあたり、次の要素を入れました。

 液晶も有機ELもブラウン管も、1ピクセルは赤青緑の三原色からなります。液晶の各色は三色の縦の棒が横に並んだような配置ですが、ブラウン管は三角形に配置されています。(って思ったけど実は単純に方式の違いらしいね草)

ブラウン管 - Wikipedia

 なのでピクセルを三角形に配置します。といっても実際に表示されるのは皆さんの液晶なので工夫します。赤、青、緑の成分しか表示しないピクセルを作り、各色を2ピクセル縦で配置し、1列ごとに3ピクセルずらすことで再現します。(画像見たほうがわかりやすいです。)

各ピクセルの色
実際の画面でのピクセル配置

 ディスプレイ上の物理的な1ピクセルとJSやCSSで定義されている1ピクセルには乖離があり、実際はブラウザの1ピクセル={window.devicePixelRatio}ピクセルとなっています。しかしこのエフェクトではdevicePixelRatioを考慮して皆さんのディスプレイの実解像度で表現することにしています。4Kモニターみたいな解像度がいいものを使っていると実は綺麗に見えすぎてしまったりします。(ブラウザの画面の拡大縮小でピクセルサイズを変えられます)

 一つ注意点として、これはピクセル化シェーダーではありません。ピクセル化シェーダーでは複数ドットで平均を取ったり代表ドットの色を取るなどして分解能を下げます。今回のエフェクトは赤青緑で6ドット消費しているので本来なら1/6の解像度になっているはずですが、実際には高解像度の元画像を特定の色をフィルターに掛けているだけでピクセル化シェーダーのように分解能を下げているわけではないということです。こうすることでエフェクトを通しても文字を読みやすくしています。

 このブラウン管表現について元々いろいろな手法を探っていて、例えば色の強さでピクセルの半径を変えたり、ピクセルの間を開けるなどやってました。ただそのあたりの手法だと全体的に暗かったり、画面に線が入って見づらかったりしたので没になりました。

途中経過 縦並べ

 ディスプレイの湾曲はLensDistortionで再現したのですが、単純に適応すると↑のピクセル別の処理の都合上、変な模様が出現します。(画像だと確認できないので実写で)

 そのため少しだけブラーをかけて軽減しました。それにより、ブラウン管の滲みなんかも表現されて、良くなりました。

 色ずれ、周辺減光は既存の手法そのままを使っています。

小ネタ

 音がなんもなかったのが寂しかったので、マウスクリック音とHDDの回転音を追加して徹底的に昔のパソコンを再現しています。HDDはフリー素材サイトの奴ですが、マウスクリック音は自分が録ったお手製音源です。(大会後に公開されたデモにはHDDの音は入っていません)

ビジュアライザのポスプロ

 ウインドウ全体に掛けるポストプロセシングとは別に、ビジュアライザに掛けるポストプロセシングもありました。ビジュアライザ自体は監視カメラ映像を意識してカメラ切り替えを行っていたので、ビジュアライザ画面上にそれっぽい文字を配置し、画面全体にノイズとスキャンラインのエフェクトを掛け、さらに彩度を下げています。(既存のフィルターの組み合わせ)

ポスプロかける前
後(わかりづらい)

YouAreAnIdiot

Ha!hahahahahaha hahahahaha

 でおなじみのアレです。元ネタは有名なブラクラで、現在は youareanidiot.ccにありますがアクセスはお勧めしません。一応現在は無害らしいですが何があるかわからないのと、結局ポップアップのブロックが無ければ無限にウインドウが増殖してブラウザが破壊されます(一敗)

 開催終了時間に発動するように時限式にしておいたので、ビジュアライザを起動してた人は最後に謎の画面が大量に出てきて困惑したと思います(見てた人いるのかな)

終わりに

 公開が遅れてすいませんでした。ギリギリまでバグと戦ってました。本当は開始少し前に公開して遊んでもらう予定だったのですが、競技中の公開となってしまい、見てくれる人も減ってしまいました。

 でもいろいろ頑張って作ってるから見てほしいな、来年はビジュアライザ見ないと解けない問題ねじ込んで嫌でも見てもらおうかなどと考えています。

Fogrex icon
この記事を書いた人
Fogrex

シェーダーとVRやってます レイマーチ楽しい(゚∀。)

この記事をシェア

このエントリーをはてなブックマークに追加
共有

関連する記事

2023年12月11日
DIGI-CON HACKATHON 2023『Mikage』
toshi00 icon toshi00
2022年4月7日
traPグラフィック班の活動紹介
annin icon annin
2021年8月12日
CPCTFを支えたWebshell
mazrean icon mazrean
2021年5月19日
CPCTF2021を実現させたスコアサーバー
xxpoxx icon xxpoxx
2024年4月14日
unityroomでAddressablesを使った話
inutamago_dogegg icon inutamago_dogegg
2022年4月5日
アーキテクチャとディレクトリ構造
mazrean icon mazrean
記事一覧 タグ一覧 Google アナリティクスについて 特定商取引法に基づく表記