らんだむちゃん
らんだむちゃんライブのパネルを担当しましたが
公開日:
2020/12/25
らんだむちゃんライブのパネルを担当しましたが

{{< iframe "https://o-atsu.github.io/Randomchan_dance" 560 940 >}}

↑は縮小版です

はじめに

見ていただいたのはらんだむちゃんうぃーく!でも紹介されました、踊ってみた動画です。 動画と言いましたが、マウスでカメラ操作できます。 今回の記事はこちらでの2つのパネルの実装についての話です。 Three.jsでの話にはなりますが、考え方自体は他のエンジンでも使えるのではと思います。

作品の曲入りVer.はこちら、 レポジトリはこちらです。

{{< post 211 >}}

キャンバスに描画

パネルの模様はどちらのパネルもcanvas要素に書き起こしてからテクスチャとして読み込んでます。 バックスクリーンは別のカメラでレンダリングした結果を、ツイートパネルでは初めにツイートを読み込み描画したものを別々のcanvasに描いています。 これでUnityでいうRender Textureに当たるものや2D画像アセットができますね。

ちなみにjavascriptって幾何模様やテキストをcanvasに描画できるんですね、色々使えそう... 例えばこんな感じ?

	const ctx = canvas.getContext('2d');
	//// 以下で開始点(0,0), width x heightの大きさの長方形が描けます. 
	ctx.fillStyle = "rgb(235, 235, 255)";
	ctx.fillRect(0,0,width, height);

パネルへの適用

テクスチャ(模様)の座標と、それに対応するオブジェクト上の座標は[0.0, 1.0]の2次元座標で対応しています。 THREE.PlaneGeometryでは片面のみに割り当てられています。 バックスクリーンパネルではcanvasとアスペクト比の同じパネルを生成し、そのまま貼り付けました。 ツイートパネルでは全ツイートをcanvasに起こしているため、パネルの高さに合うようにテクスチャをy座標方向に拡大しました。 拡大しないで貼り付けると縦方向に圧縮されてしまいますので...

スクロールシェーダー

これはツイートパネル用に作成したシェーダーです。 前述のようにテクスチャを拡大しているので、y軸方向にスクロールしていって表示を切り替える必要があります。 停止と(1ツイート分)スクロールを繰り返していったのですが、これについて時間は与えられるものとして考えてみましょう。

まずは全サイクルの時間とスクロール時間を決めます。 以下時間tを[0, サイクル時間)の範囲で考え、何サイクル目かをnowとしました。

float cycle = 120.0;
float stay = 80.0;
float t = mod(time, cycle); // 剰余
float now = floor(time / cycle); // 商の整数値

後は元の位置からt, nowのときにどれだけテクスチャ座標をずらすかを考えればよいので、スクロールする割合が(t-stay)/(cycle-stay)で与えられることより

texUV.y -= now / num_tweet; // サイクル分ずらす
texUV.y -= max(0.0, t - stay) / (cycle - stay) / num_tweet; // 

と書けます。

スクロール部の実装は以上となります。念のためfract(texUV.y)しておけば値が[0,1]の範囲に収まります。 考えたりテストしたりは時間かかったのにできたものは数行...

以下フラグメントシェーダー全体です。

precision mediump float;
uniform float time;
uniform sampler2D map;
uniform float num_tweet;
varying vec3 vNormal;
varying vec3 vPosition;
varying vec2 vUv;

void main() {
	vec2 texUV = vUv;
	texUV.y = texUV.y * 4.0 / num_tweet;

	float cycle = 120.0;
	float stay = 80.0;
	float t = mod(time, cycle);
	float now = floor(time / cycle);
	texUV.y -= now / num_tweet;
	texUV.y -= max(0.0, t - stay) / (cycle - stay) / num_tweet;

	texUV.y = fract(texUV.y);
	vec3 color = texture2D(map, texUV).rgb;
    gl_FragColor = vec4(color, 0.8);
}

今回のあれやこれやの感想

見てもらえればわかると思うのですがシェーダー触りたてぐらいの実力なんですよね... それに芸術的な関心も薄いのでアート作品の案も浮かばない...まあでも表示に関わる部分ならこんな使い方もありかと感じた次第です。 作品の構成自体は、らんだむちゃんが踊るところにオブジェクトを追加していったシンプルなものになりましたが、ゲームシステムありきでグラフィックを仕上げていっても面白そうですね。

参考資料

バックスクリーンのシェーダー作成時に参考にさせていただきました。

パネル作成に参考にさせていただきました。

loading...