#version 330 core layout(location = 0) in vec3 aPos; layout(location = 1) in vec4 aColor; layout(location = 2) in float aLife; layout(location = 4) in float size; out vec4 vColor; uniform mat4 uMVP; uniform float uScreenHeight; void main() { float alpha; if (aLife < 0.0) { alpha = 1.0; // immortal — fully opaque } else { alpha = clamp(aLife / 2.0, 0.0, 1.0); // fade over last 2 seconds of life } vColor = vec4(aColor.rgb, aColor.a * alpha); vec4 clip_pos = uMVP * vec4(aPos, 1.0); gl_Position = clip_pos; float base_size = 0.5 + (size * 2000); gl_PointSize = max(1.0, base_size / clip_pos.w); }