Gaurav
Gaurav

Reputation: 1088

Using Video as texture with Three.js

I am trying to create a simple rectangle with a .mp4 video as texture. As per three.js documentation(http://threejs.org/docs/#Reference/Textures/Texture) this should be straight forward.

When I am putting link of video, all I am getting is a black colored box with no texture on it. I have tested code by replacing video with a jpg image and it works fine. Can someone please explain me what I am doing wrong.

I have already seen the examples in which video is played by first linking it to a video element and then copy the frames on a canvas. I want to try the direct way as mentioned in the three.js documentation.

Upvotes: 7

Views: 29534

Answers (4)

Ahsen Khan
Ahsen Khan

Reputation: 391

I spent hours on this, trying to make things work, but nothing worked no matter what I tried. Always a black texture. In the end, it turns out the culprit was display: none on the video element. All of the above code solutions are valid, but it is very important that you do not set the HTML video element itself to display: none, otherwise the browser may optimize it and avoid loading the video. The solution to this was to remove the display tag from the CSS, and instead set opacity to 0%. Theoretically, the browser may also decide to not render this, so you may need to set opacity to 1% and hide it behind a div if that doesn't work.

Upvotes: 0

Bertrand Martel
Bertrand Martel

Reputation: 45382

In addition to Haos' answer, I needed to set videoTexture.needsUpdate = true; and videoMaterial.needsUpdate = true;. Also I've played the video on onloadeddata.

//Get your video element:
const video = document.getElementById("video");
video.onloadeddata = function () {
    video.play();
};

//Create your video texture:
const videoTexture = new THREE.VideoTexture(video);
videoTexture.needsUpdate = true;
const videoMaterial = new THREE.MeshBasicMaterial({
    map: videoTexture,
    side: THREE.FrontSide,
    toneMapped: false,
});
videoMaterial.needsUpdate = true;

//Create screen
const screen = new THREE.PlaneGeometry(10, 10);
const videoScreen = new THREE.Mesh(screen, videoMaterial);
scene.add(videoScreen);

Upvotes: 1

Haos
Haos

Reputation: 51

Step 1: Add a video to your HTML and "hide" it:

<video id="video" playsinline webkit-playsinline muted loop autoplay width="320" height="240" src="some-video.mp4" style="display: none;"></video>

Step 2:

//Get your video element:
const video = document.getElementById('video');

//Create your video texture:
const videoTexture = new THREE.VideoTexture(video);
const videoMaterial =  new THREE.MeshBasicMaterial( {map: videoTexture, side: THREE.FrontSide, toneMapped: false} );
//Create screen
const screen = new THREE.PlaneGeometry(1, 1);
const videoScreen = new THREE.Mesh(screen, videoMaterial);
scene.add(videoScreen);

Upvotes: 5

Alex Under
Alex Under

Reputation: 1489

Think of video as a sequence of images. So to "play" this video on your 3D object - you'll have to pass every single frame of that sequence to your material and then update that material.

Good place to start is here: https://github.com/mrdoob/three.js/wiki/Updates

And here: http://stemkoski.github.io/Three.js/Video.html

Upvotes: 7

Related Questions