From 0f0944f9ee78c28a947957ad92e59fc97f1dbbeb Mon Sep 17 00:00:00 2001 From: Yehonatan Daniv Date: Sun, 10 Nov 2024 13:47:05 +0200 Subject: [PATCH 1/4] Initial work on Water-like Displacement effect --- CHANGELOG.md | 7 ++ demo/demo.js | 11 ++- demo/index.html | 16 ++++ demo/index.js | 11 ++- demo/multi-pointer.js | 167 ++++++++++++++++++++++++++++++++++++ dist/index.cjs | 4 +- index.js | 2 +- index.umd.js | 4 +- src/effects/displacement.js | 2 +- 9 files changed, 216 insertions(+), 8 deletions(-) create mode 100644 demo/multi-pointer.js diff --git a/CHANGELOG.md b/CHANGELOG.md index bf946f7..1cb7cca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +### 0.x.x (2024-xx-xx) + +_New:_ + +- Extended `displacement` effect to support blue channel for intensity. +- Added `multi-pointer` demo. + ### 0.10.2 (2024-08-25) _Fixed:_ diff --git a/demo/demo.js b/demo/demo.js index 734821d..9135f7a 100644 --- a/demo/demo.js +++ b/demo/demo.js @@ -154,9 +154,18 @@ const sectionScripts = { refresh: 'refresh9', }); }, + + section10() { + startDemo('./multi-pointer.js', { + code: 'code10', + preview: 'preview', + refresh: 'refresh10', + }); + }, }; -insertSection('section7'); +insertSection('section10'); + // on load get active section from url hash and set const hash = window.location.hash.substring(1); diff --git a/demo/index.html b/demo/index.html index 9be3cd3..a09ebcd 100644 --- a/demo/index.html +++ b/demo/index.html @@ -313,6 +313,17 @@ + +
diff --git a/demo/index.js b/demo/index.js index 37461cc..aaa54cc 100644 --- a/demo/index.js +++ b/demo/index.js @@ -157,9 +157,18 @@ refresh: 'refresh9', }); }, + + section10() { + startDemo('./multi-pointer.js', { + code: 'code10', + preview: 'preview', + refresh: 'refresh10', + }); + }, }; - insertSection('section7'); + insertSection('section10'); + // on load get active section from url hash and set const hash = window.location.hash.substring(1); diff --git a/demo/multi-pointer.js b/demo/multi-pointer.js new file mode 100644 index 0000000..6008094 --- /dev/null +++ b/demo/multi-pointer.js @@ -0,0 +1,167 @@ +import { Kampos, effects } from '../index.js'; + +/*! + * Adapted from Daniel Velasquez's "Creating a Water-like Distortion with Three.js" + * https://tympanus.net/codrops/2019/10/08/creating-a-water-like-distortion-effect-with-three-js/ + */ + +const target = document.querySelector('#target'); +const mapTarget = document.createElement('canvas'); + +const easeOutSine = (t, b, c, d) => { + return c * Math.sin((t / d) * (Math.PI / 2)) + b; +}; + +const easeOutQuad = (t, b, c, d) => { + t /= d; + return -c * t * (t - 2) + b; +}; + +class PointerTexture { + constructor ({ target, width, height, radius, intensity, maxAge, canvas }){ + this.width = width; + this.height = height; + this.radius = radius; + this.intensity = intensity; + this.maxAge = maxAge; + this.last = null; + this.points = []; + this.ctx = canvas.getContext('2d'); + + target.addEventListener('pointermove', this.addPoint.bind(this)); + } + + clear() { + this.ctx.fillStyle = 'rgba(127, 127, 127, 1)'; + this.ctx.fillRect(0, 0, this.width, this.height); + } + + addPoint (e){ + const point = { + x: e.offsetX / this.width, + y: e.offsetY / this.height, + age: 0, + }; + + if (this.last) { + const relatveX = point.x - this.last.x; + const relatveY = point.y - this.last.y; + + const speedSquared = relatveX ** 2 + relatveY ** 2; + const speed = Math.sqrt(speedSquared); + + point.vx = relatveX / (speed + 1e-5); + point.vy = relatveY / (speed + 1e-5); + + point.speed = Math.min(speedSquared * 1e3, 1); + } + + this.last = point; + + this.points.push(point); + } + + update () { + this.clear(); + this.points.forEach((point, i) => { + const decay = 1 - point.age / this.maxAge; + const force = point.speed * decay / this.maxAge; + point.x += point.vx * force; + point.y += point.vy * force; + point.age += 1; + + if (point.age > this.maxAge) { + this.points.splice(i, 1); + } else { + this.drawPoint(point); + } + }); + } + + drawPoint (point) { + const position = { + x: point.x * this.width, + y: point.y * this.height + }; + let intensity = 1; + if (point.age < this.maxAge * 0.3) { + intensity = easeOutSine(point.age / (this.maxAge * 0.3), 0, 1, 1); + } else { + intensity = easeOutQuad( + 1 - (point.age - this.maxAge * 0.3) / (this.maxAge * 0.7), + 0, + 1, + 1 + ); + } + intensity *= point.speed; + + const red = (1 - point.vx) / 2 * 255; + const green = (point.vy + 1) / 2 * 255; + const blue = intensity * 255; + + const offset = this.width * 5; + this.ctx.shadowOffsetX = offset; + this.ctx.shadowOffsetY = offset; + this.ctx.shadowBlur = this.radius; + this.ctx.shadowColor = `rgba(${red}, ${green}, ${blue}, ${this.intensity * intensity})`; + + this.ctx.beginPath(); + this.ctx.fillStyle = 'rgba(255, 0 , 0, 0, 1)'; + this.ctx.arc(position.x - offset, position.y - offset, this.radius, 0, 2 * Math.PI); + this.ctx.fill(); + } +} + +const MAP_WIDTH = 1396; +const MAP_HEIGHT = 992; +const DEBUG = false; + +loadImage( + `https://picsum.photos/${MAP_WIDTH}/${MAP_HEIGHT}?random=1`, +).then((img) => { + const height = window.innerHeight; + const width = (height * img.naturalWidth) / img.naturalHeight; + + target.width = width; + target.height = height; + + mapTarget.width = width; + mapTarget.height = height; + + // const render = new Kampos({ target: mapTarget, effects: [pointer], noSource: true }); + const pointerTexture = new PointerTexture({ + target, + width, + height, + canvas: DEBUG ? target : mapTarget, + radius: 150, + intensity: 1.2, + maxAge: 64 + }); + + // create the main instance that renders the displaced image + const displacement = effects.displacement(); + displacement.map = mapTarget; + displacement.scale = { x: 0, y: 0}; + displacement.textures[0].update = true; // to update + + if (DEBUG) { + function tick () { + requestAnimationFrame(tick); + + pointerTexture.update(); + } + + requestAnimationFrame(tick); + } else { + const instance = new Kampos({target, effects: [displacement]}); + + // // set media source + instance.setSource({media: img, width, height}); + + instance.play(() => { + pointerTexture.update(); + }); + } +}); diff --git a/dist/index.cjs b/dist/index.cjs index 23c4107..e6d100a 100644 --- a/dist/index.cjs +++ b/dist/index.cjs @@ -803,7 +803,7 @@ function displacement({ wrap = WRAP_METHODS.CLAMP, scale } = {}) { source: ` if (u_displacementEnabled) { vec3 dispMap = texture2D(u_dispMap, v_displacementMapTexCoord).rgb - 0.5; - vec2 dispVec = vec2(sourceCoord.x + u_dispScale.x * dispMap.r, sourceCoord.y + u_dispScale.y * dispMap.g); + vec2 dispVec = vec2(sourceCoord.x + (u_dispScale.x + dispMap.b) * dispMap.r, sourceCoord.y + (u_dispScale.y + dispMap.b) * dispMap.g); ${wrap} sourceCoord = dispVec; }`, @@ -3231,7 +3231,7 @@ const effects = { duotone, displacement, turbulence, - kaleidoscope + kaleidoscope, }; const transitions = { diff --git a/index.js b/index.js index 559cea0..6a51200 100644 --- a/index.js +++ b/index.js @@ -25,7 +25,7 @@ export const effects = { duotone, displacement, turbulence, - kaleidoscope + kaleidoscope, }; export const transitions = { diff --git a/index.umd.js b/index.umd.js index 9ef736d..c7d3fde 100644 --- a/index.umd.js +++ b/index.umd.js @@ -807,7 +807,7 @@ const mat3 satmat = mat3( source: ` if (u_displacementEnabled) { vec3 dispMap = texture2D(u_dispMap, v_displacementMapTexCoord).rgb - 0.5; - vec2 dispVec = vec2(sourceCoord.x + u_dispScale.x * dispMap.r, sourceCoord.y + u_dispScale.y * dispMap.g); + vec2 dispVec = vec2(sourceCoord.x + (u_dispScale.x + dispMap.b) * dispMap.r, sourceCoord.y + (u_dispScale.y + dispMap.b) * dispMap.g); ${wrap} sourceCoord = dispVec; }`, @@ -3235,7 +3235,7 @@ void main() { duotone, displacement, turbulence, - kaleidoscope + kaleidoscope, }; const transitions = { diff --git a/src/effects/displacement.js b/src/effects/displacement.js index 300639c..362fdc4 100644 --- a/src/effects/displacement.js +++ b/src/effects/displacement.js @@ -42,7 +42,7 @@ function displacement({ wrap = WRAP_METHODS.CLAMP, scale } = {}) { source: ` if (u_displacementEnabled) { vec3 dispMap = texture2D(u_dispMap, v_displacementMapTexCoord).rgb - 0.5; - vec2 dispVec = vec2(sourceCoord.x + u_dispScale.x * dispMap.r, sourceCoord.y + u_dispScale.y * dispMap.g); + vec2 dispVec = vec2(sourceCoord.x + (u_dispScale.x + dispMap.b) * dispMap.r, sourceCoord.y + (u_dispScale.y + dispMap.b) * dispMap.g); ${wrap} sourceCoord = dispVec; }`, From 23c00e744c78f68654bb5d9a7fdcb34afb273c14 Mon Sep 17 00:00:00 2001 From: Yehonatan Daniv Date: Sun, 10 Nov 2024 19:07:25 +0200 Subject: [PATCH 2/4] Some params and minor changes to values --- demo/multi-pointer.js | 49 ++++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/demo/multi-pointer.js b/demo/multi-pointer.js index 6008094..12b8dbe 100644 --- a/demo/multi-pointer.js +++ b/demo/multi-pointer.js @@ -5,25 +5,27 @@ import { Kampos, effects } from '../index.js'; * https://tympanus.net/codrops/2019/10/08/creating-a-water-like-distortion-effect-with-three-js/ */ +const DEBUG = false; + const target = document.querySelector('#target'); const mapTarget = document.createElement('canvas'); -const easeOutSine = (t, b, c, d) => { - return c * Math.sin((t / d) * (Math.PI / 2)) + b; +const easeOutSine = (t) => { + return Math.sin(t * Math.PI / 2); }; -const easeOutQuad = (t, b, c, d) => { - t /= d; - return -c * t * (t - 2) + b; +const easeOutQuad = (t) => { + return -1 * t * (t - 2) ; }; class PointerTexture { - constructor ({ target, width, height, radius, intensity, maxAge, canvas }){ + constructor ({ target, width, height, radius, intensity, maxAge, canvas, forceDecay }){ this.width = width; this.height = height; - this.radius = radius; + this.radius = radius || 100; this.intensity = intensity; this.maxAge = maxAge; + this.decayFactor = forceDecay || 0.01; this.last = null; this.points = []; this.ctx = canvas.getContext('2d'); @@ -32,7 +34,7 @@ class PointerTexture { } clear() { - this.ctx.fillStyle = 'rgba(127, 127, 127, 1)'; + this.ctx.fillStyle = 'rgba(127, 127, 0, 1)'; this.ctx.fillRect(0, 0, this.width, this.height); } @@ -53,7 +55,7 @@ class PointerTexture { point.vx = relatveX / (speed + 1e-5); point.vy = relatveY / (speed + 1e-5); - point.speed = Math.min(speedSquared * 1e3, 1); + point.speed = Math.min(speedSquared * 1e4, 1); } this.last = point; @@ -64,14 +66,18 @@ class PointerTexture { update () { this.clear(); this.points.forEach((point, i) => { - const decay = 1 - point.age / this.maxAge; - const force = point.speed * decay / this.maxAge; + const decay = 1 - (point.age / this.maxAge); + const force = point.speed * decay * this.decayFactor; point.x += point.vx * force; point.y += point.vy * force; point.age += 1; if (point.age > this.maxAge) { this.points.splice(i, 1); + + if (this.points.length === 0) { + this.last = null; + } } else { this.drawPoint(point); } @@ -85,19 +91,14 @@ class PointerTexture { }; let intensity = 1; if (point.age < this.maxAge * 0.3) { - intensity = easeOutSine(point.age / (this.maxAge * 0.3), 0, 1, 1); + intensity = easeOutSine(point.age / (this.maxAge * 0.3)); } else { - intensity = easeOutQuad( - 1 - (point.age - this.maxAge * 0.3) / (this.maxAge * 0.7), - 0, - 1, - 1 - ); + intensity = easeOutQuad(1 - (point.age - this.maxAge * 0.3) / (this.maxAge * 0.7)); } intensity *= point.speed; const red = (1 - point.vx) / 2 * 255; - const green = (point.vy + 1) / 2 * 255; + const green = (1 + point.vy) / 2 * 255; const blue = intensity * 255; const offset = this.width * 5; @@ -115,7 +116,6 @@ class PointerTexture { const MAP_WIDTH = 1396; const MAP_HEIGHT = 992; -const DEBUG = false; loadImage( `https://picsum.photos/${MAP_WIDTH}/${MAP_HEIGHT}?random=1`, @@ -135,15 +135,16 @@ loadImage( width, height, canvas: DEBUG ? target : mapTarget, - radius: 150, - intensity: 1.2, - maxAge: 64 + radius: 130, + intensity: 0.6, + maxAge: 180, + forceDecay: 0.01, }); // create the main instance that renders the displaced image const displacement = effects.displacement(); displacement.map = mapTarget; - displacement.scale = { x: 0, y: 0}; + displacement.scale = { x: 0, y: 0 }; displacement.textures[0].update = true; // to update if (DEBUG) { From 0ff06d51b6e062cd48569684f835b77217d20f78 Mon Sep 17 00:00:00 2001 From: Yehonatan Daniv Date: Sun, 10 Nov 2024 19:51:05 +0200 Subject: [PATCH 3/4] Updated demo, build, and docs --- demo/multi-pointer.js | 6 ++++-- dist/index.cjs | 19 +++++++++++++++++-- docs/index.html | 17 +++++++++++++++++ index.umd.js | 19 +++++++++++++++++-- src/effects/displacement.js | 19 +++++++++++++++++-- 5 files changed, 72 insertions(+), 8 deletions(-) diff --git a/demo/multi-pointer.js b/demo/multi-pointer.js index 12b8dbe..e9a8f32 100644 --- a/demo/multi-pointer.js +++ b/demo/multi-pointer.js @@ -142,9 +142,11 @@ loadImage( }); // create the main instance that renders the displaced image - const displacement = effects.displacement(); + const displacement = effects.displacement({ + scale: { x: 0, y: 0 }, + enableBlueChannel: true, + }); displacement.map = mapTarget; - displacement.scale = { x: 0, y: 0 }; displacement.textures[0].update = true; // to update if (DEBUG) { diff --git a/dist/index.cjs b/dist/index.cjs index e6d100a..7598408 100644 --- a/dist/index.cjs +++ b/dist/index.cjs @@ -767,11 +767,12 @@ function duotone ({ * @param {Object} [params] * @param {string} [params.wrap] wrapping method to use. Defaults to `displacement.CLAMP`. * @param {{x: number, y: number}} [params.scale] initial scale to use for x and y displacement. Defaults to `{x: 0.0, y: 0.0}` which means no displacement. + * @param {boolean} [params.enableBlueChannel] enable blue channel for displacement intensity. Defaults to `false`. * @returns {displacementEffect} * * @example displacement({wrap: displacement.DISCARD, scale: {x: 0.5, y: -0.5}}) */ -function displacement({ wrap = WRAP_METHODS.CLAMP, scale } = {}) { +function displacement({ wrap = WRAP_METHODS.CLAMP, scale, enableBlueChannel } = {}) { const { x: sx, y: sy } = scale || { x: 0.0, y: 0.0 }; /** @@ -779,6 +780,7 @@ function displacement({ wrap = WRAP_METHODS.CLAMP, scale } = {}) { * @property {ArrayBufferView|ImageData|HTMLImageElement|HTMLCanvasElement|HTMLVideoElement|ImageBitmap} map * @property {{x: number?, y: number?}} scale * @property {boolean} disabled + * @property {boolean} enableBlueChannel * * @example * const img = new Image(); @@ -797,13 +799,15 @@ function displacement({ wrap = WRAP_METHODS.CLAMP, scale } = {}) { fragment: { uniform: { u_displacementEnabled: 'bool', + u_enableBlueChannel: 'bool', u_dispMap: 'sampler2D', u_dispScale: 'vec2', }, source: ` if (u_displacementEnabled) { vec3 dispMap = texture2D(u_dispMap, v_displacementMapTexCoord).rgb - 0.5; - vec2 dispVec = vec2(sourceCoord.x + (u_dispScale.x + dispMap.b) * dispMap.r, sourceCoord.y + (u_dispScale.y + dispMap.b) * dispMap.g); + float dispMapB = u_enableBlueChannel ? dispMap.b : 0.0; + vec2 dispVec = vec2(sourceCoord.x + (u_dispScale.x + dispMapB) * dispMap.r, sourceCoord.y + (u_dispScale.y + dispMapB) * dispMap.g); ${wrap} sourceCoord = dispVec; }`, @@ -828,6 +832,12 @@ function displacement({ wrap = WRAP_METHODS.CLAMP, scale } = {}) { set map(img) { this.textures[0].data = img; }, + get enableBlueChannel() { + return this.uniforms[3].data[0]; + }, + set enableBlueChannel(b) { + this.uniforms[3].data[0] = +b; + }, varying: { v_displacementMapTexCoord: 'vec2', }, @@ -847,6 +857,11 @@ function displacement({ wrap = WRAP_METHODS.CLAMP, scale } = {}) { type: 'f', data: [sx, sy], }, + { + name: 'u_enableBlueChannel', + type: 'i', + data: [+enableBlueChannel], + }, ], attributes: [ { diff --git a/docs/index.html b/docs/index.html index c664088..9ea5b06 100644 --- a/docs/index.html +++ b/docs/index.html @@ -2711,6 +2711,17 @@

+ + params.enableBlueChannel boolean? + + enable blue channel for displacement intensity. Defaults to +false +. + + + + + @@ -3579,6 +3590,12 @@

+
+ enableBlueChannel (boolean) + + +
+ diff --git a/index.umd.js b/index.umd.js index c7d3fde..e6465f7 100644 --- a/index.umd.js +++ b/index.umd.js @@ -771,11 +771,12 @@ const mat3 satmat = mat3( * @param {Object} [params] * @param {string} [params.wrap] wrapping method to use. Defaults to `displacement.CLAMP`. * @param {{x: number, y: number}} [params.scale] initial scale to use for x and y displacement. Defaults to `{x: 0.0, y: 0.0}` which means no displacement. + * @param {boolean} [params.enableBlueChannel] enable blue channel for displacement intensity. Defaults to `false`. * @returns {displacementEffect} * * @example displacement({wrap: displacement.DISCARD, scale: {x: 0.5, y: -0.5}}) */ - function displacement({ wrap = WRAP_METHODS.CLAMP, scale } = {}) { + function displacement({ wrap = WRAP_METHODS.CLAMP, scale, enableBlueChannel } = {}) { const { x: sx, y: sy } = scale || { x: 0.0, y: 0.0 }; /** @@ -783,6 +784,7 @@ const mat3 satmat = mat3( * @property {ArrayBufferView|ImageData|HTMLImageElement|HTMLCanvasElement|HTMLVideoElement|ImageBitmap} map * @property {{x: number?, y: number?}} scale * @property {boolean} disabled + * @property {boolean} enableBlueChannel * * @example * const img = new Image(); @@ -801,13 +803,15 @@ const mat3 satmat = mat3( fragment: { uniform: { u_displacementEnabled: 'bool', + u_enableBlueChannel: 'bool', u_dispMap: 'sampler2D', u_dispScale: 'vec2', }, source: ` if (u_displacementEnabled) { vec3 dispMap = texture2D(u_dispMap, v_displacementMapTexCoord).rgb - 0.5; - vec2 dispVec = vec2(sourceCoord.x + (u_dispScale.x + dispMap.b) * dispMap.r, sourceCoord.y + (u_dispScale.y + dispMap.b) * dispMap.g); + float dispMapB = u_enableBlueChannel ? dispMap.b : 0.0; + vec2 dispVec = vec2(sourceCoord.x + (u_dispScale.x + dispMapB) * dispMap.r, sourceCoord.y + (u_dispScale.y + dispMapB) * dispMap.g); ${wrap} sourceCoord = dispVec; }`, @@ -832,6 +836,12 @@ const mat3 satmat = mat3( set map(img) { this.textures[0].data = img; }, + get enableBlueChannel() { + return this.uniforms[3].data[0]; + }, + set enableBlueChannel(b) { + this.uniforms[3].data[0] = +b; + }, varying: { v_displacementMapTexCoord: 'vec2', }, @@ -851,6 +861,11 @@ const mat3 satmat = mat3( type: 'f', data: [sx, sy], }, + { + name: 'u_enableBlueChannel', + type: 'i', + data: [+enableBlueChannel], + }, ], attributes: [ { diff --git a/src/effects/displacement.js b/src/effects/displacement.js index 362fdc4..9d3309c 100644 --- a/src/effects/displacement.js +++ b/src/effects/displacement.js @@ -6,11 +6,12 @@ * @param {Object} [params] * @param {string} [params.wrap] wrapping method to use. Defaults to `displacement.CLAMP`. * @param {{x: number, y: number}} [params.scale] initial scale to use for x and y displacement. Defaults to `{x: 0.0, y: 0.0}` which means no displacement. + * @param {boolean} [params.enableBlueChannel] enable blue channel for displacement intensity. Defaults to `false`. * @returns {displacementEffect} * * @example displacement({wrap: displacement.DISCARD, scale: {x: 0.5, y: -0.5}}) */ -function displacement({ wrap = WRAP_METHODS.CLAMP, scale } = {}) { +function displacement({ wrap = WRAP_METHODS.CLAMP, scale, enableBlueChannel } = {}) { const { x: sx, y: sy } = scale || { x: 0.0, y: 0.0 }; /** @@ -18,6 +19,7 @@ function displacement({ wrap = WRAP_METHODS.CLAMP, scale } = {}) { * @property {ArrayBufferView|ImageData|HTMLImageElement|HTMLCanvasElement|HTMLVideoElement|ImageBitmap} map * @property {{x: number?, y: number?}} scale * @property {boolean} disabled + * @property {boolean} enableBlueChannel * * @example * const img = new Image(); @@ -36,13 +38,15 @@ function displacement({ wrap = WRAP_METHODS.CLAMP, scale } = {}) { fragment: { uniform: { u_displacementEnabled: 'bool', + u_enableBlueChannel: 'bool', u_dispMap: 'sampler2D', u_dispScale: 'vec2', }, source: ` if (u_displacementEnabled) { vec3 dispMap = texture2D(u_dispMap, v_displacementMapTexCoord).rgb - 0.5; - vec2 dispVec = vec2(sourceCoord.x + (u_dispScale.x + dispMap.b) * dispMap.r, sourceCoord.y + (u_dispScale.y + dispMap.b) * dispMap.g); + float dispMapB = u_enableBlueChannel ? dispMap.b : 0.0; + vec2 dispVec = vec2(sourceCoord.x + (u_dispScale.x + dispMapB) * dispMap.r, sourceCoord.y + (u_dispScale.y + dispMapB) * dispMap.g); ${wrap} sourceCoord = dispVec; }`, @@ -67,6 +71,12 @@ function displacement({ wrap = WRAP_METHODS.CLAMP, scale } = {}) { set map(img) { this.textures[0].data = img; }, + get enableBlueChannel() { + return this.uniforms[3].data[0]; + }, + set enableBlueChannel(b) { + this.uniforms[3].data[0] = +b; + }, varying: { v_displacementMapTexCoord: 'vec2', }, @@ -86,6 +96,11 @@ function displacement({ wrap = WRAP_METHODS.CLAMP, scale } = {}) { type: 'f', data: [sx, sy], }, + { + name: 'u_enableBlueChannel', + type: 'i', + data: [+enableBlueChannel], + }, ], attributes: [ { From c5d021df0eedee4071e038b9b1854b4c54de5d74 Mon Sep 17 00:00:00 2001 From: Yehonatan Daniv Date: Mon, 11 Nov 2024 20:48:34 +0200 Subject: [PATCH 4/4] Some tweaks --- demo/multi-pointer.js | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/demo/multi-pointer.js b/demo/multi-pointer.js index e9a8f32..e0b19c8 100644 --- a/demo/multi-pointer.js +++ b/demo/multi-pointer.js @@ -55,7 +55,7 @@ class PointerTexture { point.vx = relatveX / (speed + 1e-5); point.vy = relatveY / (speed + 1e-5); - point.speed = Math.min(speedSquared * 1e4, 1); + point.speed = Math.min(speedSquared * 1e3, 1); } this.last = point; @@ -74,10 +74,6 @@ class PointerTexture { if (point.age > this.maxAge) { this.points.splice(i, 1); - - if (this.points.length === 0) { - this.last = null; - } } else { this.drawPoint(point); } @@ -97,7 +93,7 @@ class PointerTexture { } intensity *= point.speed; - const red = (1 - point.vx) / 2 * 255; + const red = (1 + point.vx) / 2 * 255; const green = (1 + point.vy) / 2 * 255; const blue = intensity * 255; @@ -136,8 +132,8 @@ loadImage( height, canvas: DEBUG ? target : mapTarget, radius: 130, - intensity: 0.6, - maxAge: 180, + intensity: 1.2, + maxAge: 130, forceDecay: 0.01, });