This commit is contained in:
Gaël committed 2026-10-19 20:59:15 +02:00
commit 87bff164f1
416 files changed
+279512

No files matched your search

+84
View File
@@ -0,0 +1,84 @@
// Shared by intent/apply/paint/render compute shaders.
//
// Cell word (u32): bits 0-15 material index, 16-23 colour variation, 26 gas/fire horizontal direction.
// Per-cell extension (vec2): x = vertical velocity accumulator, y = horizontal velocity.
// Material table: 3 uvec4 per material
// [0] colour(ARGB), flags, density(float), liquid_gravity(float)
// [1] liquid_viscosity(int), liquid_damping(float), liquid_flow_speed(float),
// gas speeds packed: byte0 gas_speed, byte1 up, byte2 horizontal, byte3 down
// [2] lifetime(int), durability(float), burn word 1 (fire_hp | burnable << 16 | on_fire << 17 | extinguishes << 18), burn word 2 (autoignition | temperature_of_fire << 8 | smoke << 16)
// The last entry of the table is special: (fire id, smoke id, steam id, material count).
layout(std430, set = 0, binding = 0) buffer Cells { uint cells[]; };
layout(std430, set = 0, binding = 1) readonly buffer Mats { uvec4 mats[]; };
layout(std430, set = 0, binding = 2) buffer Pixels { uint pixels[]; };
layout(std430, set = 0, binding = 3) buffer Ext { vec2 ext[]; };
layout(std430, set = 0, binding = 42) buffer Birth { uint birth[]; }; // the frame a cell got its material (cell age = frame - birth, 0070ebf0 req_lifetime)
layout(std430, set = 0, binding = 4) buffer Claims { uint claims[]; };
// per cell: x = target index | (flip direction << 31), y = priority, z/w = new vy/vx bits
layout(std430, set = 0, binding = 5) buffer Intent { uvec4 intent[]; };
layout(push_constant) uniform PC {
int gw, gh; // grid size in cells
int ow, oh; // output size in pixels
int scale; // pixels per cell
int frame;
int pass_; // movement pass within the frame
int brush_x, brush_y, brush_r;
int brush_mat; // -1: none, 0: erase
int seed;
int view_x, view_y; // world cell at the top-left of the grid
int area_ox, area_oy; // world cell at the centre of wang pixel (0,0)
int pw, ph; // wang plane size
int m_rock, m_soil, m_sand, m_wet; // fill materials
int shift_x, shift_y, shift_mode;
int scene_x0, scene_y0, scene_w, scene_h; // pixel-scene plane placement (cells)
int bg_w, bg_h; // biome background tile size (0 = none)
int ent_count; // sprite instances for sprites.comp // terrain.comp: mode 1 = scroll by (shift_x, shift_y), keep the overlap
} pc;
const uint F_STATIC = 1u; // never moves (solid or liquid_static)
const uint F_LIQUID = 2u; // liquid or powder
const uint F_GAS = 4u;
const uint F_SAND = 8u; // powder (liquid_sand)
const uint F_AIR = 16u;
const uint F_FIRE = 32u;
const uint F_LIQCELL = 128u; // cell_type liquid, static or not (the native count / immersion predicate: liquid slot 22 true, powder slot 25 false)
const uint F_POWDER = 256u; // liquid_sand, static or not
const uint F_STAINS = 512u; // liquid_stains: a body in it takes its stain (vine points: the stored material that slows them)
const uint F_NOSTAIN = 2048u; // CellData stainable off (the box2d materials): no explosion burn
const uint F_INDESTRUCT = 1024u; // material tag [indestructible]: a CellEaterComponent with ignored_material_tag leaves it
const uint F_SLIME = 64u; // liquid_slime: moved by 0070b7c0 (docs/IMPLEMENTATION_BLOCKERS.md)
const uint NONE = 0xFFFFFFFFu;
const uint DIR_BIT = 1u << 26;
const uint BURN_BIT = 1u << 27; // the cell is burning
const uint FROZEN_BIT = 1u << 26; // a static cell stained frozen (MagicConvertMaterialComponent stain_frozen; bits 24-25 then hold its damage level, explode_rays.comp)
const uint ATTACH_BIT = 1u << 26; // a powder attached to a wall or ceiling (passive: byte 22 of the original cell); bits 24-25 then hold the direction: 1 right (state 5), 2 above (6), 3 left (7)
// Fire fade (the engine's signed fade byte, in steps of 4): bits 24-25 and 28-31 of the cell word. Burning cells and flames carry it.
uint cell_fade6(uint c) { return ((c >> 28) & 15u) | (((c >> 24) & 3u) << 4); }
uint with_fade6(uint c, uint f) { f = min(f, 63u); return (c & ~0xF3000000u) | ((f & 15u) << 28) | ((f >> 4) << 24); }
// The age of a cell and its fire fade share the birth word: bits 0-23 the frame it got its material (the age is the difference modulo 2^24), bits 24-31 the engine's signed fade byte (cell + 0x11).
const uint BIRTH_MASK = 0xFFFFFFu;
uint birth_frame() { return uint(pc.frame) & BIRTH_MASK; }
uint birth_age(uint b) { return (uint(pc.frame) - b) & BIRTH_MASK; }
int fade_of(uint b) { return int(b) >> 24; } // signed byte
uint with_fade(uint b, int f) { return (b & BIRTH_MASK) | (uint(f & 255) << 24); }
uint cell_mat(uint c) { return c & 0xFFFFu; }
uint mflags(uint m) { return mats[3u * m].y; }
float mdensity(uint m) { return uintBitsToFloat(mats[3u * m].z); }
float mgravity(uint m) { return uintBitsToFloat(mats[3u * m].w); }
int mviscosity(uint m) { return int(mats[3u * m + 1u].x & 0xFFFFu); }
uint mceiling(uint m) { return mats[3u * m + 1u].x >> 16; } // liquid_sticks_to_ceiling (powders)
float mdamping(uint m) { return uintBitsToFloat(mats[3u * m + 1u].y); }
float mflow(uint m) { return uintBitsToFloat(mats[3u * m + 1u].z); }
uint mgasbits(uint m) { return mats[3u * m + 1u].w; }
int mlifetime(uint m) { return int(mats[3u * m + 2u].x); }
uint hash(uint x) {
x ^= x >> 16; x *= 0x7feb352du;
x ^= x >> 15; x *= 0x846ca68bu;
x ^= x >> 16;
return x;
}
uint hash3(uint a, uint b, uint c) { return hash(a * 0x9E3779B1u ^ hash(b + 0x85EBCA6Bu ^ hash(c))); }