diff --git a/README.md b/README.md index 8c8429a..d57cc45 100644 --- a/README.md +++ b/README.md @@ -30,3 +30,7 @@ WebGL ([Three.js](https://threejs.org/), [SwissGL](https://google.github.io/swis #### High-level architecture and modules: ![Architecture](media/LordTubeMaster.svg) + +
+ +Exhibited in /'fu:bar/ glitch art festival exhibition in 2024. \ No newline at end of file diff --git a/models/dotcamera.js b/models/dotcamera.js index 0bcc358..b6714ba 100644 --- a/models/dotcamera.js +++ b/models/dotcamera.js @@ -12,9 +12,9 @@ export default class DotCamera { this.rgbMode = rgbMode; } - frame(video, {canvasSize, DPR=devicePixelRatio, loop_start=0}) { - const dayMode = loop_start ? loop_start % 2 : this.dayMode; - const rgbMode = !!(loop_start ? (loop_start/2|0) % 2 : this.rgbMode); + frame(video, {canvasSize, DPR=devicePixelRatio, random_mode}) { + const dayMode = (random_mode/2|0) % 2 != this.dayMode; + const rgbMode = random_mode % 2 != this.rgbMode; const tex = this.glsl({}, {data:video, tag:'video'}); canvasSize = canvasSize ?? tex.size; const blendParams = dayMode ? {Clear:1, Blend:'d-s'} : {Clear:0, Blend:'d+s'}; diff --git a/models/ruttetraizer.js b/models/ruttetraizer.js index e721413..57bdbf9 100644 --- a/models/ruttetraizer.js +++ b/models/ruttetraizer.js @@ -4,10 +4,10 @@ const scale_rate = .01 const min_scale = 1 const max_scale = 10 -const rot_rate_x = .0003 +const rot_rate_x = .0005 const rot_rate_y = .0002 -const min_rot = .33 -const max_rot = .66 +const min_rot = .4 +const max_rot = .6 let scale = 2 let pointer_x = .5 @@ -48,7 +48,7 @@ export default class RuttEtraIzer { canvas.addEventListener('wheel', e => scale = Math.max(min_scale, Math.min(scale + e.deltaY*scale_rate, max_scale)), {passive: true}) } - frame(W, H, rgbx, {scanStep=7, depth=100, loop_start=0}={}) { + frame(W, H, rgbx, {scanStep=7, depth=100, random_mode}={}) { const THREE = this.THREE if (this.lineGroup) { @@ -72,7 +72,7 @@ export default class RuttEtraIzer { geometry.setAttribute('color', new THREE.BufferAttribute(new Float32Array(colors), 3)) this.lineGroup.add(new THREE.Line(geometry, this.material)) } - if (loop_start) { + if (random_mode) { const rand = Math.random() if (rand > .5) { pointer_x += rot_dir_x * rot_rate_x diff --git a/script.js b/script.js index 54e566b..e9a0413 100644 --- a/script.js +++ b/script.js @@ -11,10 +11,10 @@ import { ImageSegmenter, FilesetResolver, DrawingUtils -} from 'https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@0.10.15/vision_bundle.mjs' -const mediapipe_wasm_url = 'https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@0.10.15/wasm' +} from 'https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@0.10.17/vision_bundle.mjs' +const mediapipe_wasm_url = 'https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@0.10.17/wasm' -import {AutoModel, AutoProcessor, RawImage, env as transformersEnv} from 'https://cdn.jsdelivr.net/npm/@huggingface/transformers@3.0.0-alpha.19/dist/transformers.min.js' +import {AutoModel, AutoProcessor, RawImage, env as transformersEnv} from 'https://cdn.jsdelivr.net/npm/@huggingface/transformers@3.0.0-alpha.20/dist/transformers.min.js' import 'https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@4.21.0/dist/tf.min.js' import 'https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-backend-webgpu@4.21.0/dist/tf-backend-webgpu.min.js' @@ -25,7 +25,7 @@ ort.env.wasm.wasmPaths = 'https://cdn.jsdelivr.net/npm/onnxruntime-web@1.19.2/di import SwissGL from './libs/swissgl/swissgl.mjs' import DotCamera from './models/dotcamera.js' -import * as THREE from 'https://cdn.jsdelivr.net/npm/three@0.168.0/build/three.module.min.js' +import * as THREE from 'https://cdn.jsdelivr.net/npm/three@0.169.0/build/three.module.min.js' import RuttEtraIzer from './models/ruttetraizer.js' function getGPUInfo() { @@ -74,15 +74,14 @@ video_url.addEventListener('focus', e => { e.currentTarget.select() // Broken in Chrome. See: https://issues.chromium.org/issues/40345011#comment45 }) -let loop_mode, loop_start +let loop_mode, dotcamera_mode effect.addEventListener('change', e => { if (e.currentTarget.value) capture() loop_mode = null - loop_start = 0 if (e.currentTarget.value == 'loop' || e.currentTarget.value == 'random') { loop_mode = e.currentTarget.value - loop_start = performance.now() + dotcamera_mode = 0 loop_effects() } }) @@ -98,6 +97,7 @@ document.addEventListener('keydown', e => { function loop_effects() { if (!loop_mode || !capture_started) return + // dotcamera_mode += effect.value == 'dotcamera_swissgl' const effects = [...effect.querySelectorAll('option:not([disabled]):not([label="meta" i] > *)')].map(e => e.value) effect.value = effects[(effects.indexOf(effect.value)+(loop_mode == 'random' ? Math.random()*(effects.length-1) + 1 | 0 : 1)) % effects.length] setTimeout(loop_effects, loop_secs * 1000) @@ -293,7 +293,7 @@ const effect_funcs = { canvas.width = gl_canvas.width = W canvas.height = gl_canvas.height = H } - models.dotcamera.frame(videoFrame, {canvasSize: [W, H], DPR: 1.5, loop_start: loop_start}) + models.dotcamera.frame(videoFrame, {canvasSize: [W, H], DPR: 1.5, random_mode: loop_mode ? dotcamera_mode : 0}) canvasCtx.drawImage(gl_canvas, 0, 0) }, @@ -306,7 +306,7 @@ const effect_funcs = { canvas.height = gl_canvas.height = H renderer.setViewport(0, 0, W, H) } - models.ruttetra.frame(W, H, rgbx, {scanStep: 7, depth: 100, loop_start: loop_start}) + models.ruttetra.frame(W, H, rgbx, {scanStep: 7, depth: 100, random_mode: loop_mode}) canvasCtx.drawImage(gl_canvas, 0, 0) }, @@ -590,4 +590,6 @@ async function capture() { }) trackProcessor.readable.pipeThrough(transformer).pipeTo(trackGenerator.writable) out_video.srcObject = new MediaStream([trackGenerator]) + if (loop_mode) + loop_effects() } \ No newline at end of file