Setting background video in canvas using Video texture with three.js not working

匆匆过客 提交于 2020-01-25 06:51:28

问题


I have seen that it is possible to create a sticky image effect on hover using three.js which inspired me with an idea of doing this effect over a video. I am using THREE.VideoTexture() in place of where an image was defined to create a background video. How can I set the video with the id video to the background of my canvas?

const videoSize = [1250, 1097];

const vertex = `
                attribute vec2 uv;
                attribute vec2 position;
                varying vec2 vUv;
                void main() {
                        vUv = uv;
                        gl_Position = vec4(position, 0, 1);
                }
        `;
const fragment = `
                precision highp float;
                precision highp int;
                uniform sampler2D tWater;
                uniform sampler2D tFlow;
                uniform float uTime;
                varying vec2 vUv;
                uniform vec4 res;

                void main() {

                        // R and G values are velocity in the x and y direction
                        // B value is the velocity length
                        vec3 flow = texture2D(tFlow, vUv).rgb;

                        vec2 uv = .5 * gl_FragCoord.xy / res.xy ;
                        vec2 myUV = (uv - vec2(0.5))*res.zw + vec2(0.5);
                        myUV -= flow.xy * (0.15 * 0.7);

                        vec2 myUV2 = (uv - vec2(0.5))*res.zw + vec2(0.5);
                        myUV2 -= flow.xy * (0.125 * 0.7);

                        vec2 myUV3 = (uv - vec2(0.5))*res.zw + vec2(0.5);
                        myUV3 -= flow.xy * (0.10 * 0.7);

                        vec3 tex = texture2D(tWater, myUV).rgb;
                        vec3 tex2 = texture2D(tWater, myUV2).rgb;
                        vec3 tex3 = texture2D(tWater, myUV3).rgb;

          gl_FragColor = vec4(tex.r, tex2.g, tex3.b, 1.0);
                }
        `;
{
  const renderer = new ogl.Renderer({ dpr: 2 });
  const gl = renderer.gl;
  document.body.appendChild(gl.canvas);

  // Variable inputs to control flowmap
  let aspect = 1;
  const mouse = new ogl.Vec2(-1);
  const velocity = new ogl.Vec2();
  function resize() {
    let a1, a2;
    var videoAspect = video.width[1] / video.width[0];
    if (window.innerHeight / window.innerWidth < videoAspect) {
      a1 = 1;
      a2 = window.innerHeight / window.innerWidth / videoAspect;
    } else {
      a1 = (window.innerWidth / window.innerHeight) * videoAspect;
      a2 = 1;
    }
    mesh.program.uniforms.res.value = new ogl.Vec4(
      window.innerWidth,
      window.innerHeight,
      a1,
      a2
    );

    renderer.setSize(window.innerWidth, window.innerHeight);
    aspect = window.innerWidth / window.innerHeight;
  }
  const flowmap = new ogl.Flowmap(gl, {
    falloff: 1.0, // size of the stamp, percentage of the size
    alpha: 0.7, // opacity of the stamp
    dissipation: 0.95// affects the speed that the stamp fades. Closer to 1 is slower
  });
  // Triangle that includes -1 to 1 range for 'position', and 0 to 1 range for 'uv'.
  const geometry = new ogl.Geometry(gl, {
    position: {
      size: 2,
      data: new Float32Array([-1, -1, 3, -1, -1, 3])
    },
    uv: { size: 2, data: new Float32Array([0, 0, 2, 0, 0, 2]) }
  });

  const texture = new ogl.Texture(gl, {
    minFilter: gl.LINEAR,
    magFilter: gl.LINEAR
  });

  var video = document.getElementById( 'video' );
  var videoTexture = new THREE.VideoTexture( video );
  videoTexture.minFilter = THREE.LinearFilter;
  videoTexture.magFilter = THREE.LinearFilter;
  videoTexture.format = THREE.RGBFormat;
  /*
  const img = new Image();
  img.onload = () => (texture.image = img);
  img.crossOrigin = "Anonymous";
  img.src = "./img/overlay.png";*/

  video.onload = () => (texture.video = video);
  video.crossOrigin = "Anonymous";
  video.src = "./img/Morph.mp4";

  let a1, a2;
  var videoAspect = video.width[1] / video.width[0];
  if (window.innerHeight / window.innerWidth < videoAspect) {
    a1 = 1;
    a2 = window.innerHeight / window.innerWidth / videoAspect;
  } else {
    a1 = (window.innerWidth / window.innerHeight) * videoAspect;
    a2 = 1;
  }

  const program = new ogl.Program(gl, {
    vertex,
    fragment,
    uniforms: {
      uTime: { value: 0 },
      tWater: { value: texture },
      res: {
        value: new ogl.Vec4(window.innerWidth, window.innerHeight, a1, a2)
      },
      video: { value: new ogl.Vec2(video.width[0], video.width[1]) },
      // Note that the uniform is applied without using an object and value property
      // This is because the class alternates this texture between two render targets
      // and updates the value property after each render.
      tFlow: flowmap.uniform
    }
  });
  const mesh = new ogl.Mesh(gl, { geometry, program });

  window.addEventListener("resize", resize, false);
  resize();

  // Create handlers to get mouse position and velocity
  const isTouchCapable = "ontouchstart" in window;
  if (isTouchCapable) {
    window.addEventListener("touchstart", updateMouse, false);
    window.addEventListener("touchmove", updateMouse, { passive: false });
  } else {
    window.addEventListener("mousemove", updateMouse, false);
  }
  let lastTime;
  const lastMouse = new ogl.Vec2();
  function updateMouse(e) {
    e.preventDefault();
    if (e.changedTouches && e.changedTouches.length) {
      e.x = e.changedTouches[0].pageX;
      e.y = e.changedTouches[0].pageY;
    }
    if (e.x === undefined) {
      e.x = e.pageX;
      e.y = e.pageY;
    }
    // Get mouse value in 0 to 1 range, with y flipped
    mouse.set(e.x / gl.renderer.width, 1.0 - e.y / gl.renderer.height);
    // Calculate velocity
    if (!lastTime) {
      // First frame
      lastTime = performance.now();
      lastMouse.set(e.x, e.y);
    }

    const deltaX = e.x - lastMouse.x;
    const deltaY = e.y - lastMouse.y;

    lastMouse.set(e.x, e.y);

    let time = performance.now();

    // Avoid dividing by 0
    let delta = Math.max(10.4, time - lastTime);
    lastTime = time;
    velocity.x = deltaX / delta;
    velocity.y = deltaY / delta;
    // Flag update to prevent hanging velocity values when not moving
    velocity.needsUpdate = true;
  }
  requestAnimationFrame(update);
  function update(t) {
    requestAnimationFrame(update);
    // Reset velocity when mouse not moving
    if (!velocity.needsUpdate) {
      mouse.set(-1);
      velocity.set(0);
    }
    velocity.needsUpdate = false;
    // Update flowmap inputs
    flowmap.aspect = aspect;
    flowmap.mouse.copy(mouse);
    // Ease velocity input, slower when fading out
    flowmap.velocity.lerp(velocity, velocity.len ? 0.15 : 0.1);
    flowmap.update();
    program.uniforms.uTime.value = t * 0.01;
    renderer.render({ scene: mesh });
  }
}

来源:https://stackoverflow.com/questions/58834793/setting-background-video-in-canvas-using-video-texture-with-three-js-not-working

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!