How to embed things created with threejs inside a website?

I created a simple effect for images using three.js and shaders. Here is a link

Now I have a question how would I use it on a website, for example with this layout where blue blocks are the images which should have this effect.

enter image description here

I googled around and can’t really find anything about that.

Because this whole scene is a canvas and I would need multiple images I would imagine that the canvas should stay as it is right now but how do you position images at the right spots?

The code from the link above:

<script id="vertex" type="x-shader/x-vertex">
  varying float wave;
  varying vec2 vUv;
  uniform float mouseIntersects;
  
  void main() {
    vUv = uv;
    vec3 pos = position;
    pos.z += -mouseIntersects / 20.0;
    
    wave = pos.z;
    
    gl_Position = projectionMatrix  * modelViewMatrix * vec4(position, 1.0 );
}
</script>
<script id="fragment" type="x-shader/x-vertex">
    uniform vec2 u_resolution;
    uniform float u_time;
    varying vec2 vUv;
    varying float wave;
    uniform sampler2D uTexture;

    void main() {
        vec2 st = gl_FragCoord.xy/u_resolution.xy;
      
        float r = texture2D(uTexture, vUv + wave).r;
        float g = texture2D(uTexture, vUv).g;
        float b = texture2D(uTexture, vUv).b;
      
        vec4 image = vec4(r, g, b, 1.0);
      
        gl_FragColor = image;
    }
  </script>
<div id="container"></div>
</body>

and three.js part:

import { OrbitControls } from "https://threejsfundamentals.org/threejs/resources/threejs/r110/examples/jsm/controls/OrbitControls.js";

let container, camera, scene, renderer, controls, material, uniforms, geometry, mesh, raycaster;

const setup = () => {
  scene = new THREE.Scene();

  renderer = new THREE.WebGLRenderer({ antialias: true });
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(window.innerWidth, window.innerWidth);
  renderer.setClearColor(0xffffff);

  container = document.getElementById('container');
  container.appendChild(renderer.domElement);

  camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.001, 100);
  camera.position.set(0, 0, 0.5);

  controls = new OrbitControls(camera, renderer.domElement);

  uniforms = {
    u_time: { type: 'f', value: 0 },
    u_mouse: { type: 'v2', value: new THREE.Vector2() },
    u_resolution: { type: 'v2', value: new THREE.Vector2(window.innerWidth, window.innerHeight) },
    uTexture: { type: 't', value: new THREE.TextureLoader().load('https://images.unsplash.com/photo-1512505965932-0dbfa7e7b8c8?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=701&q=80') },
    mouseIntersects: { type: 'f', value: 0 },
  };

  material = new THREE.ShaderMaterial({
    side: THREE.DoubleSide,
    uniforms: uniforms,
    // wireframe: true,
    vertexShader: document.querySelector("#vertex").textContent,
    fragmentShader: document.querySelector("#fragment").textContent
  });

  geometry = new THREE.PlaneBufferGeometry(0.4, 0.6, 16, 16);

  mesh = new THREE.Mesh(geometry, material);

  raycaster = new THREE.Raycaster();

  scene.add(mesh);

  onWindowResize();
  window.addEventListener('resize', onWindowResize, false);
  document.addEventListener('mousemove', (e) => updateMousePositions(e), false);
};

const updateMousePositions = (e) => {
  uniforms.u_mouse.value.x = (event.clientX / window.innerWidth) * 2 - 1;
  uniforms.u_mouse.value.y = -(event.clientY / window.innerHeight) * 2 + 1;
};

const onWindowResize = (event) => {
  renderer.setSize(window.innerWidth, window.innerHeight);
  uniforms.u_resolution.value.x = renderer.domElement.width;
  uniforms.u_resolution.value.y = renderer.domElement.height;
};

const animate = () => {
  requestAnimationFrame(animate);
  render();
};
let targetValue = 0;
const render = () => {
  uniforms.u_time.value += 0.05;

  raycaster.setFromCamera(uniforms.u_mouse.value, camera);
  const intersects = raycaster.intersectObject(mesh);

  if (intersects.length === 1) {
    targetValue = 1;
  } else {
    targetValue = 0;
  }

  uniforms.mouseIntersects.value = THREE.MathUtils.lerp(
    uniforms.mouseIntersects.value,
    targetValue,
    0.1,
  );

  renderer.render(scene, camera);
};

setup();
animate();

/cc

1 Like