🌵

GLSLのmod関数について理解を深める

2023/11/13に公開

GLSLで描いた模様を複製したりする際によく出てくるmodについて理解を深めたい

※VisualStudioCodeでプレビューしながらコードがかけるglsl-canvasを使用しています
https://marketplace.visualstudio.com/items?itemName=circledev.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).

https://thebookofshaders.com/glossary/?search=mod

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