#version 300 es
precision highp float;

uniform sampler2D uMainTex;
uniform float uScreenRatio;
uniform float uCellSize; // 控制 Voronoi 单元格的大小

in vec2 v_originTexCoord;
out vec4 fragColor;

// 常量定义
const float HASH_SCALE = 43758.5453;
const float PI = 6.2831;
const float MAX_DISTANCE = 8.0;
const float UV_CLAMP_MIN = 0.01;
const float UV_CLAMP_MAX = 0.99;
const float UV_TRANSITION = 0.0;

// 改进的哈希函数，提供更好的随机性
vec2 hash2(vec2 p) {
    return fract(sin(vec2(
        dot(p, vec2(127.1, 311.7)),
        dot(p, vec2(269.5, 183.3))
    )) * HASH_SCALE);
}

// 计算动画化的特征点位置
vec2 animatePoint(vec2 point) {
    #ifdef ANIMATE_VORONOI
    return 0.5 + 0.5 * sin(PI * point);
    #else
    return point;
    #endif
}

// 计算 Voronoi 单元格的偏移
vec2 calculateVoronoiOffset(vec2 uv, vec2 cellSize) {
    // 计算单元格坐标
    vec2 cellCoord = floor(uv);
    vec2 localCoord = fract(uv);
    
    // 初始化最佳距离和偏移
    float bestDistance = MAX_DISTANCE;
    vec2 bestOffset = vec2(0.0);
    
    // 在3x3邻域内搜索最近的特征点
    for (int j = -1; j <= 1; j++) {
        for (int i = -1; i <= 1; i++) {
            // 计算当前单元格的特征点
            vec2 cellOffset = vec2(float(i), float(j));
            vec2 featurePoint = animatePoint(hash2(cellCoord + cellOffset));
            
            // 计算到特征点的距离
            vec2 delta = cellOffset + featurePoint - localCoord;
            float distance = dot(delta, delta);
            
            // 更新最佳距离和偏移
            if (distance < bestDistance) {
                bestDistance = distance;
                bestOffset = delta;
            }
        }
    }
    
    return bestOffset;
}

void main() {
    // 当单元格大小为0时直接使用原始纹理
    if (uCellSize <= 0.0) {
        fragColor = texture(uMainTex, v_originTexCoord);
        return;
    }
    
    // 计算缩放后的UV坐标
    vec2 cellSize = vec2(1.0, uScreenRatio) * uCellSize;
    vec2 scaledUV = (v_originTexCoord - 0.5) / cellSize;
    
    // 计算 Voronoi 偏移
    vec2 offset = calculateVoronoiOffset(scaledUV, cellSize);
    
    // 应用偏移并恢复原始比例
    vec2 finalUV = (scaledUV + offset) * cellSize + 0.5;
    
    // 平滑的UV过渡
    vec2 clampedUV = mix(
        clamp(finalUV, UV_CLAMP_MIN, UV_CLAMP_MAX),
        v_originTexCoord,
        UV_TRANSITION
    );
    
    fragColor = texture(uMainTex, clampedUV);
}
