JSFiddle - React, Tailwind, and code Playground
by Henrique Barone
HTML
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/uikit.min.css">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/uikit.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r123/three.min.js"></script>
<script src="https://unpkg.com/[email protected]/examples/js/controls/OrbitControls.js"></script>
<video id="webcamVideo" style="display:none" autoplay playsinline></video>
<canvas id="composition" style="background-image: url(https://jameshfisher.com/assets/2020-08-11/bookshelf.jpg); background-size: cover; max-width: initial"></canvas>
<table class="uk-table uk-table-divider" >
<tbody>
<tr><th></th>
<!--<td><button class="uk-button uk-button-default" onclick="">Start webcam</button></td></tr>-->
<tr><th>Key color</th>
<td><input type="color" id="keyColor" value="#00ff00" /></td></tr>
<tr><th>Similarity</th>
<td><input type="range" id="similarity" min="0" max="1" step="0.001" value="0.4" /></td></tr>
<tr><th>Smoothness</th>
<td><input type="range" id="smoothness" min="0" max="1" step="0.001" value="0.08" /></td></tr>
<tr><th>Spill</th>
<td><input type="range" id="spill" min="0" max="1" step="0.001" value="0.1" /></td></tr>
</tbody>
</table>
<script id="vertexShader" type="glsl">
attribute vec2 c;
void main(void) {
gl_Position = vec4(c, 0.0, 1.0);
}
</script>
<script id="fragmentShader" type="glsl">
precision mediump float;
uniform sampler2D tex;
uniform float texWidth;
uniform float texHeight;
uniform vec3 keyColor;
uniform float similarity;
uniform float smoothness;
uniform float spill;
// From https://github.com/libretro/glsl-shaders/blob/master/nnedi3/shaders/rgb-to-yuv.glsl
vec2 RGBtoUV(vec3 rgb) {
...
JavaScript
var video = document.getElementById("webcamVideo");
var displayCanvasEl = document.getElementById("composition");
ChromaKeyMaterial = function (width, height, keyColor) {
THREE.ShaderMaterial.call(this);
//displayCanvasEl.width = width;
//displayCanvasEl.height = height;
var keyColorLoc = new THREE.Color(keyColor);
//var m = document.getElementById("keyColor").value.match(/^#([0-9a-f]{6})$/i)[1];
//var keyColorLoc = new THREE.Color(parseInt( m.substr(0,2),16 )/255, parseInt( m.substr(2,2),16 )/255, parseInt( m.substr(4,2),16 )/255);
var similarityLoc = parseFloat(document.getElementById("similarity").value);
var smoothnessLoc = parseFloat(document.getElementById("smoothness").value);
var spillLoc = parseFloat(document.getElementById("spill").value);
var videoTexture = new THREE.VideoTexture(video);
videoTexture.minFilter = THREE.LinearFilter;
videoTexture.magFilter = THREE.LinearFilter;
/* capture */
var constraints = {
video: {
facingMode: "user",
width: { ideal: width },
height: { ideal: height }
}
};
navigator.mediaDevices.getUserMedia( constraints ).then( function ( stream ) {
// apply the stream to the video element used in the texture
video.srcObject = stream;
video.play();
} ).catch( function ( error ) {
console.error( 'Unable to access the camera/webcam.', error );
} );
/* / capture */
this.update = function () {
similarityLoc.needsUpdate = true;
smoothnessLoc.needsUpdate = true;
spillLoc.needsUpdate = true;
if (video.readyState === video.HAVE_ENOUGH_DATA) {
// displayCanvasElContext.drawImage(video, 0, 0);
if (videoTexture) {
videoTexture.needsUpdate = true;
}
}
};
this.setValues({
uniforms: {
tex: {
type: "t",
value: videoTexture
},
keyColor: {
type: "vec3",
...