Activate dormant ants from spawn buffer in shader

This commit is contained in:
Jared Miller 2026-03-11 20:56:25 -04:00
parent b8f49afcc4
commit aa3c94091b
Signed by: shmup
GPG key ID: 22B5C6D66A38B06C

View file

@ -15,6 +15,7 @@ uniform sampler2D tWorld;
uniform sampler2D tPresence;
uniform float uForagerRatio;
uniform sampler2D uMaterialProps;
uniform vec4 uAntSpawn;
const float ANT_CARRY_STRENGTH = 1.0;
const float sampleDistance = 20.;
@ -94,38 +95,68 @@ void main() {
int antIndex = int(vUv.y * float(texSize.y)) * texSize.x + int(vUv.x * float(texSize.x));
if (pos == vec2(0)) { // init new ant
// only activate ants within the start count
if (antIndex >= ANTS_START_COUNT) {
// dormant ant — output zeros and skip everything
bool spawnRequested = (uAntSpawn.w > 0.5);
if (antIndex >= ANTS_START_COUNT && !spawnRequested) {
// dormant ant, no spawn request — skip
FragColor = vec4(0);
FragColorExt = vec4(0);
return;
}
#if VIEW_MODE_SIDE
// spawn on sand surface: random X, scan down from top to find first non-air cell
float spawnX = rand(vUv * 10000.);
float pixelSize = 1.0 / float(textureSize(tWorld, 0).x);
float surfaceY = 0.6; // fallback if scan finds nothing
for (float scanY = 1.0; scanY > 0.0; scanY -= pixelSize) {
float matId = texture(tWorld, vec2(spawnX, scanY)).x;
if (matId > 0.5) { // non-air cell found
surfaceY = scanY + pixelSize; // one cell above the surface
break;
if (antIndex >= ANTS_START_COUNT && spawnRequested) {
// probabilistic activation: ~brushRadius ants per frame
float activationChance = uAntSpawn.z / float(ANT_BUDGET);
float roll = rand(vUv * 50000. + fract(uTime / 1000.));
if (roll > activationChance) {
// not selected this frame — stay dormant
FragColor = vec4(0);
FragColorExt = vec4(0);
return;
}
// activate at spawn position with scatter
float scatter = uAntSpawn.z / WORLD_SIZE;
float rngX = rand(vUv * 10000. + fract(uTime / 1000.));
float rngY = rand(vUv * 20000. + fract(uTime / 1000.) + 0.5);
pos = vec2(
uAntSpawn.x + (rngX - 0.5) * scatter,
uAntSpawn.y + (rngY - 0.5) * scatter
);
pos = clamp(pos, 0., 1.);
angle = rand(vUv * 42069.) * 2.0 * PI;
isCarrying = 0.;
storage = 0.;
personality = rand(vUv * 42069.);
cargoMaterialId = 0.;
pathIntDx = 0.;
pathIntDy = 0.;
} else {
// normal init for starting ants
#if VIEW_MODE_SIDE
// spawn on sand surface: random X, scan down from top to find first non-air cell
float spawnX = rand(vUv * 10000.);
float pixelSize = 1.0 / float(textureSize(tWorld, 0).x);
float surfaceY = 0.6; // fallback if scan finds nothing
for (float scanY = 1.0; scanY > 0.0; scanY -= pixelSize) {
float matId = texture(tWorld, vec2(spawnX, scanY)).x;
if (matId > 0.5) { // non-air cell found
surfaceY = scanY + pixelSize; // one cell above the surface
break;
}
}
pos = vec2(spawnX, surfaceY);
angle = -PI * 0.5; // face downward initially
#else
pos = vec2(0.5);
angle = rand(vUv * 10000.) * 2. * PI;
#endif
isCarrying = 0.;
storage = 0.;
personality = rand(vUv * 42069.); // 0.0 = pure follower, 1.0 = pure explorer
cargoMaterialId = 0.;
pathIntDx = 0.;
pathIntDy = 0.;
}
pos = vec2(spawnX, surfaceY);
angle = -PI * 0.5; // face downward initially
#else
pos = vec2(0.5);
angle = rand(vUv * 10000.) * 2. * PI;
#endif
isCarrying = 0.;
storage = 0.;
personality = rand(vUv * 42069.); // 0.0 = pure follower, 1.0 = pure explorer
cargoMaterialId = 0.;
pathIntDx = 0.;
pathIntDy = 0.;
}
// --- GRAVITY AND SURFACE CHECK ---