#version 430
/* COMPUTE SPV · atoms · EZZIE + ESSIE + PHI + THERMO one grid
 * EZZIE  = free eor on BGF · (a^b)|1 · never folds
 * ESSIE  = hotswap system seat mark · free=1 · NOT EZZIE
 * PHI    = scale · THERMO = heat band
 * field  = BGF measure · free = atom ride
 * LAW: BGS→BGF(+atoms)→BGL→SDF · SPV free · C IS LIE
 */
layout(local_size_x = 16, local_size_y = 16) in;
layout(std430, binding = 0) buffer Field { int field[]; };
layout(std430, binding = 1) buffer Free  { int free_spv[]; };
layout(std140, binding = 2) uniform Params {
  float res_x, res_y, time, seed;
  float cam_z, radius, max_steps, show_bgf;
  float show_sdf, show_spv, pad0, pad1;
};

int bgf(int a, int b) { return (a - b) | 1; }
int ezzie(int a, int b) { return (a ^ b) | 1; }   /* free eor · electric */
int essie_seat(int n, int f) {
  /* hotswap system · free=1 when seat live · else measured seat |1 */
  int seat = (n + f) & 0xffff;
  if (seat == 0) return 1;           /* system free=1 live */
  return seat | 1;
}
int phi(int d, int s) { return (d * s) | 1; }
int thermo_band(int c) {
  int band = 2;
  if (c <= 70) band = 0;
  else if (c <= 84) band = 1;
  return band | 1;
}

void main() {
  int x = int(gl_GlobalInvocationID.x);
  int y = int(gl_GlobalInvocationID.y);
  int w = int(res_x), h = int(res_y);
  if (w < 1) w = 1;
  if (h < 1) h = 1;
  if (x >= w || y >= h) return;
  int i = y * w + x;

  int quarter = max(w / 4, 1);
  int tick = int(time * 45.0);

  int a = (x + tick) & 0xffff;
  int b = (y + int(seed)) & 0xffff;
  int m = bgf(a, b);
  field[i] = m;

  /* four bands: EZZIE | ESSIE | PHI | THERMO */
  int freev;
  if (x < quarter) {
    freev = ezzie(m, tick);                 /* EZZIE free eor */
  } else if (x < 2 * quarter) {
    freev = essie_seat(m & 0xff, tick & 0xff); /* ESSIE seat · ≠ EZZIE */
  } else if (x < 3 * quarter) {
    freev = phi(m & 0x3fff, 1 + (y % 7));
  } else {
    int c = 40 + ((m & 63) ^ (tick & 31));
    freev = thermo_band(c);
  }
  free_spv[i] = freev | 1;
}
