星座を動的に生成するConstellationShader(星座シェーダー)

AvatarPosted by

はじめに

この記事は GRIPHONE Advent Calendar 2022 14日目の記事になります。

こんにちは、Unityエンジニアの財津です。

ボロノイシェーダーを改良したオリジナルアルゴリズムの星座シェーダーを制作しました。

検証環境

Unity2020.3.10f1

ConstellationShaderとは

動的に星座を次々と生み出していくことができるシェーダーです。パラメータを調整することでより複雑な星座や星座同士の間隔や大きさなどを変えることができます。

ConstellationShaderの仕組み

基本的な基盤はボロノイ図を利用した格子単位のシェーダーで、今回は点と点との間に線を描画するように改良しました。

抜粋したコードはこちらになります。

// 第一点の探索
for (int y = -1; y <= 1; y++)
for (int x = -1; x <= 1; x++)
{
// ボロノイ図
float2 neighbor = float2(x, y);
float2 p = ranDis * sin(aniTime + 6.2831 * random22(ist + neighbor));
float2 diff = neighbor + p - fst;

// 最短距離の更新
if(distance.x > length(diff)){
// 最も近い距離の更新、後ほど丸の描画に使用
distance.x = length(diff);
// 最も近い点
closest = neighbor + p;
}
}

// 第二点の探索
for (int y = -1; y <= 1; y++)
for (int x = -1; x <= 1; x++)
{
// ボロノイ図
float2 neighbor = float2(x, y);
float2 p = ranDis * sin(aniTime + 6.2831 * random22(ist + neighbor));
float2 diff = neighbor + p - fst;

// 一点目と二点目の角度を算出
float d = (1.0 + dot(normalize(closest - fst), normalize(diff))) / 2.0;
// 一点目と二点目の距離を算出
float dis = length(closest-(neighbor + p));

// ピクセルが垂直であるかどうか。一定以上の距離になっているか。 
if(d < _LineThickness && dis > 0.5 && dis < 1.1)
{
// 条件の合った点の座標
secondClosest = neighbor + p;
}
}

使用例

背景として使うことも可能ですが、プロシージャル模様として様々なところにちりばめても面白いと思います。一例としてこのように凝った壁の表現などをする際に使い勝手がいいと思います。

おわりに

格子状シェーダーにはほかにも色々な使い方や表現方法があります。特にプロシージャルという観点で見るとメモリを使わないので他のアセットに容量を割くことができ、それによりさらにグラフィックのクオリティを上げることができると思います。ConstellationShaderにしても更なる改良によってエフェクトへの使い道やAIアルゴリズムとして群衆シミュレーションへの使い道が今後できると思います。