🔯

GLSLで正六角形タイリング

2024/10/29に公開

GLSLで正六角形タイリングを実装します。

実装の考え方はコードをコメントアウトしながら動作確認すればわかりますが、正六角形を上下の三角形と真ん中の長方形に分けて計算するようになっています。

vec2 equilateralHexagonTiling(vec2 p, out vec2 index) {
    const float WIDTH = sqrt(3);
    const float HALF_WIDTH = 0.5 * WIDTH;
    const float TRIANGLE_HEIGHT = 0.5;
    const float SIDE_LENGTH = 1.0;
    const float ROW_HEIGHT = SIDE_LENGTH + TRIANGLE_HEIGHT;
    const float TRIANGLE_SKEW = sqrt(3);

    vec2 q = p;
    index.y = floor(q.y / ROW_HEIGHT);
    q.y = mod(q.y, ROW_HEIGHT);
    bool isEvenRow = int(mod(index.y, 2.0)) == 0;
    
    if (q.y < TRIANGLE_HEIGHT) { // top and bottom triangles
        q.x += isEvenRow ? HALF_WIDTH : 0;
        q.x -= TRIANGLE_SKEW * q.y;
        index.x = floor(q.x / WIDTH);
        q.x = mod(q.x, WIDTH);
        if (q.x / WIDTH + q.y / TRIANGLE_HEIGHT < 1.0) { // top triangle
            index -= vec2(isEvenRow ? 1 : 0, 1);
            q.y += ROW_HEIGHT;
        } else { // bottom triangle
            q.x -= HALF_WIDTH;
        }
        q.x += TRIANGLE_SKEW * mod(q.y, ROW_HEIGHT);
    } else { // center rectangle
        q.x -= !isEvenRow ? HALF_WIDTH : 0;
        index.x = floor(q.x / WIDTH);
        q.x = mod(q.x, WIDTH);
    }

    return q;
}

equilateralHexagonTiling関数は引数pで与えられた位置から1辺の長さが1の正六角形でタイリングしたときの正六角形の座標値を返します。

vec2 p = v_texcoord * resolution / min(resolution.x, resolution.y) * 10.0;
vec2 index;
vec2 q = equilateralHexagonTiling(p, index);
gl_FragColor = vec4(q, 0.0, 1.0);

引数indexは同じ正六角形内の座標は同じ値を返します。

float rand(vec2 co){
    return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
}

vec3 random(vec2 v) {
    return vec3(rand(v), rand(v + 100.0), rand(v + 200.0));
}

gl_FragColor = vec4(random(index), 1.0);

Discussion