イラスト、モデリング、Unity、VR関連

unityとかblenderとかvr関連の作業メモ

ShadersLaboratryのサンプルを読んでいく記事-surface

Demo 23 - Wireframe like

step(a, x) (x >= a) ? 1 : 0 を返します。

frac(x) x の小数部を返します。

 

step(_LineWidth * 2, frac(IN.worldPos.x / _ParcelSize) + _LineWidth);

frac(IN.worldPos.x / _ParcelSize)は0~1の少数でループする周期的な値を返す

_LineWidth=K,frac =Iとおくと

2K < I + K

K < I =>

_LineWidth <  I のとき1が返る

 

なのでval1,val2は0 or 1

 fixed val = 1 - (val1 * val2);

はval1,val2が両方1のときは0,それ以外は1

lerp(_MainColor, _LineColor, val);

val1,val2が両方1のとき、_LineColorが返る

 

Demo 08 - Circle on terrain

中心から一定範囲内ならLineColorをそうでないならテクスチャカラーを,テクスチャのアルファ値とLineColorのアルファ値を一致させている

 

Demo 09 - Stencil effect invisible crate

 ステンシルバッファを使ったエフェクト、

【Unityシェーダ入門】ステンシルバッファを使って隠れた部分を描く - おもちゃラボ

ShaderLab: ステンシル - Unity マニュアル

ステンシルば1ピクセルあたり8bitの情報を持つ

 

Stencil {
Ref 1
Comp equal
Pass Keep
}

Ref 1,Com equalでステンシルが1の部分だけ描く

Pass Keepは

テンシルテスト(及びデプステスト)をパスした場合、バッファの内容をどうするか決めます。デフォルト: keep

 

Stencil {
Ref 1
Comp always
Pass replace
}

 「Ref 1」としてステンシルバッファを「1」で塗りつぶすことを宣言しています。また、「Comp Always」「Pass Replace」としてブロックを描画する位置は常にステンシルバッファを強制的に「1」にすることを指定しています。

 

ステンシルバッファはデフォルトで0で埋められている。

 

"Custom/Mask" でステンシルに1を書き込み、"Custom/StencilEffect"でステンシルが1の場合にのみテクスチャカラーを返している

 

Demo 07 - Rim effect

面の法線と視線の内積を取って、内積が大きければ、アルファ値を下げて透明度を上げている

 

Demo 06 - Customizable Bump

法線マップと接空間 - しゅみぷろ

ノーマルマップを使っている

UnpackNormalでノーマルマップから法線を取得している

ノーマルマップにはその座標の法線ベクトルが入っている

法線ベクトルのx,y成分を変化させることで光の反射具合を変更している

 

Demo 05 - Scrolling texture

ただのUVスクロール

 

Demo 04 - Snow effect

WorldNormalVector

ピクセル法線マップに基づいて法線ベクトルを取得する

 

o.Normal = UnpackNormal (tex2D(_Bump, IN.uv_Bump));
if(dot(WorldNormalVector(IN, o.Normal), _SnowDirection) >= _SnowLevel)

ローカル座標の法線ベクトルを取得

WorldNormalVectorでワールド座標の法線ベクトルに変換、

SnowDirectionとの内積がSnowLevelより高いければ雪の色を描写している。この内積の比較は上部分にのみ雪を積もらせるためのもの

 

Demo 56 - Triplanar mapping

複数のテクスチャを重ねて表示しているが、

vec /= vec.x + vec.y + vec.z + 0.001f;
fixed4 col = vec.x * col1 + vec.y * col2 + vec.z * col3;

がどういう理屈で書かれてるのかさっぱりわからん

 

Demo 55 - Worldspace texture

ワールド座標を利用したテクスチャマッピング

if(abs(IN.worldNormal.y) > 0.5) 

   o.Albedo = tex2D(_MainTex, IN.worldPos.xz);

法線方向によってテクスチャの向きを変えている

 

Demo 54 - Textures depending normal

回転方向=>法線方向によってテクスチャを切り替えている

 

Demo 46 - Tessellation depending distance camera

テッセレーション

GPUでメッシュを分割することで、より滑らかに表示する、負荷軽量化のための技術らしい

Unity で距離に応じたテッセレーションを行ってみた - 凹みTips

MetalでTessellation - Qiita

UnityのTessellationを使って色々してみる - テラシュールブログ

 

Demo 43 - Misc. rim effect

バリヤーっぽい。

TimeでUVスクロールしつつ、視線とオブジェクトの内積取って透明度を変えている

 

Demo 36 - Discard fragment

テクスチャはノイズテクスチャみたいなのを使用している

テクスチャのr値が一定以上なら描写せず、一定以上ならColorOutSideを返している

 

2回目のパスではCull Frontつまり、裏面のみ描写している

 

Demo 31 - Sepia with final color

セピア色にしている。色の計算式が面白い

 

Demo 29 - Soccer lawn field

しましま模様をつけている

UNITY_INITIALIZE_OUTPUT(Input, o);

指定された 型 の変数を 0 に初期化します。

Japanese Otaku Cityのピンクテクスチャを直す方法について詳しく調べてみた - Qiita

変数の初期化が必要な理由が書かれている

 

o.modelPos = v.vertex;

ローカル座標を代入

 

floor(x) x 以下の最大の整数を返します。

frac(x) x の小数部を返します。

ceil(x) x 以上の最小の整数を返します。

ceil(

  frac(

    floor(

      (IN.modelPos.x - _Offset) / _Width

    )

  / 2)

);

ローカル座標のxからオフセットを引いたものでオブジェクトの幅:Widthで割り、floorで切り捨てで整数を取得し2で割り、fracでその小数部を取得し、今度はceilで切り上げで整数を取得している。

fracで少数になってしまってるのでceilの値は0か1になる

o.Albedo = lerp(col1 * _ColorMain, col1 * _ColorSec, val);

なので、valにはceilの値が入るので、これはどちらかを選択しているfloor(

    (IN.modelPos.x - _Offset) / _Width

)

はxの一定の連続した範囲において、同じ値を返す

 /2をすると、偶数の場合は小数部がゼロになり奇数の場合は少数となるので、最終的にceilで0 or 1になっている

 

Demo 28 - Glass with skybox reflection

【連載】Unity時代の3D入門 – 第7回「キューブマッピング」 – てっくぼっと!

Cubemap - Unity マニュアル

スカイボックスのテクスチャの色を映り込ませている

キューブマップテクスチャから色を取得しPlaneのEmissionに乗算している.

Phongの反射モデル - Wikipedia

BlinnPhong alpha

BlinnPhongは鏡面反射のモデルの一種

 

Outputの描くパラメータは以下
struct SurfaceOutput {
half3 Albedo; // 拡散反射光(=Diffuse)
half3 Normal; // 法線ベクトル
half3 Emission; // エミッション
half Specular; // スペキュラ
half Gloss; // 輝き
half Alpha; // 透過度
};

 

Demo 21 - Simple electric arc

ceil(x) x 以上の最小の整数を返します。

frac(x) x の小数部を返します。

frac(ceil(_Time.y * _Speed) * 0.01);

はceli()はTime.yの一定期間同じ値を返すのでfracも0~0.99で一定期間同じ値を返すことを繰り返す

tex2D(_NoiseTex, float2(time1, time2)).r;

なので、一定期間同じところからノイズの値を取得している

 

uv.y = frac(uv.y + noise);
half4 color = tex2D (_MainTex, uv);

で、ノイズ分、uv.yをずらしている。

テクスチャが縦に流れる雷なので、y方向にずらすといい感じになる

 

Demo 18 - Flatten a model

v.vertex.y = v.vertex.y - (1 + v.vertex.y) * _Elevation;

Elevationの値に応じて、1 ~ v.vertex.yまで変化させている

 

Demo 16 - Pit an object with stencil buffer

"Custom/Silhouette"でステンシルに1を書き込み

ObjectToPitにて

Stencil {
Ref 1
Comp NotEqual
Pass keep
}

なので、1でない場合のみレンダリングしている。

つまり枠内のものを透過している

 

Demo 11 - Fireball with ramp texture

tex2Dlod

vertexシェーダ内でテクスチャを参照する場合は tex2D の代わりに tex2Dlod を使用します。
tex2Dlod( テクスチャ, float4(U値, V値, 0, w =( lod 値の指定0~7 ))
これは テクスチャlodの値がdepth値(カメラからの距離)によって決定されるため depth値がvertexシェーダでメッシュのソートが解決されてPixelシェーダにデータが渡るときに計算が行われるので vertexシェーダ内ではlodの自動割り当てが出来なくなり 直接lod値を指定してあげる必要があるからです。

 

v.vertex.xyz += v.normal * sin(_Time.w + noiseVal * 100)* _Amplitude;

ノイズテクスチャから取得した値も使って法線方向に周期的に膨らませたり縮めたり

 

half4 color = tex2D(_RampTex, float2(saturate(_RampVal + noiseVal), 0.5));

saturate(x) x を [0, 1] の範囲にクランプします。

ランプテクスチャからノイズを色を取得