#version 150
const vec2 gridLocationInAtlas = vec2(0.0, 1.0); 
#define COLOR_TOLERANCE 0.08
const float EFFECT_TOLERANCE = 0.02;
const vec3 targetColor = vec3(0.769, 1.0, 1.0);
const vec3 altTrippyColor = vec3(0.031, 0.031, 0.031);

// Increase this to make the circle SMALLER and reduce for BIGGER
const float PARTICLE_SCALE = 4.0; 
// Offset relative to particle
const vec2 CIRCLE_OFFSET = vec2(0.1, -0.28); // x=right, y=up

const float tileSizeInverse = 1.0 / 8.0; 
vec2 atlasSize = textureSize(Sampler0, 0);
vec2 texturePixelSizeInverse = 1.0 / (atlasSize * (1.0 / 64.0));
vec2 uv = texCoord0;
vec4 tintColor = particleTint;

vec2 getGridUV(vec2 localUV, vec2 iconOffset, vec2 gridMaxUV) {
    vec2 safeUV = clamp(localUV, 0.01, 0.99);
    vec2 mapped = (iconOffset + safeUV) * tileSizeInverse;
    return mix(gridMaxUV - texturePixelSizeInverse, gridMaxUV, mapped);
}

vec4 getParticleColor() {
    bool isAltEffect = distance(tintColor.rgb, altTrippyColor) < EFFECT_TOLERANCE;
    bool isTrail = distance(tintColor.rgb, targetColor) < EFFECT_TOLERANCE;
    vec4 activeLight = lightColor;
    
    if (isAltEffect) {
        vec2 gridMaxUV = (gridLocationInAtlas + 1.0) * texturePixelSizeInverse;
        vec2 iconOffset = vec2(0.0, 5.0);
        
        vec2 spriteUV = fract(texCoord0 * (atlasSize / 16.0));
        vec2 centeredUV = spriteUV - 0.5;
        vec2 offsetUV = centeredUV - CIRCLE_OFFSET;
        
        float fakeTime = (gl_FragCoord.x * 0.03) + (sphericalVertexDistance * 2.0);
        float swirl = sin(fakeTime * 6.0 + atan(offsetUV.y, offsetUV.x) * 8.0);
        float ripple = cos((length(offsetUV) * 18.0) - fakeTime * 4.0) * 0.5 + 0.5;
        
        vec2 warpedUV = centeredUV + offsetUV * (0.15 * swirl);
        vec2 textureSampleUV = warpedUV + 0.5;
        uv = getGridUV(textureSampleUV, iconOffset, gridMaxUV);
        vec4 texColor = texture(Sampler0, uv);
        
        float circleRadius = 0.5 / PARTICLE_SCALE;
        float distFromCenter = length(offsetUV);
        float circleMask = smoothstep(circleRadius + 0.03, circleRadius - 0.03, distFromCenter);
        texColor.a *= circleMask;
        
        if (spriteUV.x < 0.0 || spriteUV.x > 1.0 || spriteUV.y < 0.0 || spriteUV.y > 1.0) {
            texColor.a = 0.0;
        }
        
        vec3 altTint = altTrippyColor * (0.6 + 0.4 * ripple);
        vec4 color = texColor * vec4(altTint, 1.0) * ColorModulator;
        color.a *= (0.6 + 0.4 * ripple);
        
        if (color.a < 0.1) discard;
        return color;
    }
    
    if (isTrail) {
        vec2 gridMaxUV = (gridLocationInAtlas + 1.0) * texturePixelSizeInverse;
        vec2 iconOffset = vec2(0.0, 5.0);
        
        vec2 spriteUV = fract(texCoord0 * (atlasSize / 16.0));
        vec2 centeredUV = spriteUV - 0.5;
        vec2 offsetUV = centeredUV - CIRCLE_OFFSET;
        
        float fakeTime = (gl_FragCoord.x * 0.02) + (sphericalVertexDistance * 1.5);
        float pulse = sin(fakeTime * 4.0) * 0.08 + 0.92;
        
        vec2 textureSampleUV = centeredUV + 0.5;
        uv = getGridUV(textureSampleUV, iconOffset, gridMaxUV);
        vec4 texColor = texture(Sampler0, uv);
        
        float circleRadius = 0.5 / PARTICLE_SCALE;
        float distFromCenter = length(offsetUV);
        float circleMask = smoothstep(circleRadius + 0.02, circleRadius - 0.02, distFromCenter);
        texColor.a *= circleMask;
        
        if (spriteUV.x < 0.0 || spriteUV.x > 1.0 || spriteUV.y < 0.0 || spriteUV.y > 1.0) {
            texColor.a = 0.0;
        }
        
        float hueWarp = sin(fakeTime * 7.0 + centeredUV.x * 8.0 + centeredUV.y * 6.0) * 0.5 + 0.5;
        vec3 trippyTint = mix(targetColor, altTrippyColor, hueWarp);
        vec4 color = texColor * vec4(trippyTint, 1.0) * ColorModulator;
        
        float centerGlow = max(0.0, 1.0 - distFromCenter * PARTICLE_SCALE * 2.0) * pulse;
        color.rgb += tintColor.rgb * centerGlow * 0.6;
        color.a *= ColorModulator.a;
        
        if (color.a < 0.1) discard;
        return color;
    }
    
    vec4 color = texture(Sampler0, uv) * tintColor * activeLight * ColorModulator;
    if (color.a < 0.1) discard;
    return color;
}
