シェーダー勉強内容(2022年1月)

はじめに

2022年1月に勉強した内容です。
過去の記事はこちら

Unity

開発中のシェーダーの続きを書いていました。
前回から大きな機能の追加などは無く、バグを見つけては直すだったりパラメータの計算式を調整したり…などどいった感じです。

直せないバグはあきらめています。
初めてUnityやVRCのライティングに対応したシェーダーを書いているので分からない部分を完璧にしようとすると完成が見えないのでどうにもならない部分はあきらめています。

パラメータが増えてきて扱いが大変なのでEditor拡張をしました。

有名シェーダーにありそうな見た目にするヤツです。


旗が揺れるシェーダーを作っていました。

旗のシェーダーはよく見ますが同じ旗をたくさん置くと全部の旗が同じ周期で揺れてしまい不自然になるので座標を取得してオブジェクトごとにランダムな周期で揺れる仕組みを作りました。

// ==Random==
float3 originPos = mul(unity_ObjectToWorld, float4(0, 0, 0, 1)).xyz;
float r = rand(originPos) * 2.0 - 1.0;
r *= _RandomMode;

ランダムモードが無効だった場合0が乗算されてrの値は0になります。

あと頂点シェーダーで頂点を移動させた後は法線を再計算しないと見た目がおかしくなることを勉強しました。

// ==generate correct normals==
float4 modifiedPos = v.vertex;
modifiedPos.y += sin(v.vertex.x * _WaveFrequency + time) * _WavePower * vertMask;
    
float3 posPlusTangent = v.vertex + v.tangent * 0.01;
posPlusTangent.y += sin(posPlusTangent.x * _WaveFrequency + time) * _WavePower * vertMask;

float3 bitangent = cross(v.normal, v.tangent);
float3 posPlusBitangent = v.vertex + bitangent * 0.01;
posPlusBitangent.y += sin(posPlusBitangent.x * _WaveFrequency + time) * _WavePower * vertMask;

float3 modifiedTangent = posPlusTangent - modifiedPos;
float3 modifiedBitangent = posPlusBitangent - modifiedPos;

float3 modifiedNormal = cross(modifiedTangent, modifiedBitangent);
v.normal = normalize(modifiedNormal);

// ==MoveVert==
v.vertex = modifiedPos;

結構難しくていろんな海外のサイトを見て回って再計算方法を勉強しました。
数学的なことは少ししかわかってないですが頂点シェーダーで頂点を動かした後は法線を再計算しなくてはいけないということがわかったのでよかったです。


こんな感じでUVをチェックできるシェーダーを遊びで作りました。
これはモデリングしてる人がUVをチェックするのに矢印のテクスチャを張り付けると便利とツイートしていて、矢印の個数をシェーダーで制御出来たらテクスチャを毎回作らなくても便利だなって思ったので作りました。

float sdBox(float2 p, float2 s)
{
    p = abs(p) - s;
    return max(p.x, p.y);
}

float sdTriangle(float2 p, float r)
{
    const float k = sqrt(3.0);
    p.x = abs(p.x) - r;
    p.y = p.y + r/k;
    if( p.x+k*p.y>0.0 ) p=float2(p.x-k*p.y,-k*p.x-p.y)/2.0;
    p.x -= clamp( p.x, -2.0*r, 0.0 );
    return -length(p)*sign(p.y);
}

float map(float2 p)
{
    float d;
    float d1 = sdBox(float2(p.x, p.y+.3), float2(.1, .55));
    float d2 = sdTriangle(float2(p.x, p.y-.3), .5);
    d = min(d1, d2);
    return step(0.02, d);
}

矢印はiq氏の三角形とboxをくっつけて終わりです。三角形を自力で作りたかったのですがうまく作れなかったです。


グリッド線を出すシェーダーを作りました。これ自体の作成日は12月ですがコードを整理したのは1月です。

12月に行われたGameJamで2Dゲームの背景を簡単に作るために作成しました。いちいち背景画像をGIMPなどで作らなくてもUnityのマテリアルで線の太さや線の色、背景の色を設定できるので便利だと思います。

float4 frag (v2f i) : SV_Target
{
    float2 uv = i.uv;
    float2 gv = uv * floor(_Squares);
    float2 ip = floor(gv);
    float2 fp = frac(gv) - .5;
    float3 col = 0.0;
    
    col += Box(fp, _Size);

    col = (col == .0) ? _LineColor : _BGColor;
    return float4(col, 1.0);
}

箱を作ってifで色を分岐させてるだけです。ifを使わないでいい感じにしたかったのですが思いつかなかったです。

クリエイティブコーディング

ライブコーディングをいつかしたいのでそれの練習をしています。

魚眼レンズの作り方を勉強しました。それと久しぶりにレイマーチングをしました。

レイマーチングの原理はなんとなく理解してますが何もないところから書けなかったのでこれを作るときに1から勉強しなおしました。

新年早々レイマーチングしてました。


以降レイマーチングを一から何も見ないで作れるように練習しています。

2日かかってましたが今は5分で作れるようになりました。

レイマーチングは覚えたので他の技法を勉強するためにTDFで紹介されてた技法をいろいろ調べて勉強しています。

FOVの作り方や

魚眼レンズの手法を勉強しました。

ちょっとずつ手持ちの手法が増えてきて何か作れそうな感じです。

その他

エラーが起きるたびに調べたり過去の自分のTwitterを漁ったりしてそこを行ったり来たりする時間が無駄なのでShaderで自分がわからなかったことをまとめたものを作り始めました。

命名とかなんの略称だろう?って思ったりするのでまとめたり…

まわりの友達や学校の人がシェーダーを勉強し始めたりしてるのでいつでも教えたりここのサイト便利だよと教えれる状態にしています。


これからの予定

二月中にはUnityでのシェーダーを完成させる予定を立ててるので完成させたいです。

クリエイティブコーディングの方はいろいろな手法をもっと勉強します。
つぶやきGLSLももう少し挑戦したいですね。

いいなと思ったら応援しよう!