Syntax Highlighter を導入してみたからコードがちょっとは見やすくなってるかな?
ここのVignettingからスタートします。
Shader "Custom/WindowCoordinates/Vignetting" { SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma target 3.0 #include "UnityCG.cginc" float4 vert(appdata_base v) : POSITION { return mul (UNITY_MATRIX_MVP, v.vertex); } float4 frag(float4 sp:WPOS) : COLOR { float2 wcoord = sp.xy/_ScreenParams.xy; float vig = clamp(3.0*length(wcoord-0.5),0.0,1.0); return lerp (float4(wcoord,0.0,1.0),float4(0.3,0.3,0.3,1.0),vig); } ENDCG } } }
どでかい Plane にシェーダをはっつけて配置してみました。下の画像は Plane 2枚。
スクリーンの真ん中らへんが色づきます。Vertexシェーダについては特別なことは何一つしてませんね。 : WPOS あたりがわからない場合前回の記事を見てください。
■ clamp(3.0*length(wcoord-0.5),0.0,1.0)
clamp (float value, float min, float max)
value を入力し、その値が min より小さければ min を、max より大きければ max を返す。
vig = 1.0 でピクセルはグレーになります。lerp() の効果ですね。
■ lerp(x, y, s)
ここ。 x が始点、y が終点、 s がどれだけ近づけるか。
lerpはUnityのc#でも頻繁に使いますね。
なんだかいまいちわかりにくいですねぇ。なぜ真ん中に色がつくのか。
float vig = clamp(3.0*length(wcoord-0.5),0.0,1.0);
この -0.5 を変えてみましょう。
-0.0
-0.25
-0.75
なんとなーくわかってきたでしょうか?
実際に数値を入れて考えてみるとわかりやすいかもしれません。
length(wcoord-hoge) の値がゼロに近ければ近いほど色づくんです。
length(wcoord-0.5) でスクリーンど真ん中 wcoord = (0.5, 0.5) の場合、vig はゼロになります。length(0.0, 0.0) はゼロです。
すると return lerp (float4(0.5, 0.5, 0.0, 1.0), float4(0.3, 0.3, 0.3, 1.0), 0.0) となり、画面中央の色にはfloat4(0.5, 0.5, 0.0, 1.0)が適用され暗い黄色になるわけです。
wcoord = (0.0, 0.0) 左上端のピクセルについては length(-0.5, -0.5)
となってしまい3倍すれば vig は 1.0 を軽く超えます。なのでグレーになってしまうのです。
同じように length(wcoord-0.75) で最も明るい部分の wcoord は (0.75, 0.75) ですね。発色は float4(0.75, 0.75, 0.0, 1.0) となりますので先ほどより明るい黄色になります。
それじゃ次いってみましょう。
Shader "Custom/WindowCoordinates/CirclesMask" { Properties { _CirclesX ("Circles in X", Float) = 20 _CirclesY ("Circles in Y", Float) = 10 _Fade ("Fade", Range (0.1,1.0)) = 0.5 } SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma target 3.0 #include "UnityCG.cginc" uniform float _CirclesX; uniform float _CirclesY; uniform float _Fade; float4 vert(appdata_base v) : POSITION { return mul (UNITY_MATRIX_MVP, v.vertex); } float4 frag(float4 sp:WPOS) : COLOR { float2 wcoord = sp.xy/_ScreenParams.xy; float4 color; if (length(fmod(float2(_CirclesX*wcoord.x,_CirclesY*wcoord.y),2.0)-1.0)<_Fade) { color = float4(sp.xy/_ScreenParams.xy,0.0,1.0); } else { color = float4(0.3,0.3,0.3,1.0); } return color; } ENDCG } } }
■ Properties
ここにある変数は Mono側ではなく Unity側の Inspector でいじれるようになります。
ここで宣言したものはもう一度 Pass 内で宣言する必要があります。
うーん…特に目新しいことがないです。
if (length(fmod(float2(_CirclesX*wcoord.x,_CirclesY*wcoord.y),2.0)-1.0)<_Fade)
こういう条件式使えばパンチングできますよ。ってだけですね。やってることは Bars とほとんど同じです。
Inspectorでいろいろいじってみてください。_Fade が数値入力じゃないのが少し面白いかな。次。
Shader "Custom/TextureCoordinates/Base" { SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma target 3.0 #include "UnityCG.cginc" struct vertexInput { float4 vertex : POSITION; float4 texcoord0 : TEXCOORD0; }; struct fragmentInput{ float4 position : SV_POSITION; float4 texcoord0 : TEXCOORD0; }; fragmentInput vert(vertexInput i){ fragmentInput o; o.position = mul (UNITY_MATRIX_MVP, i.vertex); o.texcoord0 = i.texcoord0; return o; } float4 frag(fragmentInput i) : COLOR { return float4(i.texcoord0.xy,0.0,1.0); } ENDCG } } }
またグラデーションです。ただ今回はテクスチャ座標に : WPOS など使っていないので Plane 一枚で完結します。Cube にこのシェーダを適用しても似たようなかんじになります。
左下だけ比較用に CirclesMask を適用しています。
説明することがない…
struct vertexInput を Vertexシェーダ vert の入力に使っていて、vert が吐き出す fragmentInput o をFragmentシェーダの入力に使ってますねー texcoord0はそのまま流用してますねー ってかんじです。
これ以降のものですが…
ChessOpt は RGBa の値に bool値を入れられるということを示しています。
最後の return の RGBa を適当に p, q で置き換えるとちょっといいかんじなものが作れたりします。
Mandelbrot Fractal についてはやる気にならないので(やたら細かい計算をしているだけなので)やりません。
とりあえず Vertex/Fragmentシェーダの基本の『き』ぐらいはできたのかな?できてればいいんですが。
0 件のコメント:
コメントを投稿