UNPKG

@react-three/drei

Version:

useful add-ons for react-three-fiber

2 lines (1 loc) 13.1 kB
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),t=require("three"),n=require("react"),r=require("@react-three/fiber"),o=require("./shaderMaterial.cjs.js"),a=require("../helpers/constants.cjs.js");function l(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function s(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(n){if("default"!==n){var r=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(t,n,r.get?r:{enumerable:!0,get:function(){return e[n]}})}})),t.default=e,Object.freeze(t)}var c=l(e),i=s(t),u=s(n);const d=o.shaderMaterial({alphaTest:0,viewport:new i.Vector2(1980,1080),focal:1e3,centerAndScaleTexture:null,covAndColorTexture:null},"\n precision highp sampler2D;\n precision highp usampler2D;\n out vec4 vColor;\n out vec3 vPosition;\n uniform vec2 resolution;\n uniform vec2 viewport;\n uniform float focal;\n attribute uint splatIndex;\n uniform sampler2D centerAndScaleTexture;\n uniform usampler2D covAndColorTexture; \n\n vec2 unpackInt16(in uint value) {\n int v = int(value);\n int v0 = v >> 16;\n int v1 = (v & 0xFFFF);\n if((v & 0x8000) != 0)\n v1 |= 0xFFFF0000;\n return vec2(float(v1), float(v0));\n }\n\n void main () {\n ivec2 texSize = textureSize(centerAndScaleTexture, 0);\n ivec2 texPos = ivec2(splatIndex%uint(texSize.x), splatIndex/uint(texSize.x));\n vec4 centerAndScaleData = texelFetch(centerAndScaleTexture, texPos, 0);\n vec4 center = vec4(centerAndScaleData.xyz, 1);\n vec4 camspace = modelViewMatrix * center;\n vec4 pos2d = projectionMatrix * camspace;\n\n float bounds = 1.2 * pos2d.w;\n if (pos2d.z < -pos2d.w || pos2d.x < -bounds || pos2d.x > bounds\n || pos2d.y < -bounds || pos2d.y > bounds) {\n gl_Position = vec4(0.0, 0.0, 2.0, 1.0);\n return;\n }\n\n uvec4 covAndColorData = texelFetch(covAndColorTexture, texPos, 0);\n vec2 cov3D_M11_M12 = unpackInt16(covAndColorData.x) * centerAndScaleData.w;\n vec2 cov3D_M13_M22 = unpackInt16(covAndColorData.y) * centerAndScaleData.w;\n vec2 cov3D_M23_M33 = unpackInt16(covAndColorData.z) * centerAndScaleData.w;\n mat3 Vrk = mat3(\n cov3D_M11_M12.x, cov3D_M11_M12.y, cov3D_M13_M22.x,\n cov3D_M11_M12.y, cov3D_M13_M22.y, cov3D_M23_M33.x,\n cov3D_M13_M22.x, cov3D_M23_M33.x, cov3D_M23_M33.y\n );\n\n mat3 J = mat3(\n focal / camspace.z, 0., -(focal * camspace.x) / (camspace.z * camspace.z),\n 0., focal / camspace.z, -(focal * camspace.y) / (camspace.z * camspace.z),\n 0., 0., 0.\n );\n\n mat3 W = transpose(mat3(modelViewMatrix));\n mat3 T = W * J;\n mat3 cov = transpose(T) * Vrk * T;\n vec2 vCenter = vec2(pos2d) / pos2d.w;\n float diagonal1 = cov[0][0] + 0.3;\n float offDiagonal = cov[0][1];\n float diagonal2 = cov[1][1] + 0.3;\n float mid = 0.5 * (diagonal1 + diagonal2);\n float radius = length(vec2((diagonal1 - diagonal2) / 2.0, offDiagonal));\n float lambda1 = mid + radius;\n float lambda2 = max(mid - radius, 0.1);\n vec2 diagonalVector = normalize(vec2(offDiagonal, lambda1 - diagonal1));\n vec2 v1 = min(sqrt(2.0 * lambda1), 1024.0) * diagonalVector;\n vec2 v2 = min(sqrt(2.0 * lambda2), 1024.0) * vec2(diagonalVector.y, -diagonalVector.x);\n uint colorUint = covAndColorData.w;\n vColor = vec4(\n float(colorUint & uint(0xFF)) / 255.0,\n float((colorUint >> uint(8)) & uint(0xFF)) / 255.0,\n float((colorUint >> uint(16)) & uint(0xFF)) / 255.0,\n float(colorUint >> uint(24)) / 255.0\n );\n vPosition = position;\n\n gl_Position = vec4(\n vCenter \n + position.x * v2 / viewport * 2.0 \n + position.y * v1 / viewport * 2.0, pos2d.z / pos2d.w, 1.0);\n }\n ",`\n #include <alphatest_pars_fragment>\n #include <alphahash_pars_fragment>\n in vec4 vColor;\n in vec3 vPosition;\n void main () {\n float A = -dot(vPosition.xy, vPosition.xy);\n if (A < -4.0) discard;\n float B = exp(A) * vColor.a;\n vec4 diffuseColor = vec4(vColor.rgb, B);\n #include <alphatest_fragment>\n #include <alphahash_fragment>\n gl_FragColor = diffuseColor;\n #include <tonemapping_fragment>\n #include <${a.version>=154?"colorspace_fragment":"encodings_fragment"}>\n }\n `);function f(e){let t=null,n=0;e.onmessage=r=>{if("push"==r.data.method){0===n&&(t=new Float32Array(r.data.length));const e=new Float32Array(r.data.matrices);t.set(e,n),n+=e.length}else if("sort"==r.data.method&&null!==t){const n=function(e,n=!1){const r=t.length/16;let o=-1/0,a=1/0;const l=new Float32Array(r),s=new Int32Array(l.buffer),c=new Int32Array(r);let i=0;for(let s=0;s<r;s++){const r=e[0]*t[16*s+12]+e[1]*t[16*s+13]+e[2]*t[16*s+14]+e[3];(n||r<0&&t[16*s+15]>-1e-4*r)&&(l[i]=r,c[i]=s,i++,r>o&&(o=r),r<a&&(a=r))}const u=65535/(o-a),d=new Uint32Array(65536);for(let e=0;e<i;e++)s[e]=(l[e]-a)*u|0,d[s[e]]++;const f=new Uint32Array(65536);for(let e=1;e<65536;e++)f[e]=f[e-1]+d[e-1];const x=new Uint32Array(i);for(let e=0;e<i;e++)x[f[s[e]]++]=c[e];return x}(new Float32Array(r.data.view),r.data.hashed);e.postMessage({indices:n,key:r.data.key},[n.buffer])}}}class x extends i.Loader{constructor(...e){super(...e),this.gl=null,this.chunkSize=25e3}load(e,t,n,r){const o={gl:this.gl,url:this.manager.resolveURL(e),worker:new Worker(URL.createObjectURL(new Blob(["(",f.toString(),")(self)"],{type:"application/javascript"}))),manager:this.manager,update:(e,t,n)=>function(e,t,n,r){if(e.updateMatrixWorld(),t.gl.getCurrentViewport(n.viewport),n.material.viewport.x=n.viewport.z,n.material.viewport.y=n.viewport.w,n.material.focal=n.viewport.w/2*Math.abs(e.projectionMatrix.elements[5]),n.ready){if(r&&n.sorted)return;n.ready=!1;const e=new Float32Array([n.modelViewMatrix.elements[2],-n.modelViewMatrix.elements[6],n.modelViewMatrix.elements[10],n.modelViewMatrix.elements[14]]);t.worker.postMessage({method:"sort",src:t.url,key:n.uuid,view:e.buffer,hashed:r},[e.buffer]),r&&t.loaded&&(n.sorted=!0)}}(t,o,e,n),connect:e=>function(e,t){e.loading||async function(e){e.loading=!0;let t=0,n=0;const r=[];let o=0;const a=0!==e.totalDownloadBytes;for(;;)try{const{value:l,done:s}=await e.stream.read();if(s)break;if(t+=l.length,null!=e.totalDownloadBytes){const n=t/e.totalDownloadBytes*100;if(e.onProgress&&n-o>1){const r=new ProgressEvent("progress",{lengthComputable:a,loaded:t,total:e.totalDownloadBytes});e.onProgress(r),o=n}}r.push(l);const c=t-n;if(null!=e.totalDownloadBytes&&c>e.rowLength*e.chunkSize){let t=Math.floor(c/e.rowLength);const o=new Uint8Array(c);let l=0;for(const e of r)o.set(e,l),l+=e.length;if(r.length=0,c>t*e.rowLength){const n=new Uint8Array(c-t*e.rowLength);n.set(o.subarray(c-n.length,c),0),r.push(n)}const s=new Uint8Array(t*e.rowLength);s.set(o.subarray(0,s.byteLength),0);const i=p(e,s.buffer,t);if(e.worker.postMessage({method:"push",src:e.url,length:16*e.numVertices,matrices:i.buffer},[i.buffer]),n+=t*e.rowLength,e.onProgress){const t=new ProgressEvent("progress",{lengthComputable:a,loaded:e.totalDownloadBytes,total:e.totalDownloadBytes});e.onProgress(t)}}}catch(e){console.error(e);break}if(t-n>0){let t=new Uint8Array(r.reduce(((e,t)=>e+t.length),0)),n=0;for(const e of r)t.set(e,n),n+=e.length;let o=Math.floor(t.byteLength/e.rowLength);const a=p(e,t.buffer,o);e.worker.postMessage({method:"push",src:e.url,length:16*o,matrices:a.buffer},[a.buffer])}e.loaded=!0,e.manager.itemEnd(e.url)}(e);t.ready=!1,t.pm=new i.Matrix4,t.vm1=new i.Matrix4,t.vm2=new i.Matrix4,t.viewport=new i.Vector4;let n=new Uint32Array(e.bufferTextureWidth*e.bufferTextureHeight);const r=new i.InstancedBufferAttribute(n,1,!1);r.setUsage(i.DynamicDrawUsage);const o=t.geometry=new i.InstancedBufferGeometry,a=new Float32Array(18),l=new i.BufferAttribute(a,3);function s(e){if(t&&e.data.key===t.uuid){let n=new Uint32Array(e.data.indices);o.attributes.splatIndex.set(n),o.attributes.splatIndex.needsUpdate=!0,o.instanceCount=n.length,t.ready=!0}}async function c(){for(;;){const t=e.gl.properties.get(e.centerAndScaleTexture),n=e.gl.properties.get(e.covAndColorTexture);if(null!=t&&t.__webglTexture&&null!=n&&n.__webglTexture&&e.loadedVertexCount>0)break;await new Promise((e=>setTimeout(e,10)))}t.ready=!0}return o.setAttribute("position",l),l.setXYZ(2,-2,2,0),l.setXYZ(1,2,2,0),l.setXYZ(0,-2,-2,0),l.setXYZ(5,-2,-2,0),l.setXYZ(4,2,2,0),l.setXYZ(3,2,-2,0),l.needsUpdate=!0,o.setAttribute("splatIndex",r),o.instanceCount=1,e.worker.addEventListener("message",s),c(),()=>e.worker.removeEventListener("message",s)}(o,e),loading:!1,loaded:!1,loadedVertexCount:0,chunkSize:this.chunkSize,totalDownloadBytes:0,numVertices:0,rowLength:32,maxVertexes:0,bufferTextureWidth:0,bufferTextureHeight:0,stream:null,centerAndScaleData:null,covAndColorData:null,covAndColorTexture:null,centerAndScaleTexture:null,onProgress:n};(async function(e){e.manager.itemStart(e.url);const t=await fetch(e.url);if(null===t.body)throw"Failed to fetch file";let n=t.headers.get("Content-Length");const r=n?parseInt(n):void 0;if(null==r)throw"Failed to get content length";e.stream=t.body.getReader(),e.totalDownloadBytes=r,e.numVertices=Math.floor(e.totalDownloadBytes/e.rowLength);const o=e.gl.getContext();let a=o.getParameter(o.MAX_TEXTURE_SIZE);e.maxVertexes=a*a,e.numVertices>e.maxVertexes&&(e.numVertices=e.maxVertexes);return e.bufferTextureWidth=a,e.bufferTextureHeight=Math.floor((e.numVertices-1)/a)+1,e.centerAndScaleData=new Float32Array(e.bufferTextureWidth*e.bufferTextureHeight*4),e.covAndColorData=new Uint32Array(e.bufferTextureWidth*e.bufferTextureHeight*4),e.centerAndScaleTexture=new i.DataTexture(e.centerAndScaleData,e.bufferTextureWidth,e.bufferTextureHeight,i.RGBAFormat,i.FloatType),e.centerAndScaleTexture.needsUpdate=!0,e.covAndColorTexture=new i.DataTexture(e.covAndColorData,e.bufferTextureWidth,e.bufferTextureHeight,i.RGBAIntegerFormat,i.UnsignedIntType),e.covAndColorTexture.internalFormat="RGBA32UI",e.covAndColorTexture.needsUpdate=!0,e})(o).then(t).catch((e=>{null==r||r(e),o.manager.itemError(o.url)}))}}function p(e,t,n){const r=e.gl.getContext();if(e.loadedVertexCount+n>e.maxVertexes&&(n=e.maxVertexes-e.loadedVertexCount),n<=0)throw"Failed to parse file";const o=new Uint8Array(t),a=new Float32Array(t),l=new Float32Array(16*n),s=new Uint8Array(e.covAndColorData.buffer),c=new Int16Array(e.covAndColorData.buffer);for(let t=0;t<n;t++){const n=new i.Quaternion(-(o[32*t+28+1]-128)/128,(o[32*t+28+2]-128)/128,(o[32*t+28+3]-128)/128,-(o[32*t+28+0]-128)/128);n.invert();const r=new i.Vector3(a[8*t+0],a[8*t+1],-a[8*t+2]),u=new i.Vector3(a[8*t+3+0],a[8*t+3+1],a[8*t+3+2]),d=new i.Matrix4;d.makeRotationFromQuaternion(n),d.transpose(),d.scale(u);const f=d.clone();d.transpose(),d.premultiply(f),d.setPosition(r);const x=[0,1,2,5,6,10];let p=0;for(let e=0;e<x.length;e++)Math.abs(d.elements[x[e]])>p&&(p=Math.abs(d.elements[x[e]]));let g=4*e.loadedVertexCount+4*t;e.centerAndScaleData[g+0]=r.x,e.centerAndScaleData[g+1]=-r.y,e.centerAndScaleData[g+2]=r.z,e.centerAndScaleData[g+3]=p/32767,g=8*e.loadedVertexCount+4*t*2;for(let e=0;e<x.length;e++)c[g+e]=32767*d.elements[x[e]]/p;g=16*e.loadedVertexCount+4*(4*t+3);const m=new i.Color(o[32*t+24+0]/255,o[32*t+24+1]/255,o[32*t+24+2]/255);m.convertSRGBToLinear(),s[g+0]=255*m.r,s[g+1]=255*m.g,s[g+2]=255*m.b,s[g+3]=o[32*t+24+3],d.elements[15]=Math.max(u.x,u.y,u.z)*o[32*t+24+3]/255;for(let e=0;e<16;e++)l[16*t+e]=d.elements[e]}for(;n>0;){let t=0,o=0;const a=e.loadedVertexCount%e.bufferTextureWidth,l=Math.floor(e.loadedVertexCount/e.bufferTextureWidth);e.loadedVertexCount%e.bufferTextureWidth!=0?(t=Math.min(e.bufferTextureWidth,a+n)-a,o=1):Math.floor(n/e.bufferTextureWidth)>0?(t=e.bufferTextureWidth,o=Math.floor(n/e.bufferTextureWidth)):(t=n%e.bufferTextureWidth,o=1);const s=e.gl.properties.get(e.centerAndScaleTexture);r.bindTexture(r.TEXTURE_2D,s.__webglTexture),r.texSubImage2D(r.TEXTURE_2D,0,a,l,t,o,r.RGBA,r.FLOAT,e.centerAndScaleData,4*e.loadedVertexCount);const c=e.gl.properties.get(e.covAndColorTexture);r.bindTexture(r.TEXTURE_2D,c.__webglTexture),r.texSubImage2D(r.TEXTURE_2D,0,a,l,t,o,r.RGBA_INTEGER,r.UNSIGNED_INT,e.covAndColorData,4*e.loadedVertexCount),e.gl.resetState(),e.loadedVertexCount+=t*o,n-=t*o}return l}exports.Splat=function({src:e,toneMapped:t=!1,alphaTest:n=0,alphaHash:o=!1,chunkSize:a=25e3,...l}){r.extend({SplatMaterial:d});const s=u.useRef(null),f=r.useThree((e=>e.gl)),p=r.useThree((e=>e.camera)),g=r.useLoader(x,e,(e=>{e.gl=f,e.chunkSize=a}));return u.useLayoutEffect((()=>g.connect(s.current)),[e]),r.useFrame((()=>g.update(s.current,p,o))),u.createElement("mesh",c.default({ref:s,frustumCulled:!1},l),u.createElement("splatMaterial",{key:`${e}/${n}/${o}${d.key}`,transparent:!o,depthTest:!0,alphaTest:o?0:n,centerAndScaleTexture:g.centerAndScaleTexture,covAndColorTexture:g.covAndColorTexture,depthWrite:!!o||n>0,blending:o?i.NormalBlending:i.CustomBlending,blendSrcAlpha:i.OneFactor,alphaHash:!!o,toneMapped:t}))};