0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Three.jsでグリーンバック動画をテクスチャにする

Posted at

Three.jsでテクスチャに動画を貼り付けて再生することはできるが、
透過情報を持った動画を再生する方法は中々見つからなかったので、
今回はテクスチャをキーイングして動画を透過させる

#準備
何でもよいので、GB動画を用意してください。
ezgif-2-53d490eb6667.gif

#オブジェクトとテクスチャを作成
Three.jsの基礎は知っている前提で、要所だけ記述します。

const geometry = new THREE.PlaneBufferGeometry(1.6, .9);

比率が動画と合っているならサイズは何でも可


const video = document.createElement('video') //動画ファイルをhtmlへ埋め込む
video.src = './texture.mp4'
video.setAttribute('playsinline', '')
video.style.display = 'none'
video.muted = 'true'
video.play()
const videotexture = new THREE.VideoTexture(video) //テクスチャへ貼り付け

読み込んだ動画をテスクチャローダーで指定します。

#マテリアルを作成
シェダーマテリアルを作成します
vertexShaderとfragmentShaderは特に考えずに定義してください。

const material = new THREE.ShaderMaterial({
    transparent: true,
    uniforms: {
        map: { value: videotexture },
        keyColor: { value: [0.0, 1.0, 0.0] },
        similarity: { value: 0.7 },
        smoothness: { value: 0 },
    },
    vertexShader: vertexShader(),
    fragmentShader: fragmentShader(),
})

function vertexShader() {
    return `
        varying vec2 vUv;
        void main( void ) {     
            vUv = uv;
            gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
        }
    `
  }
  
  function fragmentShader() {
    return `
        uniform vec3 keyColor;
        uniform float similarity;
        uniform float smoothness;
        varying vec2 vUv;
        uniform sampler2D map;
        void main() {
            vec4 videoColor = texture2D(map, vUv);
            float Y1 = 0.299 * keyColor.r + 0.587 * keyColor.g + 0.114 * keyColor.b;
            float Cr1 = keyColor.r - Y1;
            float Cb1 = keyColor.b - Y1;
            
            float Y2 = 0.299 * videoColor.r + 0.587 * videoColor.g + 0.114 * videoColor.b;
            float Cr2 = videoColor.r - Y2; 
            float Cb2 = videoColor.b - Y2; 
            
            float blend = smoothstep(similarity, similarity + smoothness, distance(vec2(Cr2, Cb2), vec2(Cr1, Cb1)));
            gl_FragColor = vec4(videoColor.rgb, videoColor.a * blend); 
        }
    `
  }

// Mesh
const sphere = new THREE.Mesh(geometry,material)
scene.add(sphere)

#結果
Animation.gif
表示できました


境界線のジャギが少し気になるので、描写精度を優先するならあまり使い物にはならないかなー
Webmなら透過動画が使用できるけど、iOSでは動作しないので...
いい方法がありましたら教えてください

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?