Hex Grid Transition Shader

 

Hex Grid Transition Shader

This shader creates a hexagonal tile–based transition between two textures.
It gradually reveals the new texture over the old one using hex-shaped tiles, producing a smooth and visually appealing scene swap.

Usage Notes:

  • Scene transitions: provide snapshots of the current scene and the target scene as from_tex and to_tex.

  • The shader then animates the hex grid to reveal the new scene.

Parameters:

  • from_tex – Snapshot of the original scene/image

  • to_tex – Snapshot of the target scene/image

  • progress – Transition progress from 0.0 (show from_tex) to 1.0 (show to_tex)

  • hex_size – Size of the hex tiles

  • randomness – Variation in tile reveal timing

  • edge_softness – Smoothness of hex edges

  • transition_speed – Speed of the hex animation

Shader code
shader_type canvas_item;

// ========================
// 输入纹理
// ========================
uniform sampler2D from_tex;
uniform sampler2D to_tex;

// ========================
// 过渡控制
// ========================
uniform float progress : hint_range(0.0, 1.0) = 0.0;

// ========================
// 六边形参数
// ========================
uniform float hex_size : hint_range(0.01, 0.5) = 0.08; // 缩小尺寸,紧密排列
uniform float randomness = 0.05; // 低随机,保证规整
uniform float edge_softness = 0.01; // 锐利边缘,匹配目标
uniform float transition_speed = 0.3;

// ========================
// 工具函数
// ========================
float hash(vec2 p) {
    return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453123);
}

vec2 hextile(inout vec2 p) {
    const vec2 s = vec2(1.0, 1.7320508);
    const vec2 hs = s * 0.5;

    vec2 a = mod(p, s) - hs;
    vec2 b = mod(p - hs, s) - hs;

    vec2 c = dot(a, a) < dot(b, b) ? a : b;
    vec2 id = (c - p + hs) / s;

    p = c;
    return floor(id);
}

float hex(vec2 p, float r) {
    p = abs(p);
    return max(p.x * 0.866025 + p.y * 0.5, p.y) - r;
}


void fragment() {
    vec2 uv = UV;
    vec4 final_color = texture(from_tex, uv);
    
    if (progress > 0.0) {
        vec2 screen_size = vec2(1.0) / SCREEN_PIXEL_SIZE;       
        vec2 p = uv - 0.5;
        float aspect = screen_size.x / screen_size.y;
        p.x *= aspect * 0.9;
        vec2 hp = p / hex_size;
        vec2 id = hextile(hp);
		
        float delay = (uv.x + uv.y) * 0.5;
        float hex_progress = progress >= 1.0 ? 1.0 : smoothstep(
            delay - transition_speed,
            delay + transition_speed,
            progress * (1.0 + transition_speed)
        );
        hex_progress = clamp(hex_progress, 0.0, 1.0);

        float r = hash(id);
        float t = progress >= 1.0 ? 1.0 : clamp(hex_progress - r * randomness, 0.0, 1.0);
        float h = hex(hp, t * 0.9);
        float mask = smoothstep(edge_softness, -edge_softness, h);
        mask = progress >= 1.0 ? 1.0 : mask;

        // 纹理混合
        vec3 from_col = texture(from_tex, uv).rgb;
        vec3 to_col = texture(to_tex, uv).rgb;
        vec3 col = mix(from_col, to_col, mask);
        
        final_color = vec4(col, 1.0);
    }
    
    if (progress >= 1.0) {
        final_color = texture(to_tex, uv);
    }
    
    COLOR = final_color;
}


Live Preview
Tags
2d shader, canvas_item, godot 4, transition
The shader code and all code snippets in this post are under CC0 license and can be used freely without the author's permission. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.

More from muzi1983

Related shaders

guest

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Godot4me
13 days ago

不错, 感谢分享