diff --git a/src/Renderer.ts b/src/Renderer.ts index 23502e6..8e09a51 100644 --- a/src/Renderer.ts +++ b/src/Renderer.ts @@ -187,6 +187,8 @@ export default class Renderer { this.renderer.setRenderTarget(this.resources.worldBlurredRenderTarget); scenes.worldBlur.material.uniforms.tWorld.value = this.resources.sandPhysicsRenderTarget.texture; + scenes.worldBlur.material.uniforms.uMaterialProps.value = + this.materialPropsTexture; this.renderer.render(scenes.worldBlur, scenes.worldBlur.camera); this.renderer.setRenderTarget(this.resources.antsPresenceRenderTarget); diff --git a/src/scenes/WorldBlurScene.ts b/src/scenes/WorldBlurScene.ts index 3b319a3..6eff84a 100644 --- a/src/scenes/WorldBlurScene.ts +++ b/src/scenes/WorldBlurScene.ts @@ -17,6 +17,7 @@ export default class WorldBlurScene extends AbstractScene { const material = new THREE.RawShaderMaterial({ uniforms: { tWorld: { value: null }, + uMaterialProps: { value: null }, }, vertexShader, fragmentShader, diff --git a/src/shaders/worldBlur.frag b/src/shaders/worldBlur.frag index f7a32d3..beebd9c 100644 --- a/src/shaders/worldBlur.frag +++ b/src/shaders/worldBlur.frag @@ -6,19 +6,33 @@ in vec2 vUv; out vec4 FragColor; uniform sampler2D tWorld; +uniform sampler2D uMaterialProps; const float offset = 1. / WORLD_SIZE * SCENT_BLUR_RADIUS; const float repellentOffset = 1. / WORLD_SIZE * REPELLENT_BLUR_RADIUS; +// returns 1.0 if materialId has GAS behavior (pheromone can diffuse through it) +float isAir(float materialId) { + vec4 props = texelFetch(uMaterialProps, ivec2(int(materialId), 0), 0); + return props.r == BEHAVIOR_GAS ? 1.0 : 0.0; +} + void main() { vec4 s0 = texture(tWorld, vUv); + float centerAir = isAir(s0.x); vec4 s1 = texture(tWorld, vUv + vec2(1, 1) * offset); vec4 s2 = texture(tWorld, vUv + vec2(-1, -1) * offset); 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. * (1. - SCENT_FADE_OUT_FACTOR); - float scentToFood = (s0.z + s1.z + s2.z + s3.z + s4.z) / 5. * (1. - SCENT_FADE_OUT_FACTOR); + float a1 = isAir(s1.x); + float a2 = isAir(s2.x); + float a3 = isAir(s3.x); + float a4 = isAir(s4.x); + + float scentCount = 1.0 + a1 + a2 + a3 + a4; + float scentToHome = (s0.y + s1.y * a1 + s2.y * a2 + s3.y * a3 + s4.y * a4) / scentCount * (1. - SCENT_FADE_OUT_FACTOR) * centerAir; + float scentToFood = (s0.z + s1.z * a1 + s2.z * a2 + s3.z * a3 + s4.z * a4) / scentCount * (1. - SCENT_FADE_OUT_FACTOR) * centerAir; // repellent channel uses its own diffusion radius and decay rate vec4 rr0 = texture(tWorld, vUv); @@ -26,7 +40,14 @@ void main() { 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); + + float b1 = isAir(rr1.x); + float b2 = isAir(rr2.x); + float b3 = isAir(rr3.x); + float b4 = isAir(rr4.x); + + float repellentCount = 1.0 + b1 + b2 + b3 + b4; + float repellent = (rr0.w + rr1.w * b1 + rr2.w * b2 + rr3.w * b3 + rr4.w * b4) / repellentCount * (1. - REPELLENT_FADE_OUT_FACTOR) * centerAir; FragColor = vec4( s0.x,