Add repellent pheromone channel with per-channel blur parameters

This commit is contained in:
Jared Miller 2026-03-09 10:48:14 -04:00
parent cff99b7f08
commit 5899330f5c
Signed by: shmup
GPG key ID: 22B5C6D66A38B06C
4 changed files with 32 additions and 5 deletions

View file

@ -11,4 +11,9 @@ export default {
antSpeed: 1,
antRotationAngle: Math.PI / 30,
brushRadius: 20,
// per-channel pheromone params
repellentFadeOutFactor: 0.0005,
repellentBlurRadius: 0.05,
repellentMaxPerCell: 10,
repellentThreshold: 0.01,
};

View file

@ -195,6 +195,18 @@ export default class Renderer {
ANT_ROTATION_ANGLE: Renderer.convertNumberToFloatString(
Config.antRotationAngle,
),
REPELLENT_FADE_OUT_FACTOR: Renderer.convertNumberToFloatString(
Config.repellentFadeOutFactor,
),
REPELLENT_BLUR_RADIUS: Renderer.convertNumberToFloatString(
Config.repellentBlurRadius,
),
REPELLENT_MAX_PER_CELL: Renderer.convertNumberToFloatString(
Config.repellentMaxPerCell,
),
REPELLENT_THRESHOLD: Renderer.convertNumberToFloatString(
Config.repellentThreshold,
),
};
}

View file

@ -10,7 +10,7 @@ uniform sampler2D tDiscreteAnts;
void main() {
vec4 lastState = texture(tLastState, vUv);
vec3 discreteAnts = texture(tDiscreteAnts, vUv).xyz;
vec4 discreteAnts = texture(tDiscreteAnts, vUv);
int cellData = int(lastState.x);
int isFood = cellData & 1;
@ -18,10 +18,11 @@ void main() {
int isObstacle = (cellData & 4) >> 2;
float scentToHome = min(SCENT_MAX_PER_CELL, lastState.y + discreteAnts.x);
float scentToFood = min(SCENT_MAX_PER_CELL, lastState.z + discreteAnts.y);
float repellent = min(REPELLENT_MAX_PER_CELL, lastState.w);
if (discreteAnts.z == 1.) {
isFood = 0;
}
FragColor = vec4(float(isFood + (isHome << 1) + (isObstacle << 2)), scentToHome, scentToFood, 0);
FragColor = vec4(float(isFood + (isHome << 1) + (isObstacle << 2)), scentToHome, scentToFood, repellent);
}

View file

@ -8,6 +8,7 @@ out vec4 FragColor;
uniform sampler2D tWorld;
const float offset = 1. / WORLD_SIZE * SCENT_BLUR_RADIUS;
const float repellentOffset = 1. / WORLD_SIZE * REPELLENT_BLUR_RADIUS;
void main() {
vec4 s0 = texture(tWorld, vUv);
@ -19,10 +20,18 @@ void main() {
float scentToHome = (s0.y + s1.y + s2.y + s3.y + s4.y) / 5. * (1. - SCENT_FADE_OUT_FACTOR);
float scentToFood = (s0.z + s1.z + s2.z + s3.z + s4.z) / 5. * (1. - SCENT_FADE_OUT_FACTOR);
// repellent channel uses its own diffusion radius and decay rate
vec4 rr0 = texture(tWorld, vUv);
vec4 rr1 = texture(tWorld, vUv + vec2(1, 1) * repellentOffset);
vec4 rr2 = texture(tWorld, vUv + vec2(-1, -1) * repellentOffset);
vec4 rr3 = texture(tWorld, vUv + vec2(-1, 1) * repellentOffset);
vec4 rr4 = texture(tWorld, vUv + vec2(1, -1) * repellentOffset);
float repellent = (rr0.w + rr1.w + rr2.w + rr3.w + rr4.w) / 5. * (1. - REPELLENT_FADE_OUT_FACTOR);
FragColor = vec4(
s0.x,
scentToHome < SCENT_THRESHOLD ? 0. : scentToHome,
scentToFood < SCENT_THRESHOLD ? 0. : scentToFood,
0
repellent < REPELLENT_THRESHOLD ? 0. : repellent
);
}