フラグメントシェーダーでグリッチをやりたいけど上手くいかない
グリッチ(glitch)ぽい表現
フラグメントシェーダーを利用して、デジタル表現でよくあるグリッチに挑戦したいと思います。
理想は↓です。ただし私ではこの完成度は無理ですが、まずは挑戦してみます。 https://codepen.io/ykob/pen/GmEzoQ
ランダムなラインをつくる
まずはランダムなラインを作ります。
ホワイトノイズを利用してランダムな線を作成します。
precision mediump float; varying vec2 vUv; uniform sampler2D uTex; uniform float uTime; //ノイズ生成関数 float random (vec2 st) { return fract(sin(dot(st.xy, vec2(12.9898,78.233)))* 43758.5453123); } void main(){ float r = random(vec2(u.y * .001)); gl_FragColor = vec4(vec3(r),1.0); }
下記のような絵ができます。
ランダムなラインを動かす
作成したランダムなラインを動かします。 mod関数にuTime(経過時間)を渡しているのは、uTimeをそのまま使うと、徐々にラインの幅が大きくなってしまったので、3.0以上にならないようにしました。
precision mediump float; varying vec2 vUv; uniform sampler2D uTex; uniform float uTime; //ノイズ生成関数 float random (vec2 st) { return fract(sin(dot(st.xy, vec2(12.9898,78.233)))* 43758.5453123); } void main(){ float r = random(vec2(u.y * .001, mod(uTime,3.))); gl_FragColor = vec4(vec3(r),1.0); }
UV座標にノイズを加える
最終的にはテクスチャにノイズを加えたいので、UV座標にこれまでに作成いたラインのノイズを適応します。
precision mediump float; varying vec2 vUv; uniform sampler2D uTex; uniform float uTime; float random (vec2 st) { return fract(sin(dot(st.xy, vec2(12.9898,78.233)))* 43758.5453123); } void main(){ vec2 u = vUv; //ノイズを作成 float r = random(vec2(u.y * .001, mod(uTime,3.))); if (r < 0.1) { u.x += r * .1; } gl_FragColor = texture2D(uTex, u); }
色をずらす
グリッチ感をだすにはRGBの座標をノイズに合わせてずらすと良さそうです。
precision mediump float; varying vec2 vUv; uniform sampler2D uTex; uniform float uTime; float random (vec2 st) { return fract(sin(dot(st.xy, vec2(12.9898,78.233)))* 43758.5453123); } void main(){ vec2 u = vUv; //ノイズを作成 float r = random(vec2(u.y * .001, mod(uTime,5.))); if (r < 0.1) { u.x += r * .1; } if (r < 0.1) { gl_FragColor.r += texture2D(uTex, u + vec2(.01, 0.)).b; gl_FragColor.b += texture2D(uTex, u - vec2(.01, 0.)).g; }else{ gl_FragColor = texture2D(uTex, u); } }
少し調整する
ノイズの感じとかを少し調整します。
precision mediump float; varying vec2 vUv; uniform sampler2D uTex; uniform float uTime; float random (vec2 st) { return fract(sin(dot(st.xy, vec2(12.9898,78.233)))* 43758.5453123); } void main(){ vec2 u = vUv; //ノイズを作成 float r = random(vec2(u.y * .001, mod(uTime * 20.,20.))); if (r < 0.1) { u.x += r * .1; } if (r < 0.1) { gl_FragColor.r += texture2D(uTex, u + vec2(.01, 0.)).b; gl_FragColor.b += texture2D(uTex, u - vec2(.01, 0.)).g; } else if(r > 0.2 && r < 0.205){ gl_FragColor = texture2D(uTex, u + vec2(0., 0.2)); } else{ gl_FragColor = texture2D(uTex, u); } }
まとめ
最終的にはこんな感じになりました。
なんかイマイチです。
参考
ほとんど↓のコードを参考にさせてもらいました。 勿論、vedaのサンプルファイルの方がはるかにかっこいいです。 https://github.com/fand/veda