前回のぼかし・平滑化と似た処理になりますが、ノイズをなくすのではなく逆に追加して認識しにくくするのが目的です。
今回はノイズ追加、乱反射、RGB分離を行います。
ノイズの追加
乱数は「GLSL
乱数」で最初に出てくるものをお借りします。
fract
(x-floor(x)
)を返すので値域[0 ~ 1]
の乱数です。
1 2 3 4 5 6 7 8 9 10 |
precision highp float; varying vec2 uv; uniform sampler2D t; uniform vec2 resolution; float rand(vec2 co) { return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453); } void main() { gl_FragColor = texture2D(t, uv) * vec4(vec3(rand(uv)+.5), 1); } |
値域を[0.5 ~ 1.5]
にずらして画素値にかけています。
1 |
gl_FragColor = texture2D(t, uv) + vec4(rand(uv)-.5, rand(uv.yx)-.5, rand(uv*uv.xy)-.5, 1); |
あるいはこんな感じにRGB
ごとに違う乱数を使ってカラーノイズを乗せます。
スウィズル演算子で乱数のタネを変えることによって異なる色を作っています。
uv.xx
(uv.yy
)のように片方座標だけを使うと縦ノイズや横ノイズにもなります。
乱反射ノイズ
表示座標からずれた所の画素値を使うことで面影を残しながらノイズを出します。
1 2 3 4 5 6 7 8 9 10 |
#define R 5. float rand(vec2 co) { return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453); } void main() { vec2 p = uv * resolution; p.x += rand(uv.xy) * 2.*R - R; p.y += rand(uv.yx) * 2.*R - R; gl_FragColor = texture2D(t, p / resolution ); } |
rand
で作った乱数の値域を[-R ~ R]
に変換して表示画素の座標に利用します。
スウィズル演算子を逆にしていますが、こうしないと取得する画素座標が注目画素の斜め方向に限定されます。それはそれで味があるともいえるけど。
すりガラス越し(乱反射)のようになりました。
前回のBlur
をした後にこれを使うと少しマイルドになる(逆順でするとサイズにもよりますがただのBlur
に近くなります)。
RGBの分離
RGB
を分離して順番に並べるような形で表示します。
1 2 3 4 5 |
void main() { float x = floor(mod(uv.x*resolution.x,3.)); vec4 k = x==0.?vec4(1,0,0,1):x==1.?vec4(0,1,0,1):vec4(0,0,1,1); gl_FragColor = texture2D(t, uv) * k; } |
昔のディスプレイのようになります。
もしくはよくある表現としてRGB
をそれぞれ別方向にずらす。
距離をD
としてR
が上、G
が左下、B
が右下に動くような座標にしてみます。
1 2 3 4 5 6 7 8 |
#define D .05 void main() { vec4 c = vec4(1); c.r = texture2D(t, uv+vec2(0,-D)).r; c.g = texture2D(t, uv+vec2( 0.866*D,.5*D)).g; c.b = texture2D(t, uv+vec2(-0.866*D,.5*D)).b; gl_FragColor = c; } |
0.866≒√3/2
です。
他にもいろいろあるので気が向いたらどんどん書いていきます。