#ifndef STARS_GLSL
    #define STARS_GLSL a

    // from Photon v1.0

    // Stars based on https://www.shadertoy.com/view/Md2SR3

    vec3 unstable_star_field(vec2 coord, float star_threshold) {
        const float min_temp = 3500.0;
        const float max_temp = 9500.0;

        vec4 noise = hash4(coord);

        float star = linearstep(star_threshold, 1.0, noise.x);
              star = pow4(star) * STARS_INTENSITY;

        float temp = mix(min_temp, max_temp, noise.y);
        vec3 color = blackbody(temp);

        const float twinkle_speed = 2.0;
        float twinkle_amount = noise.z;
        float twinkle_offset = _2PI * noise.w;
        star *= 1.0 - twinkle_amount * cos(float(frameCounter) * (1.0/20.0) * twinkle_speed + twinkle_offset);

        return star * color;
    }

    vec3 stable_star_field(vec2 coord, float star_threshold) {
        coord = abs(coord) + 33.3 * step(0.0, coord);
        vec2 i = floor(coord);
        vec2 f = coord - i;

        f.x = cubicsmooth(f.x);
        f.y = cubicsmooth(f.y);

        return unstable_star_field(i + vec2(0.0, 0.0), star_threshold) * (1.0 - f.x) * (1.0 - f.y)
             + unstable_star_field(i + vec2(1.0, 0.0), star_threshold) * f.x * (1.0 - f.y)
             + unstable_star_field(i + vec2(0.0, 1.0), star_threshold) * f.y * (1.0 - f.x)
             + unstable_star_field(i + vec2(1.0, 1.0), star_threshold) * f.x * f.y;
    }

    vec3 render_stars(vec3 ray_dir) {
        float star_threshold = 1.0 - 0.008 * STARS_COVERAGE;

        vec2 coord = ray_dir.xy * rcp(abs(ray_dir.z) + length(ray_dir.xy)) + 41.21 * sign(ray_dir.z);
             coord *= 600.0;

        return stable_star_field(coord, star_threshold);
    }

#endif