Skip to content

Commit

Permalink
code refactor; update libraries; fix fullscreen alignment and aspect;…
Browse files Browse the repository at this point in the history
… tests for video loader; ruttetraizer
  • Loading branch information
eyaler committed Sep 13, 2024
1 parent bfd7a59 commit 914df12
Show file tree
Hide file tree
Showing 10 changed files with 495 additions and 183 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ For fullscreen zoom of output (with right-click) enable: `chrome://flags/#elemen

You can browse the effects with `Alt+↑` and `Alt+↓`

The code demos usages with MediaPipe/Wasm, TF.js/WebGPU, ONNX-Runtime/WebGPU, SwissGL and VanillaJS.
The code demos usages with MediaPipe/Wasm, TF.js/WebGPU, ONNX-Runtime/WebGPU, SwissGL, Three.js and VanillaJS.

<br>

Expand Down
12 changes: 6 additions & 6 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
<script src="script.js" type="module"></script>
</head>
<body onload="video_url.value = location.hash.slice(1); video_url.select(); video_url.dispatchEvent(new Event('change'))"> <!-- Chromium allows requesting screen capture without user gesture (against the spec). See: https://issues.chromium.org/issues/40177563 -->
<div id="inp_container">
<input type="text" id="video_url" autofocus inputmode="url" spellcheck="false" size="45" placeholder="Enter YouTube/Vimeo ID or any URL">
<div id="inputs">
<input type="text" id="video_url" autofocus inputmode="url" spellcheck="false" size="45" placeholder="Enter YouTube / Vimeo ID + params or any URL">
<select id="effect" title="Browse with Alt+↑ / Alt+↓" aria-keyshortcuts="Alt+ArrowUp Alt+ArrowDown">
<optgroup label="MediaPipe/Wasm">
<option value="recode_landmarks">Recode + landmarks</option>
Expand All @@ -21,20 +21,20 @@
<option value="cartoonization_tfjs_webgpu">Cartoonization (TF.js/WebGPU)</option>
<option value="teed_edge_detection_ort_webgpu">TEED edge detection (ORT/WebGPU)</option>
<option value="dot_camera_swissgl">Dot "camera" (SwissGL)</option>
<option value="ruttetraizer_threejs">Rutt-Etra-Izer with mouse (Three.js)</option>
<option value="bayer_dithering">Bayer dithering</option>
<option value="pixel_sorting">Pixel sorting</option>
<optgroup label="Meta">
<option value="recode_original">Recode original</option>
<option value="loop">Loop all effects</option>
<option value="random">Randomize all effects</option>
</optgroup>

</select>
</div>
<iframe id="orig_video" allow="autoplay; fullscreen" allowfullscreen></iframe>
<div id="out_container">
<div id="videos">
<iframe id="orig_video" allow="autoplay; fullscreen" allowfullscreen></iframe>
<video id="out_video" autoplay muted playsinline></video>
<canvas id="canvas"></canvas>
<canvas id="canvas" class="hide_cursor"></canvas>
</div>
<footer>
<a href="https://github.com/eyaler/LordTubeMaster/">code</a>
Expand Down
23 changes: 12 additions & 11 deletions models/DotCamera.js → models/dotcamera.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,37 @@
*/

export default class DotCamera {
constructor(glsl, {dayMode=false, rgbMode=false}) {
constructor(glsl, {dayMode=false, rgbMode=false}={}) {
this.glsl = glsl;
this.dayMode = dayMode;
this.rgbMode = rgbMode;
}

frame(glsl, video, {canvasSize, DPR}) {
const tex = glsl({}, {data:video, tag:'video'});
frame(video, {canvasSize, DPR}) {
const tex = this.glsl({}, {data:video, tag:'video'});
const blendParams = this.dayMode ? {Clear:1, Blend:'d-s'} : {Clear:0, Blend:'d+s'};
const rgbMode = this.rgbMode;
const lum = glsl({tex:tex.edge.linear, ...blendParams, rgbMode,
const lum = this.glsl({tex:tex.edge.linear, ...blendParams, rgbMode,
VP:`vec2 r = vec2(ViewSize)/vec2(tex_size()); r /= max(r.x, r.y); VPos.xy = XY/r;`, FP:`
FOut = tex(UV);
if (!rgbMode) {
FOut.r = dot(FOut.rgb, vec3(0.21,0.72,0.07));
FOut.r = dot(FOut.rgb, vec3(0.2126,0.7152,0.0722));
}`},
{scale:1/2/DPR, tag:'lum'});
const merged = glsl({T:lum.edge.miplinear, FP:`
const merged = this.glsl({T:lum.edge.miplinear, FP:`
for (float lod=0.; lod<8.0; lod+=1.0) {FOut += textureLod(T, UV, lod);}
FOut /= 8.0;`}, {size:lum.size, format:'rgba16f', tag:'merged'});
const imgForce = glsl({T:merged.edge, FP:`
const imgForce = this.glsl({T:merged.edge, FP:`
vec2 s=T_step();
vec4 a=T(UV-s), b=T(UV+vec2(s.x,-s.y)), c=T(UV+vec2(-s.x,s.y)), d=T(UV+s);
FOut = b+d-a-c; FOut1 = c+d-a-b;`
}, {size:lum.size, layern:2, format:'rgba16f', tag:'grad'});

const arg = {canvasSize, rgbMode};
const field = glsl({}, {scale:1/4/DPR, format:'rgba16f', layern:3, filter:'linear', tag:'field'});
const field = this.glsl({}, {scale:1/4/DPR, format:'rgba16f', layern:3, filter:'linear', tag:'field'});
let points;
for (let i=0; i<10; ++i) {
points = glsl({...arg, field:field.edge, imgForce:imgForce.edge.linear, seed: Math.random()*124237, FP: `
points = this.glsl({...arg, field:field.edge, imgForce:imgForce.edge.linear, seed: Math.random()*124237, FP: `
int c = rgbMode ? I.x%3 : 0;
vec4 p=Src(I), f=field(p.xy, c);
if (p.w == 0.0) {
Expand All @@ -48,15 +49,15 @@ export default class DotCamera {
p.xy = clamp(p.xy + force/canvasSize, vec2(0), vec2(1));
FOut = p;
`}, {scale:(rgbMode?1.7:1)/8/DPR, story:2, format:'rgba32f', tag:'points'});
glsl({...arg, points:points[0], Grid: points[0].size, Blend:'s+d', Clear:0, VP:`
this.glsl({...arg, points:points[0], Grid: points[0].size, Blend:'s+d', Clear:0, VP:`
VPos.xy = (points(ID.xy).xy + XY*15.0/canvasSize)*2.0-1.0;
int c = rgbMode ? ID.x%3 : 0;
varying vec3 color = vec3(c==0,c==1,c==2);`,FP:`
vec4 v = vec4(vec3(XY,1.)*exp(-dot(XY,XY)*vec3(4,4,8)), 0);
FOut=v*color.r; FOut1=v*color.g; FOut2=v*color.b;`}, field)
}
// draw dots on screen
glsl({...arg, points:points[0], Grid: points[0].size, ...blendParams, VP:`
this.glsl({...arg, points:points[0], Grid: points[0].size, ...blendParams, VP:`
VPos.xy = (points(ID.xy).xy + XY*4.0/canvasSize)*2.0-1.0;
int c = ID.x%3;
varying vec3 color = rgbMode ? vec3(c==0,c==1,c==2) : vec3(1);`,
Expand Down
73 changes: 73 additions & 0 deletions models/ruttetraizer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// Based on https://www.airtightinteractive.com/2011/06/rutt-etra-izer/
// Original RuttEtraIzer by Felix Turner www.airtight.cc

const scale_rate = .01
let scale = 2
let pointer_x = .5
let pointer_y = .5
let down_x
let down_y

export default class RuttEtraIzer {
constructor(THREE, renderer, canvas) {
this.THREE = THREE
this.renderer = renderer
this.camera = new THREE.PerspectiveCamera(90, 16 / 9, 1, 3000)
this.scene = new THREE.Scene()

this.material = new THREE.LineBasicMaterial({
color: 0xffffff,
blending: THREE.AdditiveBlending,
depthTest: false,
vertexColors: true,
})

canvas.addEventListener('pointerdown', e => {down_x = e.clientX; down_y = e.clientY})

document.addEventListener('pointerup', () => down_x = down_y = null)

document.addEventListener('pointermove', e => {
if (down_x != null && down_y != null && down_x != e.clientX && down_y != e.clientY) {
const b = canvas.getBoundingClientRect()
pointer_x = Math.max(0, Math.min((e.clientX-b.left) / b.width, 1))
pointer_y = Math.max(0, Math.min((e.clientY-b.top) / b.height, 1))
down_x = e.clientX
down_y = e.clientY
}
})

canvas.addEventListener('wheel', e => scale = Math.max(1, Math.min(scale + e.deltaY*scale_rate, 10)), {passive: true})
}

frame(W, H, rgbx, {scanStep=5, depth=100}={}) {
const THREE = this.THREE

if (this.lineGroup) {
this.scene.remove(this.lineGroup)
this.lineGroup.traverse(obj => obj.geometry?.dispose())
}
this.lineGroup = new THREE.Group()

for (let y = 0; y < H; y += scanStep) {
const points = []
const colors = []
for (let x = 0; x < W; x += scanStep) {
const index4 = (x+y*W) * 4
const color = new THREE.Color(rgbx[index4] / 255, rgbx[index4 + 1] / 255, rgbx[index4 + 2] / 255).convertSRGBToLinear()
const brightness = .2126*color.r + .7152*color.g + .0722*color.b
points.push(new THREE.Vector3(x - W/2, H/2 - y, (.5-brightness) * depth))
colors.push(color.r, color.g, color.b)
}
const geometry = new THREE.BufferGeometry().setFromPoints(points)
geometry.setAttribute('color', new THREE.BufferAttribute(new Float32Array(colors), 3))
this.lineGroup.add(new THREE.Line(geometry, this.material))
}
this.lineGroup.scale.setScalar(scale)
this.lineGroup.rotation.x = (pointer_y*2-1)*Math.PI
this.lineGroup.rotation.y = (pointer_x*2-1)*Math.PI
this.scene.add(this.lineGroup)
if (this.camera.position.z != H)
this.camera.position.z = H
this.renderer.render(this.scene, this.camera)
}
}
Loading

0 comments on commit 914df12

Please sign in to comment.