From 9ecb9f55aaba85f3e7fcb155db7caff84ced5375 Mon Sep 17 00:00:00 2001 From: vHawk <48140945+vHawk@users.noreply.github.com> Date: Mon, 11 Jul 2022 05:43:33 +0300 Subject: [PATCH] Add pheromone settings to GUI --- README.md | 2 ++ src/App.ts | 7 ++----- src/Config.ts | 7 ++++--- src/GUI.ts | 21 +++++++++++---------- src/Renderer.ts | 1 + src/shaders/world.frag | 4 ++-- src/shaders/worldBlur.frag | 4 ++-- 7 files changed, 24 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 70efa16..51a6b16 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ A simple ant colony GPU-accelerated simulation made with Three.js. **[Live demo](https://vhawk.github.io/ants-simulation/)** +![ants collecting food](https://i.imgur.com/FeU3UvR.png) + ## Rules Ants can emit two types of pheromones: to-home pheromone and to-food pheromone. To-home pheromones are emitted by those ants searching for food and to-food pheromones are emitted by those carrying food. Ants searching for food are attracted to to-food pheromones, while ants searching for home are attracted to to-home pheromones. diff --git a/src/App.ts b/src/App.ts index 176d0d5..993e1b1 100644 --- a/src/App.ts +++ b/src/App.ts @@ -34,11 +34,7 @@ export default new class App { this.renderLoop(0); - this.gui.on('antsCount', () => { - this.resetRenderer(); - }); - - this.gui.on('worldSize', () => { + this.gui.on('reset', () => { this.resetRenderer(); }); } @@ -84,6 +80,7 @@ export default new class App { const simStepsToDo = deltaTime / 1000 * Config.simulationStepsPerSecond; this.queuedSimSteps += simStepsToDo; + this.queuedSimSteps = Math.min(this.queuedSimSteps, 10); while (this.queuedSimSteps >= 1) { this.simulationStep(); diff --git a/src/Config.ts b/src/Config.ts index 63342e0..2db78c6 100644 --- a/src/Config.ts +++ b/src/Config.ts @@ -3,11 +3,12 @@ export default { antsCount: 12, simulationStepsPerSecond: 60, scentThreshold: 0.01, - scentFadeOutFactor: 0.998, + scentFadeOutFactor: 0.001, scentBlurRadius: 0.1, scentMaxStorage: 1e6, - scentPerMarker: 300, + scentPerMarker: 200, + scentMaxPerCell: 10, antSpeed: 1, - antRotationAngle: Math.PI / 50, + antRotationAngle: Math.PI / 30, brushRadius: 20, }; \ No newline at end of file diff --git a/src/GUI.ts b/src/GUI.ts index 4b79c5a..fa826d2 100644 --- a/src/GUI.ts +++ b/src/GUI.ts @@ -15,21 +15,22 @@ export default class GUI extends EventEmitter { simFolder.add(Config, 'worldSize', 256, 4096) .name('World size') .step(1) - .onChange(() => { - this.emit('worldSize'); - }); + .onChange(() => this.emit('reset')); simFolder.add(Config, 'antsCount', 0, 22) .name('Ants count 2^') .step(1) - .onChange(() => { - this.emit('antsCount'); - }); + .onChange(() => this.emit('reset')); + simFolder.add(Config, 'scentFadeOutFactor', 0, 0.01) + .name('Pheromone evaporation factor') + .step(0.0001) + .onChange(() => this.emit('reset')); + simFolder.add(Config, 'scentBlurRadius', 0, 0.5) + .name('Pheromone diffusion factor') + .step(0.01) + .onChange(() => this.emit('reset')); simFolder.add(Config, 'simulationStepsPerSecond', 1, 500) .name('Simulation steps per second') - .step(1) - .onChange(() => { - this.emit('simulationStepsPerSecond'); - }); + .step(1); const controlsFolder = this.gui.addFolder('Controls'); diff --git a/src/Renderer.ts b/src/Renderer.ts index e83941a..46eaae9 100644 --- a/src/Renderer.ts +++ b/src/Renderer.ts @@ -133,6 +133,7 @@ export default class Renderer { SCENT_BLUR_RADIUS: Renderer.convertNumberToFloatString(Config.scentBlurRadius), SCENT_MAX_STORAGE: Renderer.convertNumberToFloatString(Config.scentMaxStorage), SCENT_PER_MARKER: Renderer.convertNumberToFloatString(Config.scentPerMarker), + SCENT_MAX_PER_CELL: Renderer.convertNumberToFloatString(Config.scentMaxPerCell), ANT_SPEED: Renderer.convertNumberToFloatString(Config.antSpeed), ANT_ROTATION_ANGLE: Renderer.convertNumberToFloatString(Config.antRotationAngle) }; diff --git a/src/shaders/world.frag b/src/shaders/world.frag index 2bf799f..1d68a30 100644 --- a/src/shaders/world.frag +++ b/src/shaders/world.frag @@ -16,8 +16,8 @@ void main() { int isFood = cellData & 1; int isHome = (cellData & 2) >> 1; int isObstacle = (cellData & 4) >> 2; - float scentToHome = min(10., lastState.y + discreteAnts.x); - float scentToFood = min(10., lastState.z + discreteAnts.y); + float scentToHome = min(SCENT_MAX_PER_CELL, lastState.y + discreteAnts.x); + float scentToFood = min(SCENT_MAX_PER_CELL, lastState.z + discreteAnts.y); if (discreteAnts.z == 1.) { isFood = 0; diff --git a/src/shaders/worldBlur.frag b/src/shaders/worldBlur.frag index b52db82..bce6e4f 100644 --- a/src/shaders/worldBlur.frag +++ b/src/shaders/worldBlur.frag @@ -16,8 +16,8 @@ void main() { vec4 s3 = texture(tWorld, vUv + vec2(-1, 1) * offset); vec4 s4 = texture(tWorld, vUv + vec2(1, -1) * offset); - float scentToHome = (s0.y + s1.y + s2.y + s3.y + s4.y) / 5. * SCENT_FADE_OUT_FACTOR; - float scentToFood = (s0.z + s1.z + s2.z + s3.z + s4.z) / 5. * SCENT_FADE_OUT_FACTOR; + 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); FragColor = vec4( s0.x,