rgbd 0.0.9 → 0.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/rgbd.js +86 -85
  2. package/package.json +2 -2
package/dist/rgbd.js CHANGED
@@ -1,86 +1,87 @@
1
- const g=`#version 300 es
2
- precision mediump float;
3
- precision mediump int;
4
-
5
- uniform sampler2D u_depthImage;
6
- uniform mat4 u_projMat;
7
- uniform mat4 u_viewMat;
8
- uniform vec2 u_imageSize;
9
- uniform float u_focal;
10
- uniform float u_depthMin;
11
- uniform float u_depthMax;
12
- uniform ivec2 u_grid;
13
-
14
- out vec2 v_uv;
15
-
16
- void main()
17
- {
18
- int vid = gl_VertexID;
19
- int quad = vid / 6;
20
- int v = vid - quad * 6;
21
-
22
- int widthGrid = u_grid.x;
23
- int heightGrid = u_grid.y;
24
-
25
- int x = quad % widthGrid;
26
- int y = quad / widthGrid;
27
-
28
- float fx = float(x) / float(widthGrid);
29
- float fy = float(y) / float(heightGrid);
30
- float fx1 = float(x + 1) / float(widthGrid);
31
- float fy1 = float(y + 1) / float(heightGrid);
32
-
33
- vec2 uv00 = vec2(fx , 1.0 - fy);
34
- vec2 uv10 = vec2(fx1, 1.0 - fy);
35
- vec2 uv01 = vec2(fx , 1.0 - fy1);
36
- vec2 uv11 = vec2(fx1, 1.0 - fy1);
37
-
38
- vec2 uv;
39
- if (v == 0) uv = uv00;
40
- else if (v == 1) uv = uv10;
41
- else if (v == 2) uv = uv01;
42
- else if (v == 3) uv = uv10;
43
- else if (v == 4) uv = uv11;
44
- else uv = uv01;
1
+ const b=typeof window<"u"&&typeof HTMLElement<"u"&&typeof document<"u";let l,m,p;if(!b)l=class{},m=class{},p=class{};else{const A=`#version 300 es
45
2
 
46
- float depth = texture(u_depthImage, uv).r;
47
- float z = mix(u_depthMin, u_depthMax, depth);
48
-
49
- vec2 pixelPos = uv * u_imageSize;
50
- vec2 pos = (pixelPos - u_imageSize * 0.5) * z / u_focal;
51
-
52
- v_uv = uv;
53
- gl_Position = u_projMat * u_viewMat * vec4(pos.x, pos.y, z, 1.0);
54
- }
55
-
56
- `,v=`#version 300 es
57
-
58
- precision mediump float;
59
-
60
- in vec2 v_uv;
61
-
62
- out vec4 fragColor;
63
-
64
- uniform sampler2D u_colorImage;
65
- uniform sampler2D u_depthImage;
66
-
67
- uniform vec2 u_targetRes;
68
- uniform float u_discardCutoff;
69
-
70
- void main()
71
- {
72
- float deriv = min(
73
- length(dFdx(v_uv) * u_targetRes),
74
- length(dFdy(v_uv) * u_targetRes)
75
- );
76
- if(deriv < u_discardCutoff)
77
- discard;
78
-
79
- fragColor = texture(u_colorImage, v_uv);
80
- }
81
- `;class m extends HTMLElement{constructor(){super(),this._params={GRID_SIZE:1e3,FOCAL_LENGTH:1200,DEPTH_MIN:.1,DEPTH_MAX:10,DISCARD_CUTOFF:0,CAM_RADIUS:1.5,CAM_MAX_THETA:Math.PI/40,CAM_MAX_PHI:Math.PI/64,CAM_FOV:Math.PI/4,CAM_SMOOTHNESS:.9,BOOMERANG_SPEED:.001,BACKGROUND_COLOR:[0,0,0]},this._shadowRoot=null,this._canvas=null,this._colorSource=null,this._depthSource=null,this._gl=null,this._shaderProgram=null,this._textures={},this._uniforms=null,this._mouse={x:0,y:0,hovered:!1},this._anim={theta:Math.PI,phi:0,radius:this._params.CAM_RADIUS},this._lastTime=0,this._animFrame=null,this._running=!1,this._userViewMat=null,this._userProjMat=null,this._onResizeHandler=null,this._onMouseMoveHandler=null,this._onMouseLeaveHandler=null,this._onRenderHandler=null,this._shadowRoot=this.attachShadow({mode:"open"});const t=document.createElement("div");t.style.position="relative",t.style.width="100%",t.style.height="100%",t.style.display="flex",t.style.alignItems="center",t.style.justifyContent="center",t.style.background="black",this._shadowRoot.appendChild(t);const e=document.createElement("style");e.textContent=`
82
- :host { display: inline-block; width: 300px; height: 200px; }
83
- :host([fullbleed]) { display:block; width:100%; height:100%; }
84
- canvas { touch-action: none; }
85
- .cover-img, .cover-video { position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: contain; pointer-events: none; }
86
- `,this._shadowRoot.appendChild(e),this._canvas=document.createElement("canvas"),this._canvas.style.width="100%",this._canvas.style.height="100%",this._canvas.style.objectFit="contain",this._canvas.setAttribute("role","img"),this._canvas.setAttribute("aria-label","3D image"),t.appendChild(this._canvas),this._onResizeHandler=this._onResize.bind(this),this._onMouseMoveHandler=this._onMouseMove.bind(this),this._onMouseLeaveHandler=this._onMouseLeave.bind(this),this._onRenderHandler=this._onRender.bind(this)}connectedCallback(){this._readParams();let t;try{this._init(),t=!1}catch{t=!0}window.addEventListener("resize",this._onResizeHandler),window.addEventListener("mousemove",this._onMouseMoveHandler),document.addEventListener("mouseleave",this._onMouseLeaveHandler),this._loadSources(),t?this._createFallback():(this._onResize(),this._running=!0,this._lastTime=performance.now(),this._animFrame=requestAnimationFrame(this._onRenderHandler))}disconnectedCallback(){this._running=!1,cancelAnimationFrame(this._animFrame),window.removeEventListener("resize",this._onResizeHandler),this._canvas.removeEventListener("pointermove",this._onMouseMoveHandler),this._canvas.removeEventListener("pointerleave",this._onMouseLeaveHandler);try{if(this._gl){const t=this._gl;this._shaderProgram&&t.deleteProgram(this._shaderProgram);for(let e in this._textures)t.deleteTexture(this._textures[e])}}catch{}}setViewMatrix(t){this._userViewMat=t&&t.length===16?new Float32Array(t):null}setProjectionMatrix(t){this._userProjMat=t&&t.length===16?new Float32Array(t):null}get width(){return this._getSourceWidth(this._colorSource)}get height(){return this._getSourceHeight(this._colorSource)}_init(){const t=this._canvas.getContext("webgl2",{antialias:!0,alpha:!1});if(!t)throw new Error("WebGL not supported");this._gl=t;const e=this._createProgram(t,g,v);if(!e)return;this._shaderProgram=e,t.useProgram(e);const o=this._createTexture(t),i=this._createTexture(t);this._textures.color=o,this._textures.depth=i,this._updateTexture("color",this._colorSource),this._updateTexture("depth",this._depthSource);const r=t.getUniformLocation(e,"u_colorImage"),a=t.getUniformLocation(e,"u_depthImage");t.uniform1i(r,0),t.uniform1i(a,1),this._uniforms={uProjection:t.getUniformLocation(e,"u_projMat"),uView:t.getUniformLocation(e,"u_viewMat"),uImageSize:t.getUniformLocation(e,"u_imageSize"),uFocal:t.getUniformLocation(e,"u_focal"),uDepthMin:t.getUniformLocation(e,"u_depthMin"),uDepthMax:t.getUniformLocation(e,"u_depthMax"),uGridSegs:t.getUniformLocation(e,"u_grid"),uTargetRes:t.getUniformLocation(e,"u_targetRes"),uDiscardCutoff:t.getUniformLocation(e,"u_discardCutoff")}}_onRender(t){if(!this._running||!this._gl)return;const e=this._gl,o=t-this._lastTime;this._lastTime=t,this._updateTexturesIfNeeded(),e.clearColor(...this._params.BACKGROUND_COLOR,1),e.clear(e.COLOR_BUFFER_BIT|e.DEPTH_BUFFER_BIT),e.enable(e.DEPTH_TEST),this._mouse.hovered||(this._mouse.x=Math.sin(t*this._params.BOOMERANG_SPEED),this._mouse.y=Math.sin(t*this._params.BOOMERANG_SPEED*.5+Math.PI));const i=this._mouse.x*this._params.CAM_MAX_THETA+Math.PI,r=-this._mouse.y*this._params.CAM_MAX_PHI,a=this._mouse.hovered?this._params.CAM_RADIUS*.8:this._params.CAM_RADIUS;this._anim.theta=this._animate(i,this._anim.theta,o),this._anim.phi=this._animate(r,this._anim.phi,o),this._anim.radius=this._animate(a,this._anim.radius,o);const c=this._canvas.width/this._canvas.height,h=Math.max(1,Math.floor(this._params.GRID_SIZE)),n=Math.max(1,Math.round(h/c)),s=this._getSourceWidth(this._colorSource),u=this._getSourceHeight(this._colorSource);e.uniform2f(this._uniforms.uImageSize,s,u),e.uniform1f(this._uniforms.uFocal,this._params.FOCAL_LENGTH),e.uniform1f(this._uniforms.uDepthMin,this._params.DEPTH_MIN),e.uniform1f(this._uniforms.uDepthMax,this._params.DEPTH_MAX),e.uniform2i(this._uniforms.uGridSegs,h,n),e.uniform2f(this._uniforms.uTargetRes,this._canvas.width,this._canvas.height),e.uniform1f(this._uniforms.uDiscardCutoff,this._params.DISCARD_CUTOFF);const _=[this._anim.radius*Math.cos(this._anim.phi)*Math.sin(this._anim.theta),this._anim.radius*Math.sin(this._anim.phi),this._params.CAM_RADIUS+this._anim.radius*Math.cos(this._anim.phi)*Math.cos(this._anim.theta)],d=[0,0,this._params.CAM_RADIUS],p=[0,-1,0],f=this._userViewMat||new Float32Array(this._lookAt(_,d,p)),S=this._userProjMat||new Float32Array(this._perspective(this._params.CAM_FOV,c,.1,100));e.uniformMatrix4fv(this._uniforms.uView,!1,f),e.uniformMatrix4fv(this._uniforms.uProjection,!1,S),e.drawArrays(e.TRIANGLES,0,h*n*6),this._animFrame=requestAnimationFrame(this._onRenderHandler)}_onMouseMove(t){const e=this._canvas.getBoundingClientRect();this._mouse.hovered=!0,this._mouse.x=(t.clientX-e.left)/e.width*2-1,this._mouse.y=(t.clientY-e.top)/e.height*2-1}_onMouseLeave(){this._mouse.hovered=!1}_onResize(){const t=window.devicePixelRatio||1,e=this._canvas.parentElement;if(!e)return;const o=e.clientWidth,i=e.clientHeight;let r=this._getSourceWidth(this._colorSource)||1,a=this._getSourceHeight(this._colorSource)||1;const c=r/a;let h=o,n=h/c;n>i&&(n=i,h=n*c);const s=Math.max(1,Math.floor(h*t)),u=Math.max(1,Math.floor(n*t));this._canvas.width=s,this._canvas.height=u,this._gl&&this._gl.viewport(0,0,s,u)}_readParams(){const t=this._params;if(this.hasAttribute("grid-size")&&(t.GRID_SIZE=parseInt(this.getAttribute("grid-size"))??t.GRID_SIZE),this.hasAttribute("focal-length")&&(t.FOCAL_LENGTH=parseFloat(this.getAttribute("focal-length"))??t.FOCAL_LENGTH),this.hasAttribute("depth-min")&&(t.DEPTH_MIN=parseFloat(this.getAttribute("depth-min"))??t.DEPTH_MIN),this.hasAttribute("depth-max")&&(t.DEPTH_MAX=parseFloat(this.getAttribute("depth-max"))??t.DEPTH_MAX),this.hasAttribute("discard-cutoff")&&(t.DISCARD_CUTOFF=parseFloat(this.getAttribute("discard-cutoff"))??t.DISCARD_CUTOFF),this.hasAttribute("cam-radius")&&(t.CAM_RADIUS=parseFloat(this.getAttribute("cam-radius"))??t.CAM_RADIUS),this.hasAttribute("cam-max-theta")&&(t.CAM_MAX_THETA=parseFloat(this.getAttribute("cam-max-theta"))??t.CAM_MAX_THETA),this.hasAttribute("cam-max-phi")&&(t.CAM_MAX_PHI=parseFloat(this.getAttribute("cam-max-phi"))??t.CAM_MAX_PHI),this.hasAttribute("cam-fov")&&(t.CAM_FOV=parseFloat(this.getAttribute("cam-fov"))??t.CAM_FOV),this.hasAttribute("cam-smoothness")&&(t.CAM_SMOOTHNESS=parseFloat(this.getAttribute("cam-smoothness"))??t.CAM_SMOOTHNESS),this.hasAttribute("boomerang-speed")&&(t.BOOMERANG_SPEED=parseFloat(this.getAttribute("boomerang-speed"))??t.BOOMERANG_SPEED),this.hasAttribute("background-color"))try{const e=this.getAttribute("background-color").split(",").map(Number);e.length===3&&(t.BACKGROUND_COLOR=e)}catch{}}_createShader(t,e,o){const i=t.createShader(e);return t.shaderSource(i,o),t.compileShader(i),t.getShaderParameter(i,t.COMPILE_STATUS)?i:(console.error(t.getShaderInfoLog(i)),t.deleteShader(i),null)}_createProgram(t,e,o){const i=this._createShader(t,t.VERTEX_SHADER,e),r=this._createShader(t,t.FRAGMENT_SHADER,o);if(!i||!r)return null;const a=t.createProgram();return t.attachShader(a,i),t.attachShader(a,r),t.linkProgram(a),t.getProgramParameter(a,t.LINK_STATUS)?(t.deleteShader(i),t.deleteShader(r),a):(console.error(t.getProgramInfoLog(a)),t.deleteProgram(a),null)}_createTexture(t){const e=t.createTexture();return t.bindTexture(t.TEXTURE_2D,e),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.LINEAR),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.LINEAR),e}_updateTexture(t,e){if(!this._gl)return;const o=this._gl,i=this._textures[t];if(o.activeTexture(t==="color"?o.TEXTURE0:o.TEXTURE1),o.bindTexture(o.TEXTURE_2D,i),!this._isSourceReady(e)){o.texImage2D(o.TEXTURE_2D,0,o.RGBA,1,1,0,o.RGBA,o.UNSIGNED_BYTE,new Uint8Array([0,0,0,0]));return}try{o.pixelStorei(o.UNPACK_FLIP_Y_WEBGL,!1),o.texImage2D(o.TEXTURE_2D,0,o.RGBA,o.RGBA,o.UNSIGNED_BYTE,e)}catch{}}_perspective(t,e,o,i){const r=1/Math.tan(t/2);return[r/e,0,0,0,0,r,0,0,0,0,(i+o)/(o-i),-1,0,0,2*i*o/(o-i),0]}_lookAt(t,e,o){function i(s){const u=Math.hypot(...s)||1;return s.map(_=>_/u)}function r(s,u){return[s[1]*u[2]-s[2]*u[1],s[2]*u[0]-s[0]*u[2],s[0]*u[1]-s[1]*u[0]]}function a(s,u){return s.map((_,d)=>_-u[d])}const c=i(a(t,e)),h=i(r(o,c)),n=r(c,h);return[h[0],n[0],c[0],0,h[1],n[1],c[1],0,h[2],n[2],c[2],0,-(h[0]*t[0]+h[1]*t[1]+h[2]*t[2]),-(n[0]*t[0]+n[1]*t[1]+n[2]*t[2]),-(c[0]*t[0]+c[1]*t[1]+c[2]*t[2]),1]}_animate(t,e,o){const i=(1-this._params.CAM_SMOOTHNESS)*o/16.67,r=Math.sign(t-e);return e+=(t-e)*i,Math.sign(t-e)!==r&&(e=t),e}_loadSources(){throw new Error("Must implement _loadSources")}_createFallback(){throw new Error("Must implement _createFallback")}_updateTexturesIfNeeded(){}_isSourceReady(t){throw new Error("Must implement _isSourceReady")}_getSourceWidth(t){throw new Error("Must implement _getSourceWidth")}_getSourceHeight(t){throw new Error("Must implement _getSourceHeight")}}class A extends m{static get observedAttributes(){return["color-src","depth-src","color-id","depth-id","grid-size","focal-length","depth-min","depth-max","discard-cutoff","cam-radius","cam-max-theta","cam-max-phi","cam-fov","cam-smoothness","boomerang-speed","background-color"]}constructor(){super(),this._colorSource=new Image,this._depthSource=new Image,this._colorSource.crossOrigin="anonymous",this._depthSource.crossOrigin="anonymous"}attributeChangedCallback(t,e,o){if(e!==o)if(t==="color-src")this._colorSource.src=o||"";else if(t==="depth-src")this._depthSource.src=o||"";else if(t==="color-id"){const i=document.getElementById(o);i instanceof HTMLImageElement&&(this._colorSource=i,i.complete?this._updateTexture("color",i):i.addEventListener("load",()=>this._updateTexture("color",i)))}else if(t==="depth-id"){const i=document.getElementById(o);i instanceof HTMLImageElement&&(this._depthSource=i,i.complete?this._updateTexture("depth",i):i.addEventListener("load",()=>this._updateTexture("depth",i)))}else this._readParams()}_loadSources(){const t=this.getAttribute("color-id"),e=this.getAttribute("depth-id"),o=this.getAttribute("color-src"),i=this.getAttribute("depth-src");if(t){const r=document.getElementById(t);r instanceof HTMLImageElement&&r.complete?(this._colorSource=r,this._updateTexture("color",this._colorSource)):r&&(r.addEventListener("load",()=>this._updateTexture("color",r)),this._colorSource=r)}else o&&(this._colorSource.src=o,this._colorSource.onload=()=>this._updateTexture("color",this._colorSource));if(e){const r=document.getElementById(e);r instanceof HTMLImageElement&&r.complete?(this._depthSource=r,this._updateTexture("depth",this._depthSource)):r&&(r.addEventListener("load",()=>this._updateTexture("depth",r)),this._depthSource=r)}else i&&(this._depthSource.src=i,this._depthSource.onload=()=>this._updateTexture("depth",this._depthSource))}_createFallback(){this.getAttribute("color-id")&&(this._colorSource=this._colorSource.cloneNode(),this._colorSource.id+="_threedad-img"),this._colorSource.style.display="block",this._colorSource.classList.add("cover-img"),this._canvas.parentElement.appendChild(this._colorSource)}_isSourceReady(t){return t&&t.complete&&t.naturalWidth>0}_getSourceWidth(t){return t?t.width:1}_getSourceHeight(t){return t?t.height:1}}class E extends m{static get observedAttributes(){return["color-src","depth-src","color-id","depth-id","grid-size","focal-length","depth-min","depth-max","discard-cutoff","cam-radius","cam-max-theta","cam-max-phi","cam-fov","cam-smoothness","boomerang-speed","background-color","autoplay","loop","muted"]}constructor(){super(),this._colorSource=document.createElement("video"),this._depthSource=document.createElement("video"),this._colorSource.crossOrigin="anonymous",this._depthSource.crossOrigin="anonymous",this._colorSource.playsInline=!0,this._depthSource.playsInline=!0,this._colorSource.muted=!0,this._depthSource.muted=!0}attributeChangedCallback(t,e,o){if(e!==o)if(t==="color-src")this._colorSource.src=o||"";else if(t==="depth-src")this._depthSource.src=o||"";else if(t==="color-id"){const i=document.getElementById(o);i instanceof HTMLVideoElement&&(this._colorSource=i,i.readyState>=i.HAVE_CURRENT_DATA?this._updateTexture("color",i):i.addEventListener("loadeddata",()=>this._updateTexture("color",i)))}else if(t==="depth-id"){const i=document.getElementById(o);i instanceof HTMLVideoElement&&(this._depthSource=i,i.readyState>=i.HAVE_CURRENT_DATA?this._updateTexture("depth",i):i.addEventListener("loadeddata",()=>this._updateTexture("depth",i)))}else t==="autoplay"?(this._colorSource.autoplay=this.hasAttribute("autoplay"),this._depthSource.autoplay=this.hasAttribute("autoplay")):t==="loop"?(this._colorSource.loop=this.hasAttribute("loop"),this._depthSource.loop=this.hasAttribute("loop")):t==="muted"?(this._colorSource.muted=this.hasAttribute("muted"),this._depthSource.muted=this.hasAttribute("muted")):this._readParams()}play(){return Promise.all([this._colorSource?.play(),this._depthSource?.play()])}pause(){this._colorSource?.pause(),this._depthSource?.pause()}get paused(){return this._colorSource?this._colorSource.paused:!0}get currentTime(){return this._colorSource?this._colorSource.currentTime:0}set currentTime(t){console.log(t),this._colorSource&&(this._colorSource.currentTime=t),this._depthSource&&(this._depthSource.currentTime=t)}_loadSources(){const t=this.getAttribute("color-id"),e=this.getAttribute("depth-id"),o=this.getAttribute("color-src"),i=this.getAttribute("depth-src");if(this.hasAttribute("autoplay")&&(this._colorSource.autoplay=!0,this._depthSource.autoplay=!0),this.hasAttribute("loop")&&(this._colorSource.loop=!0,this._depthSource.loop=!0),this.hasAttribute("muted")&&(this._colorSource.muted=!0,this._depthSource.muted=!0),t){const r=document.getElementById(t);r instanceof HTMLVideoElement&&(this._colorSource=r)}else o&&(this._colorSource.src=o);if(e){const r=document.getElementById(e);r instanceof HTMLVideoElement&&(this._depthSource=r)}else i&&(this._depthSource.src=i);this.hasAttribute("autoplay")?this.play().then(()=>{this._onResize()}):this.play().then(()=>{this.pause(),this._onResize()})}_createFallback(){this.getAttribute("color-id")&&(this._colorSource=this._colorSource.cloneNode(!0),this._colorSource.id+="_threedad-video"),this._colorSource.style.display="block",this._colorSource.classList.add("cover-video"),this._colorSource.controls=!0,this._canvas.parentElement.appendChild(this._colorSource)}_updateTexturesIfNeeded(){this._isSourceReady(this._colorSource)&&this._updateTexture("color",this._colorSource),this._isSourceReady(this._depthSource)&&this._updateTexture("depth",this._depthSource),Math.abs(this._colorSource.currentTime-this._depthSource.currentTime)>.01&&(this._depthSource.currentTime=this._colorSource.currentTime,this._colorSource.paused!==this._depthSource.paused&&(this._colorSource.paused?this._depthSource.pause():this._depthSource.play()))}_isSourceReady(t){return t&&t.readyState>=t.HAVE_CURRENT_DATA}_getSourceWidth(t){return t?t.videoWidth:1}_getSourceHeight(t){return t?t.videoHeight:1}}typeof window<"u"&&typeof customElements<"u"&&(customElements.define("rgbd-img",A),customElements.define("rgbd-video",E));
3
+ precision mediump float;
4
+ precision mediump int;
5
+
6
+ uniform sampler2D u_depthImage;
7
+ uniform mat4 u_projMat;
8
+ uniform mat4 u_viewMat;
9
+ uniform vec2 u_imageSize;
10
+ uniform float u_focal;
11
+ uniform float u_depthMin;
12
+ uniform float u_depthMax;
13
+ uniform ivec2 u_grid;
14
+
15
+ out vec2 v_uv;
16
+
17
+ void main()
18
+ {
19
+ int vid = gl_VertexID;
20
+ int quad = vid / 6;
21
+ int v = vid - quad * 6;
22
+
23
+ int widthGrid = u_grid.x;
24
+ int heightGrid = u_grid.y;
25
+
26
+ int x = quad % widthGrid;
27
+ int y = quad / widthGrid;
28
+
29
+ float fx = float(x) / float(widthGrid);
30
+ float fy = float(y) / float(heightGrid);
31
+ float fx1 = float(x + 1) / float(widthGrid);
32
+ float fy1 = float(y + 1) / float(heightGrid);
33
+
34
+ vec2 uv00 = vec2(fx , 1.0 - fy);
35
+ vec2 uv10 = vec2(fx1, 1.0 - fy);
36
+ vec2 uv01 = vec2(fx , 1.0 - fy1);
37
+ vec2 uv11 = vec2(fx1, 1.0 - fy1);
38
+
39
+ vec2 uv;
40
+ if (v == 0) uv = uv00;
41
+ else if (v == 1) uv = uv10;
42
+ else if (v == 2) uv = uv01;
43
+ else if (v == 3) uv = uv10;
44
+ else if (v == 4) uv = uv11;
45
+ else uv = uv01;
46
+
47
+ float depth = texture(u_depthImage, uv).r;
48
+ float z = mix(u_depthMin, u_depthMax, depth);
49
+
50
+ vec2 pixelPos = uv * u_imageSize;
51
+ vec2 pos = (pixelPos - u_imageSize * 0.5) * z / u_focal;
52
+
53
+ v_uv = uv;
54
+ gl_Position = u_projMat * u_viewMat * vec4(pos.x, pos.y, z, 1.0);
55
+ }
56
+
57
+ `,E=`#version 300 es
58
+
59
+ precision mediump float;
60
+
61
+ in vec2 v_uv;
62
+
63
+ out vec4 fragColor;
64
+
65
+ uniform sampler2D u_colorImage;
66
+ uniform sampler2D u_depthImage;
67
+
68
+ uniform vec2 u_targetRes;
69
+ uniform float u_discardCutoff;
70
+
71
+ void main()
72
+ {
73
+ float deriv = min(
74
+ length(dFdx(v_uv) * u_targetRes),
75
+ length(dFdy(v_uv) * u_targetRes)
76
+ );
77
+ if(deriv < u_discardCutoff)
78
+ discard;
79
+
80
+ fragColor = texture(u_colorImage, v_uv);
81
+ }
82
+ `;class g extends HTMLElement{constructor(){super(),this.s={GRID_SIZE:250,FOCAL_LENGTH:1200,DEPTH_MIN:.1,DEPTH_MAX:10,DISCARD_CUTOFF:0,CAM_RADIUS:1.5,CAM_MAX_THETA:Math.PI/40,CAM_MAX_PHI:Math.PI/64,CAM_FOV:Math.PI/4,CAM_SMOOTHNESS:.9,BOOMERANG_SPEED:0,BACKGROUND_COLOR:[0,0,0]},this.m=null,this.i=null,this.t=null,this.e=null,this.n=null,this.p=null,this.c={},this.r=null,this.a={x:0,y:0,hovered:!1},this.o={theta:Math.PI,phi:0,radius:this.s.CAM_RADIUS},this._=0,this.A=null,this.E=!1,this.D=null,this.C=null,this.g=null,this.v=null,this.M=null,this.T=null,this.m=this.attachShadow({mode:"open"});const t=document.createElement("div");t.style.position="relative",t.style.width="100%",t.style.height="100%",t.style.display="flex",t.style.alignItems="center",t.style.justifyContent="center",t.style.background="black",this.m.appendChild(t);const e=document.createElement("style");e.textContent=`
83
+ :host { display: inline-block; width: 300px; height: 200px; }
84
+ :host([fullbleed]) { display:block; width:100%; height:100%; }
85
+ canvas { touch-action: none; }
86
+ .cover-img, .cover-video { position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: contain; pointer-events: none; }
87
+ `,this.m.appendChild(e),this.i=document.createElement("canvas"),this.i.style.width="100%",this.i.style.height="100%",this.i.style.objectFit="contain",this.i.setAttribute("role","img"),this.i.setAttribute("aria-label","3D image"),t.appendChild(this.i),this.g=this.f.bind(this),this.v=this.w.bind(this),this.M=this.H.bind(this),this.T=this.F.bind(this)}connectedCallback(){this.I();let t;try{this.O(),t=!1}catch{t=!0}window.addEventListener("resize",this.g),window.addEventListener("mousemove",this.v),document.addEventListener("mouseleave",this.M),this.R(),t?this.b():(this.f(),this.E=!0,this._=performance.now(),this.A=requestAnimationFrame(this.T))}disconnectedCallback(){this.E=!1,cancelAnimationFrame(this.A),window.removeEventListener("resize",this.g),this.i.removeEventListener("pointermove",this.v),this.i.removeEventListener("pointerleave",this.M);try{if(this.n){const t=this.n;this.p&&t.deleteProgram(this.p);for(let e in this.c)t.deleteTexture(this.c[e])}}catch{}}setViewMatrix(t){this.D=t&&t.length===16?new Float32Array(t):null}setProjectionMatrix(t){this.C=t&&t.length===16?new Float32Array(t):null}get width(){return this.d(this.t)}get height(){return this.u(this.t)}O(){const t=this.i.getContext("webgl2",{antialias:!0,alpha:!1});if(!t)throw new Error("WebGL not supported");this.n=t;const e=this.G(t,A,E);if(!e)return;this.p=e,t.useProgram(e);const s=this.L(t),i=this.L(t);this.c.color=s,this.c.depth=i,this.h("color",this.t),this.h("depth",this.e);const h=t.getUniformLocation(e,"u_colorImage"),r=t.getUniformLocation(e,"u_depthImage");t.uniform1i(h,0),t.uniform1i(r,1),this.r={uProjection:t.getUniformLocation(e,"u_projMat"),uView:t.getUniformLocation(e,"u_viewMat"),uImageSize:t.getUniformLocation(e,"u_imageSize"),uFocal:t.getUniformLocation(e,"u_focal"),uDepthMin:t.getUniformLocation(e,"u_depthMin"),uDepthMax:t.getUniformLocation(e,"u_depthMax"),uGridSegs:t.getUniformLocation(e,"u_grid"),uTargetRes:t.getUniformLocation(e,"u_targetRes"),uDiscardCutoff:t.getUniformLocation(e,"u_discardCutoff")}}F(t){if(!this.E||!this.n)return;const e=this.n,s=t-this._;this._=t,this.P(),e.clearColor(...this.s.BACKGROUND_COLOR,1),e.clear(e.COLOR_BUFFER_BIT|e.DEPTH_BUFFER_BIT),e.enable(e.DEPTH_TEST),this.a.hovered||(this.a.x=Math.sin(t*this.s.BOOMERANG_SPEED),this.a.y=Math.sin(t*this.s.BOOMERANG_SPEED*.5+Math.PI));const i=this.a.x*this.s.CAM_MAX_THETA+Math.PI,h=-this.a.y*this.s.CAM_MAX_PHI,r=this.a.hovered?this.s.CAM_RADIUS*.8:this.s.CAM_RADIUS;this.o.theta=this.S(i,this.o.theta,s),this.o.phi=this.S(h,this.o.phi,s),this.o.radius=this.S(r,this.o.radius,s);const c=this.i.width/this.i.height,a=Math.max(1,Math.floor(this.s.GRID_SIZE)),d=Math.max(1,Math.round(a/c)),o=this.d(this.t),n=this.u(this.t);e.uniform2f(this.r.uImageSize,o,n),e.uniform1f(this.r.uFocal,this.s.FOCAL_LENGTH),e.uniform1f(this.r.uDepthMin,this.s.DEPTH_MIN),e.uniform1f(this.r.uDepthMax,this.s.DEPTH_MAX),e.uniform2i(this.r.uGridSegs,a,d),e.uniform2f(this.r.uTargetRes,this.i.width,this.i.height),e.uniform1f(this.r.uDiscardCutoff,this.s.DISCARD_CUTOFF);const u=[this.o.radius*Math.cos(this.o.phi)*Math.sin(this.o.theta),this.o.radius*Math.sin(this.o.phi),this.s.CAM_RADIUS+this.o.radius*Math.cos(this.o.phi)*Math.cos(this.o.theta)],f=[0,0,this.s.CAM_RADIUS],T=[0,-1,0],I=this.D||new Float32Array(this.N(u,f,T)),R=this.C||new Float32Array(this.B(this.s.CAM_FOV,c,.1,100));e.uniformMatrix4fv(this.r.uView,!1,I),e.uniformMatrix4fv(this.r.uProjection,!1,R),e.drawArrays(e.TRIANGLES,0,a*d*6),this.A=requestAnimationFrame(this.T)}w(t){const e=this.i.getBoundingClientRect();this.a.hovered=!0,this.a.x=(t.clientX-e.left)/e.width*2-1,this.a.y=(t.clientY-e.top)/e.height*2-1}H(){this.a.hovered=!1}f(){const t=window.devicePixelRatio||1,e=this.i.parentElement;if(!e)return;const s=e.clientWidth,i=e.clientHeight;let h=this.d(this.t)||1,r=this.u(this.t)||1;const c=h/r;let a=s,d=a/c;d>i&&(d=i,a=d*c);const o=Math.max(1,Math.floor(a*t)),n=Math.max(1,Math.floor(d*t));this.i.width=o,this.i.height=n,this.n&&this.n.viewport(0,0,o,n)}I(){const t=this.s;if(this.hasAttribute("grid-size")&&(t.GRID_SIZE=parseInt(this.getAttribute("grid-size"))??t.GRID_SIZE),this.hasAttribute("focal-length")&&(t.FOCAL_LENGTH=parseFloat(this.getAttribute("focal-length"))??t.FOCAL_LENGTH),this.hasAttribute("depth-min")&&(t.DEPTH_MIN=parseFloat(this.getAttribute("depth-min"))??t.DEPTH_MIN),this.hasAttribute("depth-max")&&(t.DEPTH_MAX=parseFloat(this.getAttribute("depth-max"))??t.DEPTH_MAX),this.hasAttribute("discard-cutoff")&&(t.DISCARD_CUTOFF=parseFloat(this.getAttribute("discard-cutoff"))??t.DISCARD_CUTOFF),this.hasAttribute("cam-radius")&&(t.CAM_RADIUS=parseFloat(this.getAttribute("cam-radius"))??t.CAM_RADIUS),this.hasAttribute("cam-max-theta")&&(t.CAM_MAX_THETA=parseFloat(this.getAttribute("cam-max-theta"))??t.CAM_MAX_THETA),this.hasAttribute("cam-max-phi")&&(t.CAM_MAX_PHI=parseFloat(this.getAttribute("cam-max-phi"))??t.CAM_MAX_PHI),this.hasAttribute("cam-fov")&&(t.CAM_FOV=parseFloat(this.getAttribute("cam-fov"))??t.CAM_FOV),this.hasAttribute("cam-smoothness")&&(t.CAM_SMOOTHNESS=parseFloat(this.getAttribute("cam-smoothness"))??t.CAM_SMOOTHNESS),this.hasAttribute("boomerang-speed")&&(t.BOOMERANG_SPEED=parseFloat(this.getAttribute("boomerang-speed"))??t.BOOMERANG_SPEED),this.hasAttribute("background-color"))try{const e=this.getAttribute("background-color").split(",").map(Number);e.length===3&&(t.BACKGROUND_COLOR=e)}catch{}}U(t,e,s){const i=t.createShader(e);return t.shaderSource(i,s),t.compileShader(i),t.getShaderParameter(i,t.COMPILE_STATUS)?i:(console.error(t.getShaderInfoLog(i)),t.deleteShader(i),null)}G(t,e,s){const i=this.U(t,t.VERTEX_SHADER,e),h=this.U(t,t.FRAGMENT_SHADER,s);if(!i||!h)return null;const r=t.createProgram();return t.attachShader(r,i),t.attachShader(r,h),t.linkProgram(r),t.getProgramParameter(r,t.LINK_STATUS)?(t.deleteShader(i),t.deleteShader(h),r):(console.error(t.getProgramInfoLog(r)),t.deleteProgram(r),null)}L(t){const e=t.createTexture();return t.bindTexture(t.TEXTURE_2D,e),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.LINEAR),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.LINEAR),e}h(t,e){if(!this.n)return;const s=this.n,i=this.c[t];if(s.activeTexture(t==="color"?s.TEXTURE0:s.TEXTURE1),s.bindTexture(s.TEXTURE_2D,i),!this.l(e)){s.texImage2D(s.TEXTURE_2D,0,s.RGBA,1,1,0,s.RGBA,s.UNSIGNED_BYTE,new Uint8Array([0,0,0,0]));return}try{s.pixelStorei(s.UNPACK_FLIP_Y_WEBGL,!1),s.texImage2D(s.TEXTURE_2D,0,s.RGBA,s.RGBA,s.UNSIGNED_BYTE,e)}catch{}}B(t,e,s,i){const h=1/Math.tan(t/2);return[h/e,0,0,0,0,h,0,0,0,0,(i+s)/(s-i),-1,0,0,2*i*s/(s-i),0]}N(t,e,s){function i(o){const n=Math.hypot(...o)||1;return o.map(u=>u/n)}function h(o,n){return[o[1]*n[2]-o[2]*n[1],o[2]*n[0]-o[0]*n[2],o[0]*n[1]-o[1]*n[0]]}function r(o,n){return o.map((u,f)=>u-n[f])}const c=i(r(t,e)),a=i(h(s,c)),d=h(c,a);return[a[0],d[0],c[0],0,a[1],d[1],c[1],0,a[2],d[2],c[2],0,-(a[0]*t[0]+a[1]*t[1]+a[2]*t[2]),-(d[0]*t[0]+d[1]*t[1]+d[2]*t[2]),-(c[0]*t[0]+c[1]*t[1]+c[2]*t[2]),1]}S(t,e,s){const i=(1-this.s.CAM_SMOOTHNESS)*s/16.67,h=Math.sign(t-e);return e+=(t-e)*i,Math.sign(t-e)!==h&&(e=t),e}R(){throw new Error("Must implement _loadSources")}b(){throw new Error("Must implement _createFallback")}P(){}l(t){throw new Error("Must implement _isSourceReady")}d(t){throw new Error("Must implement _getSourceWidth")}u(t){throw new Error("Must implement _getSourceHeight")}}l=g;class v extends l{static get observedAttributes(){return["color-src","depth-src","color-id","depth-id","grid-size","focal-length","depth-min","depth-max","discard-cutoff","cam-radius","cam-max-theta","cam-max-phi","cam-fov","cam-smoothness","boomerang-speed","background-color"]}constructor(){super(),this.t=new Image,this.e=new Image,this.t.crossOrigin="anonymous",this.e.crossOrigin="anonymous"}attributeChangedCallback(t,e,s){if(e!==s)if(t==="color-src")this.t.src=s||"";else if(t==="depth-src")this.e.src=s||"";else if(t==="color-id"){const i=document.getElementById(s);i instanceof HTMLImageElement&&(this.t=i,i.complete?this.h("color",i):i.addEventListener("load",()=>this.h("color",i)))}else if(t==="depth-id"){const i=document.getElementById(s);i instanceof HTMLImageElement&&(this.e=i,i.complete?this.h("depth",i):i.addEventListener("load",()=>this.h("depth",i)))}else this.I()}R(){const t=this.getAttribute("color-id"),e=this.getAttribute("depth-id"),s=this.getAttribute("color-src"),i=this.getAttribute("depth-src");if(t){const h=document.getElementById(t);h instanceof HTMLImageElement&&h.complete?(this.t=h,this.h("color",this.t)):h&&(h.addEventListener("load",()=>this.h("color",h)),this.t=h)}else s&&(this.t.src=s,this.t.onload=()=>this.h("color",this.t));if(e){const h=document.getElementById(e);h instanceof HTMLImageElement&&h.complete?(this.e=h,this.h("depth",this.e)):h&&(h.addEventListener("load",()=>this.h("depth",h)),this.e=h)}else i&&(this.e.src=i,this.e.onload=()=>this.h("depth",this.e))}b(){this.getAttribute("color-id")&&(this.t=this.t.cloneNode(),this.t.id+="_threedad-img"),this.t.style.display="block",this.t.classList.add("cover-img"),this.i.parentElement.appendChild(this.t)}l(t){return t&&t.complete&&t.naturalWidth>0}d(t){return t?t.width:1}u(t){return t?t.height:1}}m=v;class M extends l{static get observedAttributes(){return["color-src","depth-src","color-id","depth-id","grid-size","focal-length","depth-min","depth-max","discard-cutoff","cam-radius","cam-max-theta","cam-max-phi","cam-fov","cam-smoothness","boomerang-speed","background-color","autoplay","loop","muted"]}constructor(){super(),this.t=document.createElement("video"),this.e=document.createElement("video"),this.t.crossOrigin="anonymous",this.e.crossOrigin="anonymous",this.t.playsInline=!0,this.e.playsInline=!0,this.t.muted=!0,this.e.muted=!0}attributeChangedCallback(t,e,s){if(e!==s)if(t==="color-src")this.t.src=s||"";else if(t==="depth-src")this.e.src=s||"";else if(t==="color-id"){const i=document.getElementById(s);i instanceof HTMLVideoElement&&(this.t=i,i.readyState>=i.HAVE_CURRENT_DATA?this.h("color",i):i.addEventListener("loadeddata",()=>this.h("color",i)))}else if(t==="depth-id"){const i=document.getElementById(s);i instanceof HTMLVideoElement&&(this.e=i,i.readyState>=i.HAVE_CURRENT_DATA?this.h("depth",i):i.addEventListener("loadeddata",()=>this.h("depth",i)))}else t==="autoplay"?(this.t.autoplay=this.hasAttribute("autoplay"),this.e.autoplay=this.hasAttribute("autoplay")):t==="loop"?(this.t.loop=this.hasAttribute("loop"),this.e.loop=this.hasAttribute("loop")):t==="muted"?(this.t.muted=this.hasAttribute("muted"),this.e.muted=this.hasAttribute("muted")):this.I()}play(){return Promise.all([this.t?.play(),this.e?.play()])}pause(){this.t?.pause(),this.e?.pause()}get paused(){return this.t?this.t.paused:!0}get currentTime(){return this.t?this.t.currentTime:0}set currentTime(t){console.log(t),this.t&&(this.t.currentTime=t),this.e&&(this.e.currentTime=t)}R(){const t=this.getAttribute("color-id"),e=this.getAttribute("depth-id"),s=this.getAttribute("color-src"),i=this.getAttribute("depth-src");if(this.hasAttribute("autoplay")&&(this.t.autoplay=!0,this.e.autoplay=!0),this.hasAttribute("loop")&&(this.t.loop=!0,this.e.loop=!0),this.hasAttribute("muted")&&(this.t.muted=!0,this.e.muted=!0),t){const h=document.getElementById(t);h instanceof HTMLVideoElement&&(this.t=h)}else s&&(this.t.src=s);if(e){const h=document.getElementById(e);h instanceof HTMLVideoElement&&(this.e=h)}else i&&(this.e.src=i);this.hasAttribute("autoplay")?this.play().then(()=>{this.f()}):this.play().then(()=>{this.pause(),this.f()})}b(){this.getAttribute("color-id")&&(this.t=this.t.cloneNode(!0),this.t.id+="_threedad-video"),this.t.style.display="block",this.t.classList.add("cover-video"),this.t.controls=!0,this.i.parentElement.appendChild(this.t)}P(){this.l(this.t)&&this.h("color",this.t),this.l(this.e)&&this.h("depth",this.e),Math.abs(this.t.currentTime-this.e.currentTime)>.01&&(this.e.currentTime=this.t.currentTime,this.t.paused!==this.e.paused&&(this.t.paused?this.e.pause():this.e.play()))}l(t){return t&&t.readyState>=t.HAVE_CURRENT_DATA}d(t){return t?t.videoWidth:1}u(t){return t?t.videoHeight:1}}p=M,customElements.define("rgbd-img",m),customElements.define("rgbd-video",p)}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rgbd",
3
- "version": "0.0.9",
3
+ "version": "0.0.12",
4
4
  "type": "module",
5
5
  "main": "dist/rgbd.js",
6
6
  "module": "dist/rgbd.js",
@@ -11,7 +11,7 @@
11
11
  "dist"
12
12
  ],
13
13
  "scripts": {
14
- "build": "esbuild src/rgbd.js --minify --outfile=dist/rgbd.js --format=esm",
14
+ "build": "esbuild src/rgbd.js --minify --outfile=dist/rgbd.js --format=esm --mangle-props=^_",
15
15
  "dev": "npx serve .",
16
16
  "prepare": "npm run build"
17
17
  },