From 8aeb156875d601c88e57098504cd6a8705eb6678 Mon Sep 17 00:00:00 2001 From: Rezmason Date: Tue, 2 Aug 2022 21:23:27 -0700 Subject: [PATCH] By default, camera features are disabled; they're opted into by URL param and browser prompt. --- js/camera.js | 39 +++++++++++++++++++++++++++++++++++++++ js/config.js | 2 ++ js/regl/main.js | 5 +++++ js/regl/ripplesPass.js | 35 +++-------------------------------- 4 files changed, 49 insertions(+), 32 deletions(-) create mode 100644 js/camera.js diff --git a/js/camera.js b/js/camera.js new file mode 100644 index 0000000..f229615 --- /dev/null +++ b/js/camera.js @@ -0,0 +1,39 @@ +// TODO: switch to video-based texture +// TODO: mipmap? +const video = document.createElement("video"); +const cameraCanvas = document.createElement("canvas"); +cameraCanvas.width = 1; +cameraCanvas.height = 1; +const context = cameraCanvas.getContext("2d"); +let cameraAspectRatio = 1.0; + +const drawToCanvas = () => { + requestAnimationFrame(drawToCanvas); + context.drawImage(video, 0, 0); +}; + +const setupCamera = async () => { + try { + const stream = await navigator.mediaDevices.getUserMedia({video: { + width: { min: 800, ideal: 1280 }, + frameRate: { ideal: 60 } + }, audio: false}); + const videoTrack = stream.getVideoTracks()[0]; + const {width, height} = videoTrack.getSettings(); + + video.width = width; + video.height = height; + cameraCanvas.width = width; + cameraCanvas.height = height; + cameraAspectRatio = width / height; + + video.srcObject = stream; + video.play(); + + drawToCanvas(); + } catch (e) { + console.warn(`Camera not initialized: ${e}`); + } +}; + +export { cameraCanvas, cameraAspectRatio, setupCamera }; diff --git a/js/config.js b/js/config.js index c6e2e9e..b3702d3 100644 --- a/js/config.js +++ b/js/config.js @@ -53,6 +53,7 @@ const fonts = { const defaults = { font: "matrixcode", + useCamera: false, backgroundColor: [0, 0, 0], // The color "behind" the glyphs volumetric: false, // A mode where the raindrops appear in perspective resurrectingCodeRatio: 0, // The percent of columns that flow upward @@ -257,6 +258,7 @@ const paramMapping = { version: { key: "version", parser: (s) => s }, font: { key: "font", parser: (s) => s }, effect: { key: "effect", parser: (s) => s }, + camera: { key: "useCamera", parser: (s) => s.toLowerCase().includes("true") }, width: { key: "numColumns", parser: (s) => nullNaN(parseInt(s)) }, numColumns: { key: "numColumns", parser: (s) => nullNaN(parseInt(s)) }, density: { key: "density", parser: (s) => nullNaN(range(parseFloat(s), 0)) }, diff --git a/js/regl/main.js b/js/regl/main.js index eb47144..877ab96 100644 --- a/js/regl/main.js +++ b/js/regl/main.js @@ -9,6 +9,7 @@ import makeResurrectionPass from "./resurrectionPass.js"; import makeQuiltPass from "./quiltPass.js"; import makeRipplesPass from "./ripplesPass.js"; import getLKG from "./lkgHelper.js"; +import { setupCamera } from "../camera.js"; const effects = { none: null, @@ -67,6 +68,10 @@ export default async (canvas, config) => { const lkg = await getLKG(config.useHoloplay, true); + if (config.useCamera) { + await setupCamera(); + } + // All this takes place in a full screen quad. const fullScreenQuad = makeFullScreenQuad(regl); const effectName = config.effect in effects ? config.effect : "plain"; diff --git a/js/regl/ripplesPass.js b/js/regl/ripplesPass.js index c0a6d01..61d4404 100644 --- a/js/regl/ripplesPass.js +++ b/js/regl/ripplesPass.js @@ -1,4 +1,5 @@ import { loadImage, loadText, makePassFBO, makePass } from "./utils.js"; +import { cameraCanvas, cameraAspectRatio } from "../camera.js"; let start = Date.now(); const numClicks = 5; @@ -13,38 +14,9 @@ window.onclick = (e) => { index = (index + 1) % numClicks; } -// TODO: switch to video-based texture -// TODO: mipmap? -const video = document.createElement("video"); -const canvas = document.createElement("canvas"); -const context = canvas.getContext("2d"); -let cameraAspectRatio = 1.0; - -const getCameraFeed = async () => { - try { - const stream = await navigator.mediaDevices.getUserMedia({video: { - width: { min: 800, ideal: 1280 }, - frameRate: { ideal: 60 } - }, audio: false}); - const videoTrack = stream.getVideoTracks()[0]; - const {width, height} = videoTrack.getSettings(); - console.log(videoTrack.getSettings()); - - video.width = width; - video.height = height; - canvas.width = width; - canvas.height = height; - cameraAspectRatio = width / height; - - video.srcObject = stream; - video.play(); - } catch (e) {} -}; - export default ({ regl, config }, inputs) => { - getCameraFeed(); - const cameraTex = regl.texture(canvas); + const cameraTex = regl.texture(cameraCanvas); start = Date.now(); @@ -73,8 +45,7 @@ export default ({ regl, config }, inputs) => { aspectRatio = w / h; }, () => { - context.drawImage(video, 0, 0); - cameraTex(canvas); + cameraTex(cameraCanvas); render({ frag: ripplesPassFrag.text() }); } );