mirror of
https://github.com/Rezmason/matrix.git
synced 2026-04-18 22:29:28 -07:00
By default, camera features are disabled; they're opted into by URL param and browser prompt.
This commit is contained in:
39
js/camera.js
Normal file
39
js/camera.js
Normal file
@@ -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 };
|
||||||
@@ -53,6 +53,7 @@ const fonts = {
|
|||||||
|
|
||||||
const defaults = {
|
const defaults = {
|
||||||
font: "matrixcode",
|
font: "matrixcode",
|
||||||
|
useCamera: false,
|
||||||
backgroundColor: [0, 0, 0], // The color "behind" the glyphs
|
backgroundColor: [0, 0, 0], // The color "behind" the glyphs
|
||||||
volumetric: false, // A mode where the raindrops appear in perspective
|
volumetric: false, // A mode where the raindrops appear in perspective
|
||||||
resurrectingCodeRatio: 0, // The percent of columns that flow upward
|
resurrectingCodeRatio: 0, // The percent of columns that flow upward
|
||||||
@@ -257,6 +258,7 @@ const paramMapping = {
|
|||||||
version: { key: "version", parser: (s) => s },
|
version: { key: "version", parser: (s) => s },
|
||||||
font: { key: "font", parser: (s) => s },
|
font: { key: "font", parser: (s) => s },
|
||||||
effect: { key: "effect", 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)) },
|
width: { key: "numColumns", parser: (s) => nullNaN(parseInt(s)) },
|
||||||
numColumns: { 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)) },
|
density: { key: "density", parser: (s) => nullNaN(range(parseFloat(s), 0)) },
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import makeResurrectionPass from "./resurrectionPass.js";
|
|||||||
import makeQuiltPass from "./quiltPass.js";
|
import makeQuiltPass from "./quiltPass.js";
|
||||||
import makeRipplesPass from "./ripplesPass.js";
|
import makeRipplesPass from "./ripplesPass.js";
|
||||||
import getLKG from "./lkgHelper.js";
|
import getLKG from "./lkgHelper.js";
|
||||||
|
import { setupCamera } from "../camera.js";
|
||||||
|
|
||||||
const effects = {
|
const effects = {
|
||||||
none: null,
|
none: null,
|
||||||
@@ -67,6 +68,10 @@ export default async (canvas, config) => {
|
|||||||
|
|
||||||
const lkg = await getLKG(config.useHoloplay, true);
|
const lkg = await getLKG(config.useHoloplay, true);
|
||||||
|
|
||||||
|
if (config.useCamera) {
|
||||||
|
await setupCamera();
|
||||||
|
}
|
||||||
|
|
||||||
// All this takes place in a full screen quad.
|
// All this takes place in a full screen quad.
|
||||||
const fullScreenQuad = makeFullScreenQuad(regl);
|
const fullScreenQuad = makeFullScreenQuad(regl);
|
||||||
const effectName = config.effect in effects ? config.effect : "plain";
|
const effectName = config.effect in effects ? config.effect : "plain";
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { loadImage, loadText, makePassFBO, makePass } from "./utils.js";
|
import { loadImage, loadText, makePassFBO, makePass } from "./utils.js";
|
||||||
|
import { cameraCanvas, cameraAspectRatio } from "../camera.js";
|
||||||
|
|
||||||
let start = Date.now();
|
let start = Date.now();
|
||||||
const numClicks = 5;
|
const numClicks = 5;
|
||||||
@@ -13,38 +14,9 @@ window.onclick = (e) => {
|
|||||||
index = (index + 1) % numClicks;
|
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) => {
|
export default ({ regl, config }, inputs) => {
|
||||||
|
|
||||||
getCameraFeed();
|
const cameraTex = regl.texture(cameraCanvas);
|
||||||
const cameraTex = regl.texture(canvas);
|
|
||||||
|
|
||||||
start = Date.now();
|
start = Date.now();
|
||||||
|
|
||||||
@@ -73,8 +45,7 @@ export default ({ regl, config }, inputs) => {
|
|||||||
aspectRatio = w / h;
|
aspectRatio = w / h;
|
||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
context.drawImage(video, 0, 0);
|
cameraTex(cameraCanvas);
|
||||||
cameraTex(canvas);
|
|
||||||
render({ frag: ripplesPassFrag.text() });
|
render({ frag: ripplesPassFrag.text() });
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user