7
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

さて、この記事は前回の記事
「ポケポケのホログラム表現に挑戦①」

の続きであります
この記事が初見の方は最初にそちらを読んでもらうとより理解が深まるかと思います

ポケポケのホログラム表現に挑戦②

今回のテーマは「プロシージャル」です。プロシージャルとは実際にテクスチャを事前に用意するのではなく、計算によってテクスチャを生成する事です。

今回も例によって
以下の記事に基づいて考えていこうと思います

マーブル背景

記事の一部を抜粋します
image.png
さて、このマーブル模様。テクスチャじゃないんです。どうやって書いてるんでしょう?
キーワードは

  • セルラーノイズ
  • 影響値→等高線
  • PD制御(なにそれ)

です。一つずつやればまぁ完ぺきとはいかなくとも何とかなるでしょ
さぁ、頑張って実装していきましょう

セルラーノイズ

えっ!?ノイズ?ノイズなんて役に立つの?と思われるかもしれませんが、CGではノイズの利用は必須だと思ってください。
興味がある方はこのサイトを読んでみましょう
https://thebookofshaders.com/11/?lan=jp

様々な模様がノイズをもとにして作られています。まずは普通にランダムなノイズを作ってみましょう。本当はXorShiftをやりたいのですが変なパターンが出てうまくいかなかったため、いつものfrac(sin(でやろうと思います
https://x.com/CTsuchinoko/status/2001155931091189943
いつもの

普通のノイズ

float GenerateRandomNoise(float2 st)
{
    return frac(sin(dot(st.xy, float2(12.9898, 78.233))) * 43758.5453123);
}

この乱数の値を濃淡値として画面上に出力すると当然こうなります

float r = GenerateRandomNoise(input.uv);
return float4(r, r, r, 1);

image.png

ブロックノイズ

次にこれを特定の大きさの格子状にぶった切ります
image.png
もちろん線は必要ないです。区分けをするだけです
仮に0.1ごとにぶった切るならこう(アス比考慮しています)

uint3 dims;
tex.GetDimensions(0,dims.x,dims.y,dims.z);
float aspect = (float) dims.x / (float)dims.y;
float2 gridSize = float2(0.1, 0.1*aspect);
float2 gridUV = floor(input.uv / gridSize);
float r = GenerateRandomNoise(gridUV);
return float4(r, r, r, 1);

image.png
これがいわゆるブロックノイズですね。でも今回作りたいのはセルラーノイズ。いったいどういうノイズなんでしょうか

セルラーノイズ(飽体ノイズの一種)とは?

ブロックノイズやバリューノイズは最初のノイズをもとに加工して作るものでした。それにたいしてセルラーノイズは幾何学的なノイズを生成して、そこから多様な模様を生み出すものです。
飽体ノイズにはセルラーノイズのほかにウォーリーノイズなんてのもあるようです

それはともかくセルラーノイズですね

ブロックノイズを作る際に格子状の領域に分けましたが、そのひとつひとつを「セル」と言います。

ではセルラーノイズの作り方の手順ですが、こうします

  1. まず、それぞれのセル内のランダムな位置の点を乱数で生成します
    1. 生成のシードは格子点ごとに固定とする
  2. 現在のピクセルから見た直線距離を測る
    1. このとき現在のピクセルが属するセルを含めて9近傍(8近傍+1)測る
  3. その9近傍内の点から最も近い点を選択する
  4. その距離をもとに塗りつぶし等の処理を行う

このような形です
(Claudeによる図)
image.png
(GenSparkによる図)
image.png
ちょっとこれ両方の図とも微妙なんですが、間違えないで欲しいのは8近傍ではなく9近傍のセルなのを忘れないでください
AIに作らせたら分かりづらいため、結局自分でプログラム書きましたが
image.png
image.png
image.png

こんな感じで最短の矢印を求めます(赤いのが最短矢印)
で、この赤の矢印の長さを濃淡値に変換するとこうなります。
image.png
グリッドを外すと、こう
image.png

これがセルラーノイズです
今回はクソデカグリッドくんなので4分割でこんな感じ
image.png

マーブルシェーダ

つぎに、「ポイントに影響度を持たせて、距離と影響度をもとに色を決定」する
image.png

とあるけど、距離はともかく影響度ってなんだ?
記事の説明を読むと、プラスとマイナスで影響度を計算するとあるため、恐らくそれぞれのセルに+かーを割り当て、それを9近傍セルで合計すると言ったところだろう。
で、この影響度には距離によるウェイトがかかると考えると先ほどのセルラーノイズで作った距離関数が使えそうだ

疑似コード

float totalAffect = 0.0f;
float totalWeight = 0.0f;
for(int yidx=minYIdx;yidx<=maxYIdx;++yidx){
	for(int xidx=minXIdx;xidx<=maxXIdx;++xidx){
		int pidx = yidx * grid_columns + xidx;
		float2 pos = float2( (float)x ,(float)y  );		
		float len = distance(points[pidx],pos);
		float weight = 1.0f / (len*len + 0.01f);
		totalAffect += affectValues[pidx] * weight;
		totalWeight += weight;
	}
}
float affect = (totalAffect / totalWeight)*0.5+0.5;//-1~1になっているため範囲を修正

するとこうなりました
image.png
いい感じに見えるかもしれませんが、セルごとにエッジが残ってしまっている箇所があります。これは恐らくですがセル数が9を超えてしまうとその隣のセルとの整合性が合わずにこれが発生しているものと思われます。例えば4x4ならばこう
image.png
↓動画
https://x.com/CTsuchinoko/status/2005132376054350257

セル数9ならばこう
image.png
ってんんー?やっぱりエッジ出とるやんけー!!
もともとセルラーノイズの9近傍は沢山のセルがあった場合のメモリの効率化だったため、マーブルシェーダの場合はもう割り切って「全てのセル」の距離を測る事にする。総セル数が4個~16個とかなら問題ないでしょ
ということで9近傍の制約を取っ払ったのがこちら
image.png

動画↓
https://x.com/CTsuchinoko/status/2005136753733271898

歪み

さて、次にこれを歪ませるわけですが、どうしましょうか・・・?
image.png
パッと見た感じ「せん断変形」+中心からの距離による回転を行っているように見えます

せん断変形

せん断変形とは長方形を平行四辺形にするように、上辺と下辺を互い違いにずらす変形です
行列で書くとこう

\begin{pmatrix}
1&m\\
0&1
\end{pmatrix}
\begin{pmatrix}
x\\
y
\end{pmatrix}=
\begin{pmatrix}
x+my\\
y
\end{pmatrix}

中心からの距離で回転

まず、中心(cnt)を計算しますがこれは大したことがなく、中心からの距離(dist)も現在のピクセルとの距離を測っておけばいい

float2 cnt=float2(0.5,0.5);
float dist = float2(cnt,uv); 

次にこれを用いて回転角とします。つまり

float theta=dist*0.01;

後はこれを用いて回転させるだけですが、最初に求めておいた中心点を中心にするのを忘れずに

\begin{pmatrix}
1&0&cx\\
0&1&cy\\
0&0&1
\end{pmatrix}

\begin{pmatrix}
cos\theta&-sin\theta&0\\
sin\theta&cos\theta&0\\
0&0&1
\end{pmatrix}
\begin{pmatrix}
1&0&-cx\\
0&1&-cy\\
0&0&1
\end{pmatrix}
\begin{pmatrix}
x\\
y\\
1
\end{pmatrix}

さきほどのせん断変形と組み合わせると
image.png
ままえあろ

あとはこれをもとに、テクスチャを適用しましょう

テクスチャを適用

image.png
あとはこれですね。さすがにこれはプロシージャルじゃなくて外から持ってきましょう。プロシージャルでもいいんですが、流石にメンドクサイので資料の奴を真似て作りました(AIに作らせました)
image.png

やることは簡単です。前回までで、赤と青の模様を作っていますが、これは0~1を色に変換しただけの事ですので、0~1をUV座標のUとして取り扱えば勝手にマーブル模様になります

image.png

↓動画
https://x.com/CTsuchinoko/status/2005157060904997110

はい、ここまで進んだ段階で時間的に厳しくなったため、一旦ここで区切ります。
と言う事で、次回の③をしばらくお待ちください

書けました

7
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?