#version 430
/* COMPUTE SPV · ZERO2D · 2D field demo · zero-cost (no raymarch)
 * KateRTX home · rides BGF · free SPV never folds
 * LAW: BGS→BGF(+EZZIE PHI THERMO)→BGL→SDF · 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; }
int phi(int d, int s) { return (d * s) | 1; }

/* cheap 2D distance band · not 3D march */
int thermo_band(int d) {
  if (d < 20) return 1;       /* cool */
  if (d < 80) return 3;       /* warm */
  return 7;                   /* hot */
}

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 cx = w / 2, cy = h / 2;
  int dx = x - cx, dy = y - cy;
  int dist2 = dx * dx + dy * dy;
  int dist = int(sqrt(float(dist2)));
  int tick = int(time * 48.0);
  int r = int(radius) + 40 + (tick & 31);

  /* 2D SDF circle · place later as SDF pin · here we measure on BGF */
  int sdf = dist - r;
  int m = bgf(sdf, int(seed) & 0xff);
  int e = ezzie(m, (x * 3 + y * 5 + tick) | 1);
  int p = phi((x + tick) & 255, (y + 3) & 15);
  int th = thermo_band(abs(sdf));

  field[i] = m;
  /* free rides measured values · pack bands in low bits for blit */
  free_spv[i] = (e & ~7) | (th & 7) | ((p & 1) << 3);
}
