Three.jsでテクスチャに動画を貼り付けて再生することはできるが、
透過情報を持った動画を再生する方法は中々見つからなかったので、
今回はテクスチャをキーイングして動画を透過させる
#オブジェクトとテクスチャを作成
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)
#結果
表示できました
境界線のジャギが少し気になるので、描写精度を優先するならあまり使い物にはならないかなー
Webmなら透過動画が使用できるけど、iOSでは動作しないので...
いい方法がありましたら教えてください