diff --git a/src/Config.ts b/src/Config.ts index 25f13da..141539a 100644 --- a/src/Config.ts +++ b/src/Config.ts @@ -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, }; diff --git a/src/Renderer.ts b/src/Renderer.ts index 7a3979a..60117b0 100644 --- a/src/Renderer.ts +++ b/src/Renderer.ts @@ -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, + ), }; } diff --git a/src/shaders/world.frag b/src/shaders/world.frag index 1d68a30..94a10ba 100644 --- a/src/shaders/world.frag +++ b/src/shaders/world.frag @@ -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); -} \ No newline at end of file + FragColor = vec4(float(isFood + (isHome << 1) + (isObstacle << 2)), scentToHome, scentToFood, repellent); +} diff --git a/src/shaders/worldBlur.frag b/src/shaders/worldBlur.frag index bce6e4f..f7a32d3 100644 --- a/src/shaders/worldBlur.frag +++ b/src/shaders/worldBlur.frag @@ -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 ); -} \ No newline at end of file +}