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 件のコメント:
コメントを投稿