🌵
GLSLのmod関数について理解を深める
GLSLで描いた模様を複製したりする際によく出てくるmod
について理解を深めたい
※VisualStudioCodeでプレビューしながらコードがかけるglsl-canvas
を使用しています
とりあえず使ってみよう
シンプルにグラデーションするコード
左下から右上に向かって黒→白にグラデーションするコード
※座標を正規化し、縦横の長さを合わせるためy > 1.0
をdiscardしています
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
#define PI 3.14159265
void main(){
vec2 r = gl_FragCoord.xy / min(u_resolution.x, u_resolution.y);
if(r.y > 1.0) discard;
float c = length(r);
gl_FragColor = vec4(vec3(c), 1.0);
}
modで複製してみる
void main(){
vec2 r = gl_FragCoord.xy / min(u_resolution.x, u_resolution.y);
if(r.y > 1.0) discard;
vec2 q = mod(r, 0.1);
float c = length(q) / 0.1;
gl_FragColor = vec4(vec3(c), 1.0);
}
縦横それぞれ10分割されたが感覚的になぜこうなるのか理解が難しい...
mod
modの定義
mod() returns the value of x modulo y. This is computed as x - y * floor(x/y).
グラフ化してみる
y = 0.1 | y = 0.5 | y = 1.0 |
---|---|---|
座標空間をy分縮小して繰り返すイメージであることが分かった
yの値によって座標空間を分割しているような動作になるため模様の複製
という手法に用いられることが分かる
mod
を使ったコードを見てみる
それを踏まえてvoid main(){
vec2 r = gl_FragCoord.xy / min(u_resolution.x, u_resolution.y);
if(r.y > 1.0) discard;
vec2 q = mod(r, 0.1);
float c = length(q) / 0.1;
gl_FragColor = vec4(vec3(c), 1.0);
}
vec2 q = mod(r, 0.1);
0.0~1.0に正規化された座標rをmod
によって0.0~0.1の座標空間に縮小している
float c = length(q) / 0.1;
元々は左下から右上に向かっての座標は(0, 0)->(1, 0)であったが、mod
により縮小された座標空間の左下から右上に向かっての座標は(0, 0)->(0.1, 0)となったためグラデーションを表現しているlengh
にも0.1をかけて縮小する必要がある
最後にmod使って適当に作ってみる
void main(){
vec2 r = (gl_FragCoord.xy * 2.0 - u_resolution.xy) / min(u_resolution.x, u_resolution.y);
if(r.y > 0.6) discard;
vec2 q = mod(r, 0.2) - 0.1;
float sV = sin(u_time);
float cV = cos(u_time);
q *= mat2(cV, sV, -sV, cV);
vec2 pos = q + vec2(sin(u_time * 5.0), sin(u_time * 5.0)) * 0.07;
float c = 0.03 / length(pos);
gl_FragColor = vec4(vec3(c), 1.0);
}
Discussion