From 6d26026a685f535801f8bc4d345788745a4d75d2 Mon Sep 17 00:00:00 2001 From: Jean Date: Fri, 23 Aug 2024 17:59:06 +0200 Subject: [PATCH 1/3] init --- src/components/media.ts | 55 +++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 32 deletions(-) diff --git a/src/components/media.ts b/src/components/media.ts index 2a0faf8..2824a51 100644 --- a/src/components/media.ts +++ b/src/components/media.ts @@ -54,7 +54,7 @@ export default class Media { this.setTexture() this.createGPGPU() - this.setupDebug() + //this.setupDebug() this.scene.add(this.mesh) } @@ -69,36 +69,33 @@ export default class Media { fragmentShader, uniforms: { uTexture: new THREE.Uniform(new THREE.Vector4()), - uGrid: new THREE.Uniform(new THREE.Vector4()), - uContainerResolution: new THREE.Uniform(new THREE.Vector2()), - uImageResolution: new THREE.Uniform(new THREE.Vector2(0, 0)), - uDisplacement: new THREE.Uniform(0), - uRGBshift: new THREE.Uniform(new THREE.Vector2(0.02, 0.0)), + uContainerResolution: new THREE.Uniform(new THREE.Vector2(window.innerWidth, window.innerHeight)), + uImageResolution: new THREE.Uniform(new THREE.Vector2()), }, }) } - setupDebug() { - const opt = { - dis: this.material.uniforms.uDisplacement.value > 0, - } - - this.debug - .add(opt, 'dis') - .onChange((dis: boolean) => { - if (dis) this.material.uniforms.uDisplacement.value = 1 - else this.material.uniforms.uDisplacement.value = 0 - }) - .name('grid map') - - //this.debug.add(this.material.uniforms.uRGBshift.value, 'x').min(-0.1).max(0.1).step(0.001).name('rgb X') - //this.debug.add(this.material.uniforms.uRGBshift.value, 'y').min(-0.1).max(0.1).step(0.001).name('rgb Y') - } - createMesh() { this.mesh = new THREE.Mesh(this.geometry, this.material) } + // setupDebug() { + // const opt = { + // dis: this.material.uniforms.uDisplacement.value > 0, + // } + + // this.debug + // .add(opt, 'dis') + // .onChange((dis: boolean) => { + // if (dis) this.material.uniforms.uDisplacement.value = 1 + // else this.material.uniforms.uDisplacement.value = 0 + // }) + // .name('grid map') + + // //this.debug.add(this.material.uniforms.uRGBshift.value, 'x').min(-0.1).max(0.1).step(0.001).name('rgb X') + // //this.debug.add(this.material.uniforms.uRGBshift.value, 'y').min(-0.1).max(0.1).step(0.001).name('rgb Y') + // } + createGPGPU() { this.gpgpu = new GPGPU({ renderer: this.renderer, @@ -146,13 +143,7 @@ export default class Media { setTexture() { this.material.uniforms.uTexture.value = new THREE.TextureLoader().load(this.element.src, ({ image }) => { const { naturalWidth, naturalHeight } = image - const container = document.querySelector('.image-container') as HTMLElement - const { width, height } = container.getBoundingClientRect() - - console.log(naturalWidth, naturalHeight) - this.material.uniforms.uImageResolution.value = new THREE.Vector2(naturalWidth, naturalHeight) - this.material.uniforms.uContainerResolution.value = new THREE.Vector2(width, height) }) } @@ -184,10 +175,10 @@ export default class Media { render(time: number) { const deltaTime = this.time - time - this.time = time + //this.time = time - this.gpgpu.render(time, deltaTime) + //this.gpgpu.render(time, deltaTime) - this.material.uniforms.uGrid.value = this.gpgpu.getTexture() + //this.material.uniforms.uGrid.value = this.gpgpu.getTexture() } } From bf6e3025d886f0175987c285f02be3cf3381afdd Mon Sep 17 00:00:00 2001 From: Jean Date: Fri, 23 Aug 2024 19:34:15 +0200 Subject: [PATCH 2/3] init --- index.html | 6 +--- src/components/media.ts | 53 +++++++++++++-------------- src/shaders/fragment.glsl | 60 +++---------------------------- src/shaders/gpgpu/gpgpu.glsl | 18 ---------- src/style.scss | 23 ++---------- src/utils/gpgpu.ts | 70 +++++------------------------------- 6 files changed, 44 insertions(+), 186 deletions(-) diff --git a/index.html b/index.html index 973d291..8f7d5f9 100644 --- a/index.html +++ b/index.html @@ -9,11 +9,7 @@
-
-
- -
-
+
diff --git a/src/components/media.ts b/src/components/media.ts index 2824a51..ae52633 100644 --- a/src/components/media.ts +++ b/src/components/media.ts @@ -69,32 +69,40 @@ export default class Media { fragmentShader, uniforms: { uTexture: new THREE.Uniform(new THREE.Vector4()), + uGrid: new THREE.Uniform(new THREE.Vector4()), uContainerResolution: new THREE.Uniform(new THREE.Vector2(window.innerWidth, window.innerHeight)), uImageResolution: new THREE.Uniform(new THREE.Vector2()), }, }) } + setTexture() { + this.material.uniforms.uTexture.value = new THREE.TextureLoader().load(this.element.src, ({ image }) => { + const { naturalWidth, naturalHeight } = image + this.material.uniforms.uImageResolution.value = new THREE.Vector2(naturalWidth, naturalHeight) + }) + } + createMesh() { this.mesh = new THREE.Mesh(this.geometry, this.material) } - // setupDebug() { - // const opt = { - // dis: this.material.uniforms.uDisplacement.value > 0, - // } + setupDebug() { + const opt = { + dis: this.material.uniforms.uDisplacement.value > 0, + } - // this.debug - // .add(opt, 'dis') - // .onChange((dis: boolean) => { - // if (dis) this.material.uniforms.uDisplacement.value = 1 - // else this.material.uniforms.uDisplacement.value = 0 - // }) - // .name('grid map') + this.debug + .add(opt, 'dis') + .onChange((dis: boolean) => { + if (dis) this.material.uniforms.uDisplacement.value = 1 + else this.material.uniforms.uDisplacement.value = 0 + }) + .name('grid map') - // //this.debug.add(this.material.uniforms.uRGBshift.value, 'x').min(-0.1).max(0.1).step(0.001).name('rgb X') - // //this.debug.add(this.material.uniforms.uRGBshift.value, 'y').min(-0.1).max(0.1).step(0.001).name('rgb Y') - // } + //this.debug.add(this.material.uniforms.uRGBshift.value, 'x').min(-0.1).max(0.1).step(0.001).name('rgb X') + //this.debug.add(this.material.uniforms.uRGBshift.value, 'y').min(-0.1).max(0.1).step(0.001).name('rgb Y') + } createGPGPU() { this.gpgpu = new GPGPU({ @@ -140,13 +148,6 @@ export default class Media { this.mesh.position.y = this.meshPostion.y } - setTexture() { - this.material.uniforms.uTexture.value = new THREE.TextureLoader().load(this.element.src, ({ image }) => { - const { naturalWidth, naturalHeight } = image - this.material.uniforms.uImageResolution.value = new THREE.Vector2(naturalWidth, naturalHeight) - }) - } - updateScroll(scrollY: number) { this.currentScroll = (-scrollY * this.sizes.height) / window.innerHeight @@ -175,10 +176,10 @@ export default class Media { render(time: number) { const deltaTime = this.time - time - //this.time = time - - //this.gpgpu.render(time, deltaTime) - - //this.material.uniforms.uGrid.value = this.gpgpu.getTexture() + this.time = time + // + this.gpgpu.render(time, deltaTime) + // + this.material.uniforms.uGrid.value = this.gpgpu.getTexture() } } diff --git a/src/shaders/fragment.glsl b/src/shaders/fragment.glsl index 7b8d4e1..52e65da 100644 --- a/src/shaders/fragment.glsl +++ b/src/shaders/fragment.glsl @@ -1,11 +1,9 @@ uniform sampler2D uTexture; uniform sampler2D uGrid; -varying vec2 vUv; +varying vec2 vUv; uniform vec2 uContainerResolution; -uniform float uDisplacement; uniform vec2 uImageResolution; -uniform vec2 uRGBshift; vec2 coverUvs(vec2 imageRes,vec2 containerRes) @@ -30,63 +28,13 @@ vec2 coverUvs(vec2 imageRes,vec2 containerRes) } -float random (vec2 st) { - return fract(sin(dot(st.xy, - vec2(12.9898,78.233)))* - 43758.5453123); -} - void main() { - vec2 newUvs = coverUvs(uImageResolution,uContainerResolution); - - + vec2 newUvs = coverUvs(uImageResolution,uContainerResolution); vec2 squareUvs = coverUvs(vec2(1.),uContainerResolution); - vec4 image = texture2D(uTexture,newUvs); + vec4 image = texture2D(uTexture,newUvs); vec4 displacement = texture2D(uGrid,squareUvs); - vec2 finalUvs = newUvs - displacement.rg*0.01; - - vec4 finalImage = texture2D(uTexture,finalUvs); - - //rgb shift - vec2 redUvs = finalUvs; - vec2 blueUvs = finalUvs; - vec2 greenUvs = finalUvs; - - - vec2 shift = displacement.rg*0.001; - - float displacementStrengh=length(displacement.rg); - displacementStrengh = clamp(displacementStrengh,0.,2.); - - float redStrengh = 1.+displacementStrengh*0.25; - redUvs += shift*redStrengh; - - float blueStrengh = 1.+displacementStrengh*1.5; - blueUvs += shift*blueStrengh; - - float greenStrengh = 1.+displacementStrengh*2.; - greenUvs += shift*greenStrengh; - - float red = texture2D(uTexture,redUvs).r; - float blue = texture2D(uTexture,blueUvs).b; - float green = texture2D(uTexture,greenUvs).g; - - - finalImage.r =red; - finalImage.g =green; - finalImage.b =blue; - - vec4 visualDisplacement = displacement; - visualDisplacement*=0.5; - visualDisplacement+=0.5; - - vec4 final = step(0.5,uDisplacement)*visualDisplacement + (1.-step(0.5,uDisplacement))*finalImage; - - gl_FragColor = final; - - //#include - //#include + gl_FragColor = displacement; } \ No newline at end of file diff --git a/src/shaders/gpgpu/gpgpu.glsl b/src/shaders/gpgpu/gpgpu.glsl index 835bd31..406ffc7 100644 --- a/src/shaders/gpgpu/gpgpu.glsl +++ b/src/shaders/gpgpu/gpgpu.glsl @@ -1,26 +1,8 @@ -uniform vec2 uMouse; -uniform vec2 uDeltaMouse; -uniform float uMouseMove; -uniform float uGridSize; -uniform float uRelaxation; -uniform float uDistance; - - void main() { vec2 uv = gl_FragCoord.xy/resolution.xy; vec4 color = texture(uGrid,uv); - - float dist = distance(uv,uMouse); - dist = 1.-(smoothstep(0.,uDistance/uGridSize,dist)); - - - vec2 delta = uDeltaMouse; - - color.rg+=delta*dist; - color.rg*=min(uRelaxation,uMouseMove); - gl_FragColor = color; } \ No newline at end of file diff --git a/src/style.scss b/src/style.scss index 1a2c1d3..3b6c9e6 100644 --- a/src/style.scss +++ b/src/style.scss @@ -141,32 +141,15 @@ table { .container { max-height: 100%; - height: 100%; - box-sizing: border-box; -} - -$wrapper-padding:0vmax; - -.wrapper { - height: 100%; - max-height: 100%; - padding: $wrapper-padding; + height: 100vw; + width: 100vw; box-sizing: border-box; - display: flex; - justify-content: center; - align-items: center; - overflow: hidden; -} - -.image-container { - display: inline-block; } img { height: 100%; - //max-height: calc(100dvh - calc($wrapper-padding * 2)); width: 100%; object-fit: cover; opacity: 0; - display: block; + display: block; } diff --git a/src/utils/gpgpu.ts b/src/utils/gpgpu.ts index 2f3ae66..0635a49 100644 --- a/src/utils/gpgpu.ts +++ b/src/utils/gpgpu.ts @@ -3,7 +3,6 @@ import fragmentShader from '../shaders/gpgpu/gpgpu.glsl' import { GPUComputationRenderer, Variable } from 'three/addons/misc/GPUComputationRenderer.js' import GUI from 'lil-gui' import { Size } from '../types/types' -import { min } from 'three/webgpu' interface Props { renderer: THREE.WebGLRenderer @@ -13,16 +12,12 @@ interface Props { } interface Params { - relaxation: number size: number - distance: number - strengh: number } export default class GPGPU { time: number size: number - sizes: Size gpgpuRenderer: GPUComputationRenderer renderer: THREE.WebGLRenderer dataTexture: THREE.DataTexture @@ -33,17 +28,12 @@ export default class GPGPU { params: Params debug: GUI - constructor({ renderer, scene, sizes, debug }: Props) { + constructor({ renderer, scene }: Props) { this.scene = scene this.renderer = renderer - this.sizes = sizes - this.debug = debug this.params = { - relaxation: 0.965, size: 700, - distance: 0.6, - strengh: 0.8, } this.size = Math.ceil(Math.sqrt(this.params.size)) @@ -54,27 +44,24 @@ export default class GPGPU { this.createVariable() this.setRendererDependencies() this.initiateRenderer() - //this.createDebugPlane() - this.setupDebug() } createGPGPURenderer() { - this.gpgpuRenderer = new GPUComputationRenderer(this.size, this.size, this.renderer) + this.gpgpuRenderer = new GPUComputationRenderer( + this.size, //the size of the grid we want to create, in the example the size is 27 + this.size, + this.renderer //the WebGLRenderer we are using for our scene + ) } - createDataTexture() { this.dataTexture = this.gpgpuRenderer.createTexture() } createVariable() { this.variable = this.gpgpuRenderer.addVariable('uGrid', fragmentShader, this.dataTexture) - this.variable.material.uniforms.uTime = new THREE.Uniform(0) - this.variable.material.uniforms.uRelaxation = new THREE.Uniform(this.params.relaxation) this.variable.material.uniforms.uGridSize = new THREE.Uniform(this.size) this.variable.material.uniforms.uMouse = new THREE.Uniform(new THREE.Vector2(0, 0)) this.variable.material.uniforms.uDeltaMouse = new THREE.Uniform(new THREE.Vector2(0, 0)) - this.variable.material.uniforms.uMouseMove = new THREE.Uniform(0) - this.variable.material.uniforms.uDistance = new THREE.Uniform(this.params.distance * 10) } setRendererDependencies() { @@ -85,27 +72,13 @@ export default class GPGPU { this.gpgpuRenderer.init() } - createDebugPlane() { - this.debugPlane = new THREE.Mesh( - new THREE.PlaneGeometry(1, 1), - new THREE.MeshBasicMaterial({ - map: this.gpgpuRenderer.getCurrentRenderTarget(this.variable).texture, - }) - ) - - this.debugPlane.scale.set(8, 8, 1) - //this.debugPlane.position.set(-4, 4, 0) - - this.scene.add(this.debugPlane) - } - updateMouse(uv: THREE.Vector2) { - this.variable.material.uniforms.uMouseMove.value = 1 + //this.variable.material.uniforms.uMouseMove.value = 1 const current = this.variable.material.uniforms.uMouse.value as THREE.Vector2 current.subVectors(uv, current) - current.multiplyScalar(this.params.strengh * 100) + current.multiplyScalar(80) this.variable.material.uniforms.uDeltaMouse.value = current this.variable.material.uniforms.uMouse.value = uv @@ -115,33 +88,8 @@ export default class GPGPU { return this.gpgpuRenderer.getCurrentRenderTarget(this.variable).textures[0] } - setupDebug() { - this.debug - .add(this.params, 'relaxation') - .min(0.5) - .max(0.99) - .step(0.001) - .onChange((_: number) => { - this.variable.material.uniforms.uRelaxation.value = _ - }) - - this.debug - .add(this.params, 'distance') - .min(0) - .max(1) - .step(0.001) - .onChange((_: number) => { - this.variable.material.uniforms.uDistance.value = _ * 10 - }) - this.debug.add(this.params, 'strengh').min(0).max(1).step(0.001) - } - render(time: number, deltaTime: number) { - this.time = time - - this.variable.material.uniforms.uTime.value = this.time - this.variable.material.uniforms.uMouseMove.value *= 0.95 - this.variable.material.uniforms.uDeltaMouse.value.multiplyScalar(this.variable.material.uniforms.uRelaxation.value) + //this.variable.material.uniforms.uDeltaMouse.value.multiplyScalar(this.variable.material.uniforms.uRelaxation.value) this.gpgpuRenderer.compute() } From 685106d1298148286e568c77aebeea3feb83f476 Mon Sep 17 00:00:00 2001 From: Jean Date: Sun, 25 Aug 2024 23:28:05 +0200 Subject: [PATCH 3/3] rgb shift --- src/components/canvas.ts | 5 ++-- src/components/media.ts | 13 ++++----- src/shaders/fragment.glsl | 54 ++++++++++++++++++++++++++++++++---- src/shaders/gpgpu/gpgpu.glsl | 17 ++++++++++++ src/utils/gpgpu.ts | 12 ++++---- 5 files changed, 81 insertions(+), 20 deletions(-) diff --git a/src/components/canvas.ts b/src/components/canvas.ts index fe58b9e..1fc5f7e 100644 --- a/src/components/canvas.ts +++ b/src/components/canvas.ts @@ -30,7 +30,7 @@ export default class Canvas { this.createRayCaster() this.createOrbitControls() this.addEventListeners() - this.createDebug() + //this.createDebug() this.createMedias() this.render() } @@ -92,10 +92,12 @@ export default class Canvas { this.mouse.y = -(event.clientY / window.innerHeight) * 2 + 1 this.raycaster.setFromCamera(this.mouse, this.camera) + const intersects = this.raycaster.intersectObjects(this.scene.children) const target = intersects[0] if (target && 'material' in target.object) { const targetMesh = intersects[0].object as THREE.Mesh + this.medias.forEach((media) => { if (media.mesh === targetMesh && target.uv) { media.onMouseMove(target.uv) @@ -106,7 +108,6 @@ export default class Canvas { addEventListeners() { window.addEventListener('mousemove', this.onMouseMove.bind(this)) - window.addEventListener('resize', this.onResize.bind(this)) } onResize() { diff --git a/src/components/media.ts b/src/components/media.ts index ae52633..62ae6fb 100644 --- a/src/components/media.ts +++ b/src/components/media.ts @@ -63,15 +63,18 @@ export default class Media { this.geometry = new THREE.PlaneGeometry(1, 1) } + // createMaterial() { this.material = new THREE.ShaderMaterial({ vertexShader, fragmentShader, uniforms: { uTexture: new THREE.Uniform(new THREE.Vector4()), - uGrid: new THREE.Uniform(new THREE.Vector4()), uContainerResolution: new THREE.Uniform(new THREE.Vector2(window.innerWidth, window.innerHeight)), uImageResolution: new THREE.Uniform(new THREE.Vector2()), + + //add this new Uniform + uGrid: new THREE.Uniform(new THREE.Vector4()), }, }) } @@ -174,12 +177,8 @@ export default class Media { this.gpgpu.updateMouse(uv) } - render(time: number) { - const deltaTime = this.time - time - this.time = time - // - this.gpgpu.render(time, deltaTime) - // + render() { + this.gpgpu.render() this.material.uniforms.uGrid.value = this.gpgpu.getTexture() } } diff --git a/src/shaders/fragment.glsl b/src/shaders/fragment.glsl index 52e65da..1231902 100644 --- a/src/shaders/fragment.glsl +++ b/src/shaders/fragment.glsl @@ -27,14 +27,58 @@ vec2 coverUvs(vec2 imageRes,vec2 containerRes) return newUvs; } - void main() { - vec2 newUvs = coverUvs(uImageResolution,uContainerResolution); - vec2 squareUvs = coverUvs(vec2(1.),uContainerResolution); - + vec2 newUvs = coverUvs(uImageResolution,uContainerResolution); + vec2 squareUvs = coverUvs(vec2(1.),uContainerResolution); + vec4 image = texture2D(uTexture,newUvs); vec4 displacement = texture2D(uGrid,squareUvs); - gl_FragColor = displacement; + vec2 finalUvs = newUvs - displacement.rg*0.01; + + vec4 finalImage = texture2D(uTexture,finalUvs); + + + /* + * rgb shift + */ + + //separate set of UVs for each color + vec2 redUvs = finalUvs; + vec2 blueUvs = finalUvs; + vec2 greenUvs = finalUvs; + + //The shift will follow the displacement direction but with a reduced intensity, + //we need the effect to be subtle + vec2 shift = displacement.rg*0.001; + + //The shift strength will depend on the speed of the mouse move, + //since the intensity rely on deltaMouse we just have to use the length of the (red,green) vector + float displacementStrength=length(displacement.rg); + displacementStrength = clamp(displacementStrength,0.,2.); + + //We apply different strengths to each color + + float redStrength = 1.+displacementStrength*0.25; + redUvs += shift*redStrength; + + float blueStrength = 1.+displacementStrength*1.5; + blueUvs += shift*blueStrength; + + float greenStrength = 1.+displacementStrength*2.; + greenUvs += shift*greenStrength; + + + float red = texture2D(uTexture,redUvs).r; + float blue = texture2D(uTexture,blueUvs).b; + float green = texture2D(uTexture,greenUvs).g; + + //we apply the shift effect to our image + finalImage.r =red; + finalImage.g =green; + finalImage.b =blue; + + + gl_FragColor = finalImage; } \ No newline at end of file diff --git a/src/shaders/gpgpu/gpgpu.glsl b/src/shaders/gpgpu/gpgpu.glsl index 406ffc7..477c87b 100644 --- a/src/shaders/gpgpu/gpgpu.glsl +++ b/src/shaders/gpgpu/gpgpu.glsl @@ -1,8 +1,25 @@ +uniform vec2 uMouse; +uniform vec2 uDeltaMouse; + +uniform float uMouseMove; + + void main() { vec2 uv = gl_FragCoord.xy/resolution.xy; vec4 color = texture(uGrid,uv); + + float dist = distance(uv,uMouse); + dist = 1.-(smoothstep(0.,0.22,dist)); + + + color.rg+=uDeltaMouse*dist; + + float uRelaxation = 0.965; + + color.rg*=min(uRelaxation,uMouseMove); + gl_FragColor = color; } \ No newline at end of file diff --git a/src/utils/gpgpu.ts b/src/utils/gpgpu.ts index 0635a49..56a15de 100644 --- a/src/utils/gpgpu.ts +++ b/src/utils/gpgpu.ts @@ -7,8 +7,6 @@ import { Size } from '../types/types' interface Props { renderer: THREE.WebGLRenderer scene: THREE.Scene - sizes: Size - debug: GUI } interface Params { @@ -26,7 +24,6 @@ export default class GPGPU { debugPlane: THREE.Mesh scene: THREE.Scene params: Params - debug: GUI constructor({ renderer, scene }: Props) { this.scene = scene @@ -62,6 +59,8 @@ export default class GPGPU { this.variable.material.uniforms.uGridSize = new THREE.Uniform(this.size) this.variable.material.uniforms.uMouse = new THREE.Uniform(new THREE.Vector2(0, 0)) this.variable.material.uniforms.uDeltaMouse = new THREE.Uniform(new THREE.Vector2(0, 0)) + // + this.variable.material.uniforms.uMouseMove = new THREE.Uniform(0) } setRendererDependencies() { @@ -73,7 +72,7 @@ export default class GPGPU { } updateMouse(uv: THREE.Vector2) { - //this.variable.material.uniforms.uMouseMove.value = 1 + this.variable.material.uniforms.uMouseMove.value = 1 const current = this.variable.material.uniforms.uMouse.value as THREE.Vector2 @@ -88,8 +87,9 @@ export default class GPGPU { return this.gpgpuRenderer.getCurrentRenderTarget(this.variable).textures[0] } - render(time: number, deltaTime: number) { - //this.variable.material.uniforms.uDeltaMouse.value.multiplyScalar(this.variable.material.uniforms.uRelaxation.value) + render() { + this.variable.material.uniforms.uMouseMove.value *= 0.95 + this.variable.material.uniforms.uDeltaMouse.value.multiplyScalar(0.965) this.gpgpuRenderer.compute() }