/* USER DATA */
const videoLink = 'https://mywebar-a.akamaihd.net/9168/226989/green-screen-sample.mp4';
const videoVolume = 1;
const chromaKeyColor = new THREE.Color(0x00ff00);
/* END OF USER DATA */
/* Scene Logic */
let video, videoPromise, videoTexture, videoMaterial;
function init(json, init_callbacks) {
const removeColor = new THREE.Color(0x00ff00); // Set the color to remove (green)
const removeColorUniform = { value: removeColor }; // Create a uniform for the color to remove
videoPromise = init_callbacks
.loadVideo(videoLink, {
autoplay: true,
loop: true,
})
.then((v) => {
video = v;
video.volume = videoVolume;
videoTexture = new THREE.VideoTexture(video.target);
videoTexture.minFilter = THREE.LinearFilter;
videoTexture.magFilter = THREE.LinearFilter;
const vertexShader = `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
`;
const fragmentShader = `
uniform sampler2D tex;
uniform float texWidth;
uniform float texHeight;
uniform vec3 keyColor;
uniform float similarity;
uniform float smoothness;
uniform float spill;
varying vec2 vUv;
vec2 RGBtoUV(vec3 rgb) {
return vec2(
rgb.r * -0.169 + rgb.g * -0.331 + rgb.b * 0.5 + 0.5,
rgb.r * 0.5 + rgb.g * -0.419 + rgb.b * -0.081 + 0.5
);
}
vec4 ProcessChromaKey(vec2 texCoord) {
vec4 rgba = texture2D(tex, texCoord);
float chromaDist = distance(RGBtoUV(texture2D(tex, texCoord).rgb), RGBtoUV(keyColor));
float baseMask = chromaDist - similarity;
float fullMask = pow(clamp(baseMask / smoothness, 0., 1.), 1.5);
rgba.a = fullMask;
float spillVal = pow(clamp(baseMask / spill, 0., 1.), 1.5);
float desat = clamp(rgba.r * 0.2126 + rgba.g * 0.7152 + rgba.b * 0.0722, 0., 1.);
rgba.rgb = mix(vec3(desat, desat, desat), rgba.rgb, spillVal);
return rgba;
}
void main(void) {
vec2 texCoord = vUv;
gl_FragColor = ProcessChromaKey(texCoord);
}
`;
videoMaterial = new THREE.ShaderMaterial({
uniforms: {
tex: {
value: videoTexture,
},
keyColor: {value: chromaKeyColor},
similarity: {value: 0.1},
smoothness: {value: 0.2},
spill: {value: 0.1},
},
vertexShader: vertexShader,
fragmentShader: fragmentShader,
transparent: true,
});
this.material = videoMaterial;
});
}
function mywebar_fill_init_promises(init_promises) {
init_promises.push(videoPromise);
}
function mywebar_fill_medias(medias) {
medias.push(video);
}
/**
* Start/resume playing scene
*/
function start() {
video.play();
}
/**
* End/pause playing scene
*/
function stop() {
video.pause();
}
/**
* Unload event, free up memory
*/
function mywebar_destroy() {
video.destroy();
videoTexture.dispose();
}