├── .DS_Store ├── .gitignore ├── LICENSE ├── README.md ├── css └── base.css ├── dist ├── code block``` three.js min.js 3.0.js ├── index.css ├── index.html └── index.js ├── favicon.ico ├── index.html ├── index2.html ├── index3.html ├── package.json ├── src ├── .DS_Store ├── RoundedBox.js ├── demo.js ├── index.html ├── rendering.js ├── style.css ├── utils.js └── vite.config.js ├── vite.config.js └── yarn.lock /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anemolo/ThreeJs-Instancing-mouse-effect/3fd620d99659f6598e51a4da8a20e7bdbd53a54c/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .cache 3 | .parcel-cache 4 | package-lock.json -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2009 - 2022 [Codrops](https://tympanus.net/codrops) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Mouse Effect with Three.js Instancing 2 | 3 | Demo for tutorial on creating interactive mouse effects with Three.js instancing. 4 | 5 | ![Mouse effect](https://tympanus.net/codrops/wp-content/uploads/2023/12/instancing.jpg) 6 | 7 | [Article on Codrops](https://tympanus.net/codrops/?p=74529) 8 | 9 | [Demo](http://tympanus.net/Tutorials/MouseInstancing/) 10 | 11 | ## Installation 12 | 13 | 14 | 1. Development mode. For developing the project internals 15 | 16 | ``` 17 | yarn install 18 | yarn dev 19 | ``` 20 | 21 | 2. Run mode -> Local server only to run the code directly without modifications. 22 | 1. Run this demo on a [local server](https://developer.mozilla.org/en-US/docs/Learn/Common_questions/Tools_and_setup/set_up_a_local_testing_server). 23 | 2. Open index.html 24 | 25 | ### Files && comments 26 | 27 | | file | Description | 28 | | --- | --- | 29 | | demo.js | The meat of the demo | 30 | | rendering.js | All the threeJS rendering | 31 | 32 | ## Misc 33 | 34 | Follow *Daniel Velasquez*: [Twitter](https://twitter.com/Anemolito), [ThreeJS/Webgl Newsletter](https://offscreencanvas.com/), [GitHub](https://github.com/Anemolo) 35 | 36 | Follow Codrops: [Twitter](http://www.twitter.com/codrops), [Facebook](http://www.facebook.com/codrops), [GitHub](https://github.com/codrops), [Instagram](https://www.instagram.com/codropsss/) 37 | 38 | ## License 39 | [MIT](LICENSE) 40 | 41 | Made with :blue_heart: by [Codrops](http://www.codrops.com) 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /css/base.css: -------------------------------------------------------------------------------- 1 | *, 2 | *::after, 3 | *::before { 4 | box-sizing: border-box; 5 | } 6 | 7 | :root { 8 | font-size: 14px; 9 | --color-text: rgb(140, 146, 164); 10 | --color-bg: #000; 11 | --color-link: rgb(140, 146, 164); 12 | --color-link-hover: #fff; 13 | --page-padding: 1rem; 14 | } 15 | 16 | #canvas { 17 | width: 100%; 18 | height: 100%; 19 | } 20 | 21 | #canvas-wrapper { 22 | position: fixed; 23 | top: 0; 24 | left: 0; 25 | width: 100%; 26 | height: 100%; 27 | } 28 | 29 | html, body { 30 | width: 100vw; 31 | height: 100%; 32 | overflow: hidden; 33 | } 34 | 35 | body { 36 | margin: 0; 37 | color: var(--color-text); 38 | background-color: var(--color-bg); 39 | font-family: ui-monospace,SFMono-Regular,Menlo,Roboto Mono,monospace; 40 | -webkit-font-smoothing: antialiased; 41 | -moz-osx-font-smoothing: grayscale; 42 | } 43 | 44 | .demo-2 { 45 | --color-text: #000; 46 | --color-link: #000; 47 | --color-link-hover: #000; 48 | } 49 | 50 | .demo-3 { 51 | --color-text: #e5e2ec; 52 | --color-link: #cb0f40; 53 | } 54 | 55 | /* Page Loader */ 56 | .js .loading::before, 57 | .js .loading::after { 58 | content: ''; 59 | position: fixed; 60 | z-index: 1000; 61 | } 62 | 63 | .js .loading::before { 64 | top: 0; 65 | left: 0; 66 | width: 100%; 67 | height: 100%; 68 | background: var(--color-bg); 69 | } 70 | 71 | .js .loading::after { 72 | top: 50%; 73 | left: 50%; 74 | width: 60px; 75 | height: 60px; 76 | margin: -30px 0 0 -30px; 77 | opacity: 0.4; 78 | background: var(--color-link); 79 | animation: loaderAnim 0.7s linear infinite alternate forwards; 80 | 81 | } 82 | 83 | @keyframes loaderAnim { 84 | to { 85 | opacity: 1; 86 | transform: scale3d(0.7,0.7,1); 87 | } 88 | } 89 | 90 | a { 91 | text-decoration: underline; 92 | color: var(--color-link); 93 | outline: none; 94 | cursor: pointer; 95 | } 96 | 97 | a:hover { 98 | text-decoration: none; 99 | color: var(--color-link-hover); 100 | outline: none; 101 | } 102 | 103 | /* Better focus styles from https://developer.mozilla.org/en-US/docs/Web/CSS/:focus-visible */ 104 | a:focus { 105 | /* Provide a fallback style for browsers 106 | that don't support :focus-visible */ 107 | outline: none; 108 | } 109 | 110 | a:focus-visible { 111 | /* Draw a very noticeable focus style for 112 | keyboard-focus on browsers that do support 113 | :focus-visible */ 114 | outline: 2px solid red; 115 | } 116 | 117 | .unbutton { 118 | background: none; 119 | border: 0; 120 | padding: 0; 121 | margin: 0; 122 | font: inherit; 123 | cursor: pointer; 124 | } 125 | 126 | .unbutton:focus { 127 | outline: none; 128 | } 129 | 130 | .frame { 131 | padding: var(--page-padding); 132 | position: fixed; 133 | top: 0; 134 | left: 0; 135 | display: grid; 136 | z-index: 1000; 137 | width: 100%; 138 | height: 100%; 139 | grid-row-gap: 1rem; 140 | grid-column-gap: 2rem; 141 | pointer-events: none; 142 | justify-items: start; 143 | grid-template-columns: auto auto; 144 | grid-template-areas: 'title' 'prev' 'back' 'sub' 'sponsor' 'demos'; 145 | } 146 | 147 | .frame #cdawrap { 148 | justify-self: start; 149 | } 150 | 151 | .frame a { 152 | pointer-events: auto; 153 | } 154 | 155 | .frame__title { 156 | grid-area: title; 157 | font-size: inherit; 158 | margin: 0; 159 | } 160 | 161 | .frame__back { 162 | grid-area: back; 163 | justify-self: start; 164 | } 165 | 166 | .frame__prev { 167 | grid-area: prev; 168 | justify-self: start; 169 | } 170 | 171 | .frame__sub { 172 | grid-area: sub; 173 | } 174 | 175 | .frame__demos { 176 | grid-area: demos; 177 | display: flex; 178 | gap: 1rem; 179 | } 180 | 181 | @media screen and (min-width: 53em) { 182 | body { 183 | --page-padding: 2rem 3rem; 184 | } 185 | .frame { 186 | grid-template-columns: auto auto auto 1fr; 187 | grid-template-rows: auto auto; 188 | align-content: space-between; 189 | grid-template-areas: 'title prev back sponsor' 'demos demos demos sub'; 190 | } 191 | .frame #cdawrap, .frame__sub { 192 | justify-self: end; 193 | } 194 | } 195 | 196 | -------------------------------------------------------------------------------- /dist/index.css: -------------------------------------------------------------------------------- 1 | #canvas{width:100%;height:100%}#canvas-wrapper{position:fixed;top:0;left:0;width:100%;height:100%}:root{font-family:sofia-pro,-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Open Sans,Arial,sans-serif}body{margin:0;width:100%;height:100vh;overflow:hidden;color:var(--text)}body,html{font-size:16px;line-height:1.5;letter-spacing:.005em}.ui{position:fixed;bottom:50px;left:0;right:0;text-align:center}.ui-logo{font-size:1rem;margin:0;margin-bottom:1rem!important;user-select:none;text-transform:uppercase}.ui-title{font-family:thunder2,Thunder2,thunder,sofia-pro,-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Open Sans,Arial,sans-serif;font-size:4rem;font-weight:800;line-height:.8;letter-spacing:.05em;width:100%!important;max-width:80%!important;user-select:none;text-align:center;margin:0 auto!important;text-transform:uppercase} 2 | -------------------------------------------------------------------------------- /dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Offscreen Canvas DEMO 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anemolo/ThreeJs-Instancing-mouse-effect/3fd620d99659f6598e51a4da8a20e7bdbd53a54c/favicon.ico -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Mouse Effect with Instancing in Three.js | Demo 1 | Codrops 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |

Mouse Effect with Instancing in Three.js

18 | Back to the article 19 | Previous demo 20 | Subscribe 21 | 26 |
27 |
28 |
29 |
30 |
31 | 32 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /index2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Mouse Effect with Instancing in Three.js | Demo 2 | Codrops 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 |
18 |

Mouse Effect with Instancing in Three.js

19 | Back to the article 20 | Previous demo 21 | Subscribe 22 | 27 |
28 |
29 |
30 |
31 |
32 | 33 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /index3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Mouse Effect with Instancing in Three.js | Demo 3 | Codrops 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 |
18 |

Mouse Effect with Instancing in Three.js

19 | Back to the article 20 | Previous demo 21 | Subscribe 22 | 27 |
28 |
29 |
30 |
31 |
32 | 33 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "offscreen-three-template", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite ./src ", 8 | "build": "vite build ./src --target es2020 --outDir ../dist", 9 | "preview": "vite preview" 10 | }, 11 | "devDependencies": { 12 | "vite": "^4.4.5" 13 | }, 14 | "dependencies": { 15 | "glsl-easings": "^1.0.0", 16 | "gsap": "^3.12.2", 17 | "n8ao": "^1.7.0", 18 | "postprocessing": "^6.33.3", 19 | "stats-js": "^1.0.1", 20 | "three": "^0.155.0", 21 | "vite-plugin-glslify": "^2.0.2" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anemolo/ThreeJs-Instancing-mouse-effect/3fd620d99659f6598e51a4da8a20e7bdbd53a54c/src/.DS_Store -------------------------------------------------------------------------------- /src/RoundedBox.js: -------------------------------------------------------------------------------- 1 | import * as THREE from "three"; 2 | 3 | /** 4 | * @author pailhead / http://dusanbosnjak.com 5 | * @author benolayinka / github.com/benolayinka 6 | */ 7 | 8 | class RoundedBoxGeometry extends THREE.BufferGeometry{ 9 | constructor( 10 | width, 11 | height, 12 | depth, 13 | radius, 14 | radiusSegments 15 | ) { 16 | 17 | super() 18 | 19 | this.type = 'RoundedBoxGeometry'; 20 | 21 | 22 | //validate params =================================== 23 | 24 | radiusSegments = !isNaN(radiusSegments) ? Math.max(1, Math.floor(radiusSegments)) : 1; 25 | 26 | width = !isNaN(width) ? width : 1; 27 | height = !isNaN(height) ? height : 1; 28 | depth = !isNaN(depth) ? depth : 1; 29 | 30 | radius = !isNaN(radius) ? radius : .15; 31 | 32 | radius = Math.min(radius, Math.min(width, Math.min(height, Math.min(depth))) / 2); 33 | 34 | var edgeHalfWidth = width / 2 - radius; 35 | var edgeHalfHeight = height / 2 - radius; 36 | var edgeHalfDepth = depth / 2 - radius; 37 | 38 | 39 | //not sure why this is needed, for querying? ======== 40 | 41 | this.parameters = { 42 | width: width, 43 | height: height, 44 | depth: depth, 45 | radius: radius, 46 | radiusSegments: radiusSegments 47 | }; 48 | 49 | 50 | //calculate vertices count ========================== 51 | 52 | var rs1 = radiusSegments + 1; //radius segments + 1 53 | 54 | var totalVertexCount = (rs1 * radiusSegments + 1) << 3; 55 | 56 | 57 | //make buffers ====================================== 58 | 59 | var positions = new THREE.BufferAttribute(new Float32Array(totalVertexCount * 3), 3); 60 | 61 | var normals = new THREE.BufferAttribute(new Float32Array(totalVertexCount * 3), 3); 62 | 63 | 64 | //some vars ========================================= 65 | 66 | var 67 | cornerVerts = [], 68 | cornerNormals = [], 69 | normal = new THREE.Vector3(), 70 | vertex = new THREE.Vector3(), 71 | vertexPool = [], 72 | normalPool = [], 73 | indices = [] 74 | ; 75 | 76 | var 77 | lastVertex = rs1 * radiusSegments, 78 | cornerVertNumber = rs1 * radiusSegments + 1 79 | ; 80 | 81 | doVertices(); 82 | doFaces(); 83 | doCorners(); 84 | doHeightEdges(); 85 | doWidthEdges(); 86 | doDepthEdges() 87 | 88 | // calculate vert positions ========================= 89 | 90 | function doVertices() { 91 | 92 | //corner offsets 93 | var cornerLayout = [ 94 | new THREE.Vector3(1, 1, 1), 95 | new THREE.Vector3(1, 1, -1), 96 | new THREE.Vector3(-1, 1, -1), 97 | new THREE.Vector3(-1, 1, 1), 98 | new THREE.Vector3(1, -1, 1), 99 | new THREE.Vector3(1, -1, -1), 100 | new THREE.Vector3(-1, -1, -1), 101 | new THREE.Vector3(-1, -1, 1) 102 | ]; 103 | 104 | //corner holder 105 | for (var j = 0; j < 8; j++) { 106 | 107 | cornerVerts.push([]); 108 | cornerNormals.push([]); 109 | 110 | } 111 | 112 | //construct 1/8 sphere ============================== 113 | 114 | var PIhalf = Math.PI / 2; 115 | 116 | var cornerOffset = new THREE.Vector3(edgeHalfWidth, edgeHalfHeight, edgeHalfDepth); 117 | 118 | for (var y = 0; y <= radiusSegments; y++) { 119 | 120 | var v = y / radiusSegments; 121 | 122 | var va = v * PIhalf; //arrange in 90 deg 123 | 124 | var cosVa = Math.cos(va); //scale of vertical angle 125 | 126 | var sinVa = Math.sin(va); 127 | 128 | if (y == radiusSegments) { 129 | 130 | vertex.set(0, 1, 0); 131 | 132 | var vert = vertex.clone().multiplyScalar(radius).add(cornerOffset); 133 | 134 | cornerVerts[0].push(vert); 135 | 136 | vertexPool.push(vert); 137 | 138 | var norm = vertex.clone(); 139 | 140 | cornerNormals[0].push(norm); 141 | 142 | normalPool.push(norm); 143 | 144 | continue; //skip row loop 145 | 146 | } 147 | 148 | for (var x = 0; x <= radiusSegments; x++) { 149 | 150 | var u = x / radiusSegments; 151 | 152 | var ha = u * PIhalf; 153 | 154 | //make 1/8 sphere points 155 | vertex.x = cosVa * Math.cos(ha); 156 | vertex.y = sinVa; 157 | vertex.z = cosVa * Math.sin(ha); 158 | 159 | //copy sphere point, scale by radius, offset by half whd 160 | var vert = vertex.clone().multiplyScalar(radius).add(cornerOffset); 161 | 162 | cornerVerts[0].push(vert); 163 | 164 | vertexPool.push(vert); 165 | 166 | //sphere already normalized, just clone 167 | 168 | var norm = vertex.clone().normalize(); 169 | cornerNormals[0].push(norm); 170 | normalPool.push(norm); 171 | 172 | } 173 | 174 | } 175 | 176 | //distribute corner verts =========================== 177 | 178 | for (var i = 1; i < 8; i++) { 179 | 180 | for (var j = 0; j < cornerVerts[0].length; j++) { 181 | 182 | var vert = cornerVerts[0][j].clone().multiply(cornerLayout[i]); 183 | 184 | cornerVerts[i].push(vert); 185 | 186 | vertexPool.push(vert); 187 | 188 | var norm = cornerNormals[0][j].clone().multiply(cornerLayout[i]); 189 | 190 | cornerNormals[i].push(norm); 191 | 192 | normalPool.push(norm); 193 | 194 | } 195 | 196 | } 197 | 198 | } 199 | 200 | 201 | // weave corners ==================================== 202 | 203 | function doCorners() { 204 | 205 | var indexInd = 0; 206 | 207 | 208 | var flips = [ 209 | true, 210 | false, 211 | true, 212 | false, 213 | false, 214 | true, 215 | false, 216 | true 217 | ]; 218 | 219 | var lastRowOffset = rs1 * (radiusSegments - 1); 220 | 221 | for (var i = 0; i < 8; i++) { 222 | 223 | var cornerOffset = cornerVertNumber * i; 224 | 225 | for (var v = 0; v < radiusSegments - 1; v++) { 226 | 227 | var r1 = v * rs1; //row offset 228 | var r2 = (v + 1) * rs1; //next row 229 | 230 | for (var u = 0; u < radiusSegments; u++) { 231 | 232 | var u1 = u + 1; 233 | var a = cornerOffset + r1 + u; 234 | var b = cornerOffset + r1 + u1; 235 | var c = cornerOffset + r2 + u; 236 | var d = cornerOffset + r2 + u1; 237 | 238 | if (!flips[i]) { 239 | 240 | indices.push(a); 241 | indices.push(b); 242 | indices.push(c); 243 | 244 | indices.push(b); 245 | indices.push(d); 246 | indices.push(c); 247 | 248 | } else { 249 | 250 | indices.push(a); 251 | indices.push(c); 252 | indices.push(b); 253 | 254 | indices.push(b); 255 | indices.push(c); 256 | indices.push(d); 257 | 258 | } 259 | 260 | } 261 | 262 | } 263 | 264 | for (var u = 0; u < radiusSegments; u++) { 265 | 266 | var a = cornerOffset + lastRowOffset + u; 267 | var b = cornerOffset + lastRowOffset + u + 1; 268 | var c = cornerOffset + lastVertex; 269 | 270 | if (!flips[i]) { 271 | 272 | indices.push(a); 273 | indices.push(b); 274 | indices.push(c); 275 | 276 | } else { 277 | 278 | indices.push(a); 279 | indices.push(c); 280 | indices.push(b); 281 | 282 | } 283 | 284 | } 285 | 286 | } 287 | 288 | } 289 | 290 | 291 | //plates ============================================ 292 | //fix this loop matrices find pattern something 293 | 294 | function doFaces() { 295 | 296 | //top 297 | var a = lastVertex;// + cornerVertNumber * 0; 298 | var b = lastVertex + cornerVertNumber;// * 1; 299 | var c = lastVertex + cornerVertNumber * 2; 300 | var d = lastVertex + cornerVertNumber * 3; 301 | 302 | indices.push(a); 303 | indices.push(b); 304 | indices.push(c); 305 | indices.push(a); 306 | indices.push(c); 307 | indices.push(d); 308 | 309 | //bottom 310 | a = lastVertex + cornerVertNumber * 4;// + cornerVertNumber * 0; 311 | b = lastVertex + cornerVertNumber * 5;// * 1; 312 | c = lastVertex + cornerVertNumber * 6; 313 | d = lastVertex + cornerVertNumber * 7; 314 | 315 | indices.push(a); 316 | indices.push(c); 317 | indices.push(b); 318 | indices.push(a); 319 | indices.push(d); 320 | indices.push(c); 321 | 322 | //left 323 | a = 0; 324 | b = cornerVertNumber; 325 | c = cornerVertNumber * 4; 326 | d = cornerVertNumber * 5; 327 | 328 | indices.push(a); 329 | indices.push(c); 330 | indices.push(b); 331 | indices.push(b); 332 | indices.push(c); 333 | indices.push(d); 334 | 335 | //right 336 | a = cornerVertNumber * 2; 337 | b = cornerVertNumber * 3; 338 | c = cornerVertNumber * 6; 339 | d = cornerVertNumber * 7; 340 | 341 | indices.push(a); 342 | indices.push(c); 343 | indices.push(b); 344 | indices.push(b); 345 | indices.push(c); 346 | indices.push(d); 347 | 348 | //front 349 | a = radiusSegments; 350 | b = radiusSegments + cornerVertNumber * 3; 351 | c = radiusSegments + cornerVertNumber * 4; 352 | d = radiusSegments + cornerVertNumber * 7; 353 | 354 | indices.push(a); 355 | indices.push(b); 356 | indices.push(c); 357 | indices.push(b); 358 | indices.push(d); 359 | indices.push(c); 360 | 361 | //back 362 | a = radiusSegments + cornerVertNumber; 363 | b = radiusSegments + cornerVertNumber * 2; 364 | c = radiusSegments + cornerVertNumber * 5; 365 | d = radiusSegments + cornerVertNumber * 6; 366 | 367 | indices.push(a); 368 | indices.push(c); 369 | indices.push(b); 370 | indices.push(b); 371 | indices.push(c); 372 | indices.push(d); 373 | 374 | } 375 | 376 | 377 | // weave edges ====================================== 378 | 379 | function doHeightEdges() { 380 | 381 | for (var i = 0; i < 4; i++) { 382 | 383 | var cOffset = i * cornerVertNumber; 384 | var cRowOffset = 4 * cornerVertNumber + cOffset; 385 | var needsFlip = i & 1 === 1; 386 | for (var u = 0; u < radiusSegments; u++) { 387 | 388 | var u1 = u + 1; 389 | var a = cOffset + u; 390 | var b = cOffset + u1; 391 | var c = cRowOffset + u; 392 | var d = cRowOffset + u1; 393 | 394 | if (!needsFlip) { 395 | 396 | indices.push(a); 397 | indices.push(b); 398 | indices.push(c); 399 | indices.push(b); 400 | indices.push(d); 401 | indices.push(c); 402 | 403 | } else { 404 | 405 | indices.push(a); 406 | indices.push(c); 407 | indices.push(b); 408 | indices.push(b); 409 | indices.push(c); 410 | indices.push(d); 411 | 412 | } 413 | 414 | } 415 | 416 | } 417 | 418 | } 419 | 420 | function doDepthEdges() { 421 | 422 | var cStarts = [0, 2, 4, 6]; 423 | var cEnds = [1, 3, 5, 7]; 424 | 425 | for (var i = 0; i < 4; i++) { 426 | 427 | var cStart = cornerVertNumber * cStarts[i]; 428 | var cEnd = cornerVertNumber * cEnds[i]; 429 | 430 | var needsFlip = 1 >= i; 431 | 432 | for (var u = 0; u < radiusSegments; u++) { 433 | 434 | var urs1 = u * rs1; 435 | var u1rs1 = (u + 1) * rs1; 436 | 437 | var a = cStart + urs1; 438 | var b = cStart + u1rs1; 439 | var c = cEnd + urs1; 440 | var d = cEnd + u1rs1 441 | 442 | if (needsFlip) { 443 | 444 | indices.push(a); 445 | indices.push(c); 446 | indices.push(b); 447 | indices.push(b); 448 | indices.push(c); 449 | indices.push(d); 450 | 451 | } else { 452 | 453 | indices.push(a); 454 | indices.push(b); 455 | indices.push(c); 456 | indices.push(b); 457 | indices.push(d); 458 | indices.push(c); 459 | 460 | } 461 | 462 | } 463 | 464 | } 465 | 466 | } 467 | 468 | function doWidthEdges() { 469 | 470 | var end = radiusSegments - 1; 471 | 472 | var cStarts = [0, 1, 4, 5]; 473 | var cEnds = [3, 2, 7, 6]; 474 | var needsFlip = [0, 1, 1, 0]; 475 | 476 | for (var i = 0; i < 4; i++) { 477 | 478 | var cStart = cStarts[i] * cornerVertNumber; 479 | var cEnd = cEnds[i] * cornerVertNumber; 480 | 481 | 482 | for (var u = 0; u <= end; u++) { 483 | 484 | // var dInd = u != end ? radiusSegments + u * rs1 : cornerVertNumber - 1; 485 | 486 | var a = cStart + radiusSegments + u * rs1; 487 | var b = cStart + (u != end ? radiusSegments + (u + 1) * rs1 : cornerVertNumber - 1); 488 | 489 | var c = cEnd + radiusSegments + u * rs1; 490 | var d = cEnd + (u != end ? radiusSegments + (u + 1) * rs1 : cornerVertNumber - 1); 491 | 492 | if (!needsFlip[i]) { 493 | 494 | indices.push(a); 495 | indices.push(b); 496 | indices.push(c); 497 | indices.push(b); 498 | indices.push(d); 499 | indices.push(c); 500 | 501 | } 502 | else { 503 | 504 | indices.push(a); 505 | indices.push(c); 506 | indices.push(b); 507 | indices.push(b); 508 | indices.push(c); 509 | indices.push(d); 510 | 511 | } 512 | 513 | } 514 | 515 | } 516 | 517 | } 518 | 519 | 520 | //fill buffers ====================================== 521 | 522 | var index = 0; 523 | 524 | for (var i = 0; i < vertexPool.length; i++) { 525 | 526 | positions.setXYZ( 527 | index, 528 | vertexPool[i].x, 529 | vertexPool[i].y, 530 | vertexPool[i].z 531 | ); 532 | 533 | normals.setXYZ( 534 | index, 535 | normalPool[i].x, 536 | normalPool[i].y, 537 | normalPool[i].z 538 | ); 539 | 540 | index++; 541 | 542 | } 543 | 544 | this.setIndex(new THREE.BufferAttribute(new Uint16Array(indices), 1)); 545 | 546 | this.setAttribute('position', positions); 547 | 548 | this.setAttribute('normal', normals); 549 | 550 | }; 551 | } 552 | 553 | 554 | export default RoundedBoxGeometry 555 | -------------------------------------------------------------------------------- /src/demo.js: -------------------------------------------------------------------------------- 1 | import "./style.css" 2 | import { gsap } from "gsap" 3 | 4 | import { Rendering } from "./rendering" 5 | 6 | import * as THREE from "three"; 7 | import RoundedBox from './RoundedBox' 8 | 9 | class InstancedMouseEffect { 10 | constructor(opts = {}, follower = null ){ 11 | 12 | 13 | if(opts.speed == null) { 14 | opts.speed = 1 15 | } 16 | if(opts.frequency == null) { 17 | opts.frequency = 1 18 | } 19 | if(opts.mouseSize == null) { 20 | opts.mouseSize = 1 21 | } 22 | if(opts.rotationSpeed == null) { 23 | opts.rotationSpeed = 1 24 | } 25 | if(opts.rotationAmmount == null) { 26 | opts.rotationAmmount = 0 27 | } 28 | if(opts.mouseScaling == null) { 29 | opts.mouseScaling = 0 30 | } 31 | if(opts.mouseIndent == null) { 32 | opts.mouseIndent = 1 33 | } 34 | if(opts.color == null) { 35 | opts.color = "#1084ff" 36 | } 37 | if(opts.colorDegrade == null) { 38 | opts.colorDegrade = 1. 39 | } 40 | if(opts.shape == null) { 41 | opts.shape = "square" 42 | } 43 | // Renderer up 44 | let rendering = new Rendering(document.querySelector("#canvas"), false) 45 | rendering.renderer.shadowMap.enabled = true; 46 | rendering.renderer.shadowMap.type = THREE.PCFSoftShadowMap; 47 | rendering.camera.position.z = 40 48 | rendering.camera.position.y = 40 49 | rendering.camera.position.x = 40 50 | rendering.camera.lookAt(new THREE.Vector3(0,0,0)) 51 | this.rendering = rendering; 52 | 53 | 54 | // follower = new THREE.Mesh( 55 | // new THREE.BoxGeometry(), 56 | // new THREE.MeshPhysicalMaterial({ 57 | // emissive: 0x000000, 58 | // color: "#ff4080", 59 | // color: "#2040bb", 60 | // roughness: 0, 61 | // metalness: 0.4 62 | // }) 63 | // ) 64 | // rendering.scene.add(follower) 65 | 66 | // let controls = new OrbitControls(rendering.camera, rendering.canvas) 67 | 68 | let uTime = { value: 0 }; 69 | 70 | // Light Setup 71 | rendering.scene.add(new THREE.HemisphereLight(0x9f9f9f, 0xffffff, 1)) 72 | rendering.scene.add(new THREE.AmbientLight(0xffffff, 1)) 73 | let d2 = new THREE.DirectionalLight(0x909090, 1) 74 | rendering.scene.add(d2) 75 | d2.position.set( -1, 0.5, 1) 76 | d2.position.multiplyScalar(10) 77 | 78 | let d1 = new THREE.DirectionalLight(0xffffff, 4) 79 | rendering.scene.add(d1) 80 | d1.position.set( 1, 0.5, 1) 81 | d1.position.multiplyScalar(10) 82 | 83 | d1.castShadow = true 84 | d1.shadow.camera.left = -10 85 | d1.shadow.camera.right = 10 86 | d1.shadow.camera.top = 10 87 | d1.shadow.camera.bottom = -10 88 | d1.shadow.camera.far = 40 89 | 90 | d1.shadow.mapSize.width = 2048 91 | d1.shadow.mapSize.height = 2048 92 | 93 | // DEMO CODE 94 | 95 | let grid = 55; 96 | let size = .5; 97 | let gridSize = grid * size 98 | 99 | let geometry = new THREE.BoxGeometry(size, size, size); 100 | geometry = new RoundedBox(size, size, size, 0.1, 4); 101 | if(typeof(opts.shape) == "string"){ 102 | switch(opts.shape){ 103 | case "cylinder": 104 | geometry = new THREE.CylinderGeometry(size, size, size); 105 | break 106 | case "torus": 107 | geometry = new THREE.TorusGeometry(size * 0.5, size * 0.3) 108 | break 109 | case "icosahedron": 110 | geometry = new THREE.IcosahedronGeometry(size, 0) 111 | break 112 | } 113 | } else { 114 | geometry = opts.shape; 115 | } 116 | 117 | 118 | let material = new THREE.MeshPhysicalMaterial({ color: opts.color, metalness: 0., roughness: 0.0 }) 119 | let mesh = new THREE.InstancedMesh(geometry, material, grid * grid); 120 | 121 | mesh.castShadow = true 122 | mesh.receiveShadow = true 123 | 124 | 125 | const totalColor = material.color.r + material.color.g + material.color.b; 126 | const color = new THREE.Vector3() 127 | const weights = new THREE.Vector3() 128 | weights.x = material.color.r 129 | weights.y = material.color.g 130 | weights.z = material.color.b 131 | weights.divideScalar(totalColor) 132 | weights.multiplyScalar(-0.5) 133 | weights.addScalar(1.) 134 | 135 | let dummy = new THREE.Object3D() 136 | 137 | let i =0; 138 | for(let x = 0; x < grid; x++) 139 | for(let y = 0; y < grid; y++){ 140 | 141 | 142 | dummy.position.set( 143 | x * size - gridSize /2 + size / 2., 144 | 0, 145 | y * size - gridSize/2 + size / 2., 146 | ); 147 | 148 | dummy.updateMatrix() 149 | mesh.setMatrixAt(i, dummy.matrix) 150 | 151 | let center = 1.- dummy.position.length() * 0.12 * opts.colorDegrade 152 | color.set( center * weights.x + (1.-weights.x) , center * weights.y + (1.-weights.y) , center * weights.z + (1.-weights.z)) 153 | mesh.setColorAt(i,color) 154 | 155 | i++; 156 | } 157 | let vertexHead = glsl` 158 | 159 | uniform float uTime; 160 | uniform float uAnimate; 161 | uniform vec2 uPos0; 162 | uniform vec2 uPos1; 163 | uniform vec4 uConfig; 164 | uniform vec4 uConfig2; 165 | 166 | float map(float value, float min1, float max1, float min2, float max2) { 167 | return min2 + (value - min1) * (max2 - min2) / (max1 - min1); 168 | } 169 | mat4 rotationMatrix(vec3 axis, float angle) { 170 | axis = normalize(axis); 171 | float s = sin(angle); 172 | float c = cos(angle); 173 | float oc = 1.0 - c; 174 | 175 | return mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0, 176 | oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0, 177 | oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0, 178 | 0.0, 0.0, 0.0, 1.0); 179 | } 180 | 181 | vec3 rotate(vec3 v, vec3 axis, float angle) { 182 | mat4 m = rotationMatrix(axis, angle); 183 | return (m * vec4(v, 1.0)).xyz; 184 | } 185 | float sdSegment( in vec2 p, in vec2 a, in vec2 b ) 186 | { 187 | vec2 pa = p-a, ba = b-a; 188 | float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 ); 189 | return length( pa - ba*h ); 190 | } 191 | #pragma glslify: ease = require(glsl-easings/cubic-in-out) 192 | #pragma glslify: ease = require(glsl-easings/cubic-out) 193 | void main(){ 194 | ` 195 | let projectVertex = glsl` 196 | 197 | vec4 position = instanceMatrix[3]; 198 | float toCenter = length(position.xz) ; 199 | 200 | 201 | // float mouseTrail = length(position.xz- uPos0.xy); 202 | float mouseTrail = sdSegment(position.xz, uPos0, uPos1 ); 203 | mouseTrail = smoothstep(2.0, 5. * uConfig.z , mouseTrail) ; 204 | 205 | // Mouse Scale 206 | transformed *= 1. + cubicOut(1.0-mouseTrail) * uConfig2.y; 207 | 208 | 209 | // Instance Animation 210 | float start = 0. + toCenter * 0.02; 211 | float end = start+ (toCenter + 1.5) * 0.06; 212 | float anim = (map(clamp(uAnimate, start,end) , start, end, 0., 1.)); 213 | 214 | 215 | transformed = rotate(transformed, vec3(0., 1., 1. ),uConfig2.x * (anim * 3.14+ uTime * uConfig.x + toCenter * 0.4 * uConfig.w) ); 216 | 217 | // Mouse Offset 218 | transformed.y += (-1.0 * (1.-mouseTrail)) * uConfig2.z; 219 | 220 | transformed.xyz *= cubicInOut(anim); 221 | transformed.y += cubicInOut(1.-anim) * 1.; 222 | 223 | transformed.y += sin(uTime * 2. * uConfig.x + toCenter * uConfig.y) * 0.1; 224 | 225 | vec4 mvPosition = vec4( transformed, 1.0 ); 226 | 227 | #ifdef USE_INSTANCING 228 | 229 | mvPosition = instanceMatrix * mvPosition; 230 | 231 | #endif 232 | 233 | mvPosition = modelViewMatrix * mvPosition; 234 | 235 | gl_Position = projectionMatrix * mvPosition; 236 | ` 237 | let uniforms = { 238 | uTime: uTime, 239 | uPos0: {value: new THREE.Vector2()}, 240 | uPos1: {value: new THREE.Vector2()}, 241 | uAnimate: {value: 0}, 242 | uConfig: { value: new THREE.Vector4(opts.speed, opts.frequency, opts.mouseSize, opts.rotationSpeed)}, 243 | uConfig2: { value: new THREE.Vector4(opts.rotationAmmount, opts.mouseScaling, opts.mouseIndent)} 244 | } 245 | mesh.material.onBeforeCompile = (shader)=>{ 246 | shader.vertexShader = shader.vertexShader.replace("void main() {", vertexHead) 247 | shader.vertexShader = shader.vertexShader.replace("#include ", projectVertex) 248 | shader.uniforms = { 249 | ...shader.uniforms, 250 | ...uniforms, 251 | } 252 | } 253 | 254 | 255 | mesh.customDepthMaterial = new THREE.MeshDepthMaterial() 256 | mesh.customDepthMaterial.onBeforeCompile = (shader)=>{ 257 | shader.vertexShader = shader.vertexShader.replace("void main() {", vertexHead) 258 | shader.vertexShader = shader.vertexShader.replace("#include ", projectVertex) 259 | shader.uniforms = { 260 | ...shader.uniforms, 261 | ...uniforms, 262 | } 263 | } 264 | mesh.customDepthMaterial.depthPacking = THREE.RGBADepthPacking 265 | rendering.scene.add(mesh) 266 | 267 | 268 | let t1= gsap.timeline() 269 | t1.to(uniforms.uAnimate, { 270 | value: 1, 271 | duration: 3.0, 272 | ease: "none" 273 | }, 0.0) 274 | if(follower){ 275 | 276 | t1.from(follower.scale, 277 | {x: 0, y: 0, z: 0, duration: 1, ease: "back.out"}, 278 | 1, 279 | ) 280 | } 281 | this.animation = t1; 282 | 283 | // Events 284 | const hitplane = new THREE.Mesh( 285 | new THREE.PlaneGeometry(), 286 | new THREE.MeshBasicMaterial() 287 | ) 288 | hitplane.scale.setScalar(20) 289 | hitplane.rotation.x = -Math.PI/2 290 | hitplane.updateMatrix() 291 | hitplane.updateMatrixWorld() 292 | let raycaster = new THREE.Raycaster() 293 | 294 | let mouse = new THREE.Vector2() 295 | let v2 = new THREE.Vector2() 296 | window.addEventListener('mousemove', (ev)=>{ 297 | let x = ev.clientX / window.innerWidth - 0.5 298 | let y = ev.clientY / window.innerHeight - 0.5 299 | 300 | v2.x = x *2; 301 | v2.y = -y *2; 302 | raycaster.setFromCamera(v2,rendering.camera) 303 | 304 | let intersects = raycaster.intersectObject(hitplane) 305 | 306 | if(intersects.length > 0){ 307 | let first = intersects[0] 308 | mouse.x = first.point.x 309 | mouse.y = first.point.z 310 | // mouse.copy(first.point) 311 | } 312 | 313 | }) 314 | 315 | let vel = new THREE.Vector2() 316 | const tick = (t, delta)=>{ 317 | uTime.value = t 318 | 319 | let v3 = new THREE.Vector2() 320 | v3.copy(mouse) 321 | v3.sub(uniforms.uPos0.value) 322 | v3.multiplyScalar(0.08) 323 | uniforms.uPos0.value.add(v3) 324 | 325 | // Calculate the change/velocity 326 | v3.copy(uniforms.uPos0.value) 327 | v3.sub(uniforms.uPos1.value) 328 | v3.multiplyScalar(0.05) 329 | 330 | // Lerp the change as well 331 | v3.sub(vel) 332 | v3.multiplyScalar(0.05) 333 | vel.add(v3) 334 | 335 | // Add the lerped velocity 336 | uniforms.uPos1.value.add(vel) 337 | 338 | if(follower ){ 339 | follower.position.x = uniforms.uPos0.value.x 340 | follower.position.z = uniforms.uPos0.value.y 341 | follower.rotation.x = t 342 | follower.rotation.y = t 343 | } 344 | 345 | rendering.render() 346 | 347 | } 348 | 349 | gsap.ticker.add(tick) 350 | 351 | } 352 | } 353 | 354 | if(process.env.NODE_ENV === "development"){ 355 | new InstancedMouseEffect() 356 | } 357 | 358 | export default InstancedMouseEffect 359 | 360 | window.InstancedMouseEffect = InstancedMouseEffect 361 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Offscreen Canvas DEMO 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/rendering.js: -------------------------------------------------------------------------------- 1 | 2 | import { BloomEffect, EffectComposer, EffectPass, NormalPass, OverrideMaterialManager, RenderPass, SSAOEffect, ToneMappingEffect } from "postprocessing"; 3 | import * as THREE from "three"; 4 | import Stats from 'stats-js' 5 | 6 | let stats = new Stats() 7 | // document.body.append(stats.dom) 8 | 9 | import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js" 10 | import { N8AOPostPass } from "n8ao"; 11 | 12 | export class Rendering { 13 | constructor(canvas, usePostProcess = false) { 14 | this.canvas = canvas; 15 | // let hex = "#"+ palette.highlight.getHexString() 16 | // document.documentElement.style.setProperty("--text", hex); 17 | 18 | 19 | 20 | this.vp = { 21 | canvas: { 22 | width: canvas.offsetWidth, 23 | height: canvas.offsetHeight, 24 | dpr: Math.min(window.devicePixelRatio, 1.5) 25 | }, 26 | scene: { 27 | width: 1, 28 | height: 1 29 | }, 30 | screen: { 31 | width: window.innerWidth, 32 | height: window.innerHeight, 33 | }, 34 | } 35 | this.renderer = new THREE.WebGLRenderer({ 36 | antialias: false, 37 | canvas, 38 | stencil: false, 39 | }); 40 | 41 | this.renderer.setSize(this.vp.canvas.width, this.vp.canvas.height, false); 42 | this.renderer.setPixelRatio(this.vp.canvas.dpr); 43 | 44 | let size = 4 45 | let ratio = this.vp.canvas.width / this.vp.canvas.height; 46 | let ratioW = this.vp.canvas.height / this.vp.canvas.width; 47 | 48 | if(ratio > ratioW){ 49 | ratioW = 1; 50 | } else { 51 | ratio = 1; 52 | } 53 | 54 | this.camera = new THREE.OrthographicCamera(-size * ratio, size * ratio,size * ratioW ,-size * ratioW , 0.001, 1000) 55 | 56 | 57 | this.scene = new THREE.Scene(); 58 | 59 | // this.scene.background = palette.BG.clone() 60 | 61 | this.clock = new THREE.Clock(); 62 | 63 | // this.vp.scene = this.getViewSizeAtDepth(); 64 | 65 | this.disposed = false; 66 | // this.renderer.outputColorSpace = THREE.LinearSRGBColorSpace 67 | OverrideMaterialManager.workaroundEnabled = true; 68 | if(usePostProcess){ 69 | const composer = new EffectComposer(this.renderer); 70 | composer.addPass(new RenderPass(this.scene, this.camera)); 71 | 72 | // const normalPass = new NormalPass(this.scene, this.camera, {resolutionScale: 0.75}); 73 | // normalPass.renderPass.overrideMaterialManager.render = function (renderer, scene, camera) { 74 | // 75 | // 76 | // // Ignore shadows. 77 | // const shadowMapEnabled = renderer.shadowMap.enabled; 78 | // renderer.shadowMap.enabled = false; 79 | // 80 | // if(OverrideMaterialManager.workaroundEnabled) { 81 | // 82 | // 83 | // const originalMaterials = this.originalMaterials; 84 | // 85 | // this.meshCount = 0; 86 | // scene.traverse((node) => { 87 | // this.replaceMaterial(node) 88 | // if(!node.isMesh) return; 89 | // if(node.customNormalMaterial){ 90 | // node.material = node.customNormalMaterial; 91 | // } 92 | // }); 93 | // renderer.render(scene, camera); 94 | // 95 | // for(const entry of originalMaterials) { 96 | // 97 | // entry[0].material = entry[1]; 98 | // 99 | // } 100 | // 101 | // if(this.meshCount !== originalMaterials.size) { 102 | // 103 | // originalMaterials.clear(); 104 | // 105 | // } 106 | // 107 | // } else { 108 | // 109 | // const overrideMaterial = scene.overrideMaterial; 110 | // scene.overrideMaterial = this.material; 111 | // renderer.render(scene, camera); 112 | // scene.overrideMaterial = overrideMaterial; 113 | // 114 | // } 115 | // 116 | // renderer.shadowMap.enabled = shadowMapEnabled; 117 | // 118 | // } 119 | 120 | // composer.addPass(normalPass) 121 | // composer.addPass(new EffectPass(this.camera, new SSAOEffect(this.camera, normalPass.texture, {resolutionScale: 0.75, intensity: 2, color: new THREE.Color(0x000000), radius: 0.020, samples: 10, rings: 4 }))); 122 | // 123 | const n8aopass = new N8AOPostPass( 124 | this.scene, 125 | this.camera, 126 | this.vp.canvas.width , 127 | this.vp.canvas.height 128 | ); 129 | n8aopass.configuration.aoRadius = 0.2; 130 | n8aopass.configuration.distanceFalloff = 0.5; 131 | n8aopass.configuration.intensity = 20.0; 132 | n8aopass.configuration.color = new THREE.Color(0, 0, 0); 133 | n8aopass.configuration.aoSamples = 8; 134 | n8aopass.configuration.denoiseSamples = 4; 135 | n8aopass.configuration.denoiseRadius = 12; 136 | n8aopass.configuration.halfRes = true; 137 | n8aopass.setQualityMode("Medium") 138 | 139 | n8aopass.configuration.halfRes = true; 140 | 141 | 142 | n8aopass.screenSpaceRadius = true 143 | composer.addPass(n8aopass) 144 | // n8aopass.setDisplayMode("Split"); 145 | // composer.addPass(new EffectPass(this.camera, new ToneMappingEffect({ mode: THREE.ACESFilmicToneMapping }))); 146 | 147 | 148 | this.composer = composer 149 | } 150 | this.usePostProcess = usePostProcess; 151 | 152 | 153 | this.addEvents(); 154 | } 155 | addEvents() { 156 | window.addEventListener("resize", this.onResize); 157 | } 158 | dispose() {} 159 | getViewSizeAtDepth(depth = 0) { 160 | const fovInRadians = (this.camera.fov * Math.PI) / 180; 161 | const height = Math.abs( 162 | (this.camera.position.z - depth) * Math.tan(fovInRadians / 2) * 2 163 | ); 164 | return { width: height * this.camera.aspect, height }; 165 | } 166 | init() { } 167 | render() { 168 | stats.begin() 169 | if(this.usePostProcess){ 170 | this.composer.render() 171 | } else { 172 | this.renderer.render(this.scene, this.camera); 173 | } 174 | stats.end() 175 | } 176 | onResize = () => { 177 | let canvas = this.canvas 178 | this.vp.canvas.width = canvas.offsetWidth; 179 | this.vp.canvas.height = canvas.offsetHeight; 180 | this.vp.canvas.dpr = Math.min(window.devicePixelRatio, 2); 181 | 182 | this.vp.scene.width = window.innerWidth; 183 | this.vp.scene.height = window.innerHeight; 184 | 185 | this.renderer.setSize(this.vp.canvas.width, this.vp.canvas.height, false); 186 | 187 | let size = 4 188 | let ratio = this.vp.canvas.width / this.vp.canvas.height; 189 | let ratioW = this.vp.canvas.height / this.vp.canvas.width; 190 | 191 | if(ratio > ratioW){ 192 | ratioW = 1; 193 | } else { 194 | ratio = 1; 195 | } 196 | 197 | this.camera.left = -size * ratio 198 | this.camera.right = size * ratio 199 | this.camera.top = size * ratioW 200 | this.camera.bottom = -size * ratioW 201 | 202 | // this.camera.aspect = this.vp.canvas.width / this.vp.canvas.height; 203 | this.camera.updateProjectionMatrix(); 204 | 205 | this.vp.scene = this.getViewSizeAtDepth(); 206 | } 207 | } 208 | 209 | // let a = new Demo(GL.canvas); 210 | // a.init(); 211 | -------------------------------------------------------------------------------- /src/style.css: -------------------------------------------------------------------------------- 1 | 2 | /* DEMO SPECIFIC CSS*/ 3 | 4 | 5 | /* Canvas required*/ 6 | #canvas { 7 | width: 100%; 8 | height: 100%; 9 | } 10 | 11 | #canvas-wrapper { 12 | position: fixed; 13 | top: 0; 14 | left: 0; 15 | width: 100%; 16 | height: 100%; 17 | } 18 | 19 | /* UI STUFF*/ 20 | 21 | :root { 22 | font-family: sofia-pro, -apple-system, BlinkMacSystemFont, "Segoe UI", 23 | Helvetica, "Open Sans", Arial, sans-serif; 24 | 25 | } 26 | 27 | body { 28 | margin: 0; 29 | width: 100%; 30 | height: 100vh; 31 | overflow: hidden; 32 | color: var(--text); 33 | } 34 | 35 | body, 36 | html { 37 | font-size: 16px; 38 | line-height: 1.5; 39 | letter-spacing: 0.005em; 40 | } 41 | .ui { 42 | position: fixed; 43 | bottom: 50px; 44 | left: 0; 45 | right: 0; 46 | text-align: center; 47 | } 48 | .ui-logo { 49 | font-size: 1rem; 50 | margin: 0; 51 | margin-bottom: 1rem !important; 52 | user-select: none; 53 | text-transform: uppercase; 54 | } 55 | .ui-title { 56 | font-family: thunder2, "Thunder2", thunder, sofia-pro, -apple-system, BlinkMacSystemFont, "Segoe UI", 57 | Helvetica, "Open Sans", Arial, sans-serif; 58 | font-size: 4rem; 59 | font-weight: 800; 60 | line-height: 0.8; 61 | letter-spacing: .05em; 62 | 63 | margin-bottom: 0 !important; 64 | width: 100% !important; 65 | max-width: 80% !important; 66 | 67 | user-select: none; 68 | text-align: center; 69 | margin: 0 auto !important; 70 | 71 | text-transform: uppercase; 72 | } 73 | -------------------------------------------------------------------------------- /src/utils.js: -------------------------------------------------------------------------------- 1 | export function getMousePos(e){ 2 | const x = e.changedTouches ? e.changedTouches[0].clientX : e.clientX; 3 | const y = e.changedTouches ? e.changedTouches[0].clientY : e.clientY; 4 | const target = e.target; 5 | 6 | return { 7 | x, 8 | y, 9 | target, 10 | }; 11 | } 12 | 13 | export const sinPaletteHead = ` 14 | uniform vec3 c0; 15 | uniform vec3 c1; 16 | uniform vec3 c2; 17 | uniform vec3 c3; 18 | 19 | vec3 palette( in float t, in vec3 a, in vec3 b, in vec3 c, in vec3 d ){ 20 | return a + b*cos( 6.28318*(c*t+d) ); 21 | } 22 | ` 23 | 24 | 25 | // Demo Utils 26 | 27 | export function getPaletteFromParams(defaultPalette = "black"){ 28 | let search = new URLSearchParams(window.location.search) 29 | return search.get("palette") == null ? defaultPalette : search.get("palette") 30 | } 31 | 32 | let palettes = [ 33 | "black", 34 | "pink", 35 | "aquamarine", 36 | "blue", 37 | "darkblue", 38 | "grey", 39 | "white", 40 | "orange" 41 | ] 42 | 43 | export function setupControls(palette){ 44 | window.addEventListener("keydown",(ev)=>{ 45 | 46 | let currentI = palettes.indexOf(palette); 47 | 48 | switch(ev.key){ 49 | case "ArrowLeft": 50 | let prevPalette = (currentI - 1) < 0 ? palettes.length-1: currentI - 1; 51 | window.location.search = "?palette="+palettes[prevPalette] 52 | // window.location.reload() 53 | break; 54 | case "ArrowRight": 55 | let nextPalette = (currentI + 1) % palettes.length 56 | window.location.search = "?palette="+palettes[nextPalette] 57 | break; 58 | } 59 | }) 60 | } 61 | -------------------------------------------------------------------------------- /src/vite.config.js: -------------------------------------------------------------------------------- 1 | // vite.config.js 2 | import { defineConfig } from 'vite'; 3 | 4 | import {glslify} from 'vite-plugin-glslify' 5 | 6 | export default defineConfig({ 7 | plugins: [glslify()], 8 | build: { 9 | rollupOptions: { 10 | output: { 11 | entryFileNames: `[name].js`, 12 | chunkFileNames: `[name].js`, 13 | assetFileNames: `[name].[ext]` 14 | } 15 | } 16 | } 17 | }); 18 | -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | // vite.config.js 2 | import { defineConfig } from 'vite'; 3 | 4 | import {glslify} from 'vite-plugin-glslify' 5 | 6 | export default defineConfig({ 7 | plugins: [glslify()] 8 | }); 9 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@choojs/findup@^0.2.0": 6 | version "0.2.1" 7 | resolved "https://registry.yarnpkg.com/@choojs/findup/-/findup-0.2.1.tgz#ac13c59ae7be6e1da64de0779a0a7f03d75615a3" 8 | integrity sha512-YstAqNb0MCN8PjdLCDfRsBcGVRN41f3vgLvaI0IrIcBp4AqILRSS0DeWNGkicC+f/zRIPJLc+9RURVSepwvfBw== 9 | dependencies: 10 | commander "^2.15.1" 11 | 12 | "@esbuild/android-arm64@0.18.20": 13 | version "0.18.20" 14 | resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz#984b4f9c8d0377443cc2dfcef266d02244593622" 15 | integrity sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ== 16 | 17 | "@esbuild/android-arm@0.18.20": 18 | version "0.18.20" 19 | resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.18.20.tgz#fedb265bc3a589c84cc11f810804f234947c3682" 20 | integrity sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw== 21 | 22 | "@esbuild/android-x64@0.18.20": 23 | version "0.18.20" 24 | resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.18.20.tgz#35cf419c4cfc8babe8893d296cd990e9e9f756f2" 25 | integrity sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg== 26 | 27 | "@esbuild/darwin-arm64@0.18.20": 28 | version "0.18.20" 29 | resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz#08172cbeccf95fbc383399a7f39cfbddaeb0d7c1" 30 | integrity sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA== 31 | 32 | "@esbuild/darwin-x64@0.18.20": 33 | version "0.18.20" 34 | resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz#d70d5790d8bf475556b67d0f8b7c5bdff053d85d" 35 | integrity sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ== 36 | 37 | "@esbuild/freebsd-arm64@0.18.20": 38 | version "0.18.20" 39 | resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz#98755cd12707f93f210e2494d6a4b51b96977f54" 40 | integrity sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw== 41 | 42 | "@esbuild/freebsd-x64@0.18.20": 43 | version "0.18.20" 44 | resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz#c1eb2bff03915f87c29cece4c1a7fa1f423b066e" 45 | integrity sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ== 46 | 47 | "@esbuild/linux-arm64@0.18.20": 48 | version "0.18.20" 49 | resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz#bad4238bd8f4fc25b5a021280c770ab5fc3a02a0" 50 | integrity sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA== 51 | 52 | "@esbuild/linux-arm@0.18.20": 53 | version "0.18.20" 54 | resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz#3e617c61f33508a27150ee417543c8ab5acc73b0" 55 | integrity sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg== 56 | 57 | "@esbuild/linux-ia32@0.18.20": 58 | version "0.18.20" 59 | resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz#699391cccba9aee6019b7f9892eb99219f1570a7" 60 | integrity sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA== 61 | 62 | "@esbuild/linux-loong64@0.18.20": 63 | version "0.18.20" 64 | resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz#e6fccb7aac178dd2ffb9860465ac89d7f23b977d" 65 | integrity sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg== 66 | 67 | "@esbuild/linux-mips64el@0.18.20": 68 | version "0.18.20" 69 | resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz#eeff3a937de9c2310de30622a957ad1bd9183231" 70 | integrity sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ== 71 | 72 | "@esbuild/linux-ppc64@0.18.20": 73 | version "0.18.20" 74 | resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz#2f7156bde20b01527993e6881435ad79ba9599fb" 75 | integrity sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA== 76 | 77 | "@esbuild/linux-riscv64@0.18.20": 78 | version "0.18.20" 79 | resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz#6628389f210123d8b4743045af8caa7d4ddfc7a6" 80 | integrity sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A== 81 | 82 | "@esbuild/linux-s390x@0.18.20": 83 | version "0.18.20" 84 | resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz#255e81fb289b101026131858ab99fba63dcf0071" 85 | integrity sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ== 86 | 87 | "@esbuild/linux-x64@0.18.20": 88 | version "0.18.20" 89 | resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz#c7690b3417af318a9b6f96df3031a8865176d338" 90 | integrity sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w== 91 | 92 | "@esbuild/netbsd-x64@0.18.20": 93 | version "0.18.20" 94 | resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz#30e8cd8a3dded63975e2df2438ca109601ebe0d1" 95 | integrity sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A== 96 | 97 | "@esbuild/openbsd-x64@0.18.20": 98 | version "0.18.20" 99 | resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz#7812af31b205055874c8082ea9cf9ab0da6217ae" 100 | integrity sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg== 101 | 102 | "@esbuild/sunos-x64@0.18.20": 103 | version "0.18.20" 104 | resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz#d5c275c3b4e73c9b0ecd38d1ca62c020f887ab9d" 105 | integrity sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ== 106 | 107 | "@esbuild/win32-arm64@0.18.20": 108 | version "0.18.20" 109 | resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz#73bc7f5a9f8a77805f357fab97f290d0e4820ac9" 110 | integrity sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg== 111 | 112 | "@esbuild/win32-ia32@0.18.20": 113 | version "0.18.20" 114 | resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz#ec93cbf0ef1085cc12e71e0d661d20569ff42102" 115 | integrity sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g== 116 | 117 | "@esbuild/win32-x64@0.18.20": 118 | version "0.18.20" 119 | resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz#786c5f41f043b07afb1af37683d7c33668858f6d" 120 | integrity sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ== 121 | 122 | "@rollup/pluginutils@^4.1.1": 123 | version "4.2.1" 124 | resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-4.2.1.tgz#e6c6c3aba0744edce3fb2074922d3776c0af2a6d" 125 | integrity sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ== 126 | dependencies: 127 | estree-walker "^2.0.1" 128 | picomatch "^2.2.2" 129 | 130 | acorn@^7.1.1: 131 | version "7.4.1" 132 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" 133 | integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== 134 | 135 | astring@^1.7.5: 136 | version "1.8.6" 137 | resolved "https://registry.yarnpkg.com/astring/-/astring-1.8.6.tgz#2c9c157cf1739d67561c56ba896e6948f6b93731" 138 | integrity sha512-ISvCdHdlTDlH5IpxQJIex7BWBywFWgjJSVdwst+/iQCoEYnyOaQ95+X1JGshuBjGp6nxKUy1jMgE3zPqN7fQdg== 139 | 140 | bl@^2.2.1: 141 | version "2.2.1" 142 | resolved "https://registry.yarnpkg.com/bl/-/bl-2.2.1.tgz#8c11a7b730655c5d56898cdc871224f40fd901d5" 143 | integrity sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g== 144 | dependencies: 145 | readable-stream "^2.3.5" 146 | safe-buffer "^5.1.1" 147 | 148 | buffer-from@^1.0.0: 149 | version "1.1.2" 150 | resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" 151 | integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== 152 | 153 | commander@^2.15.1: 154 | version "2.20.3" 155 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" 156 | integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== 157 | 158 | concat-stream@^1.5.2: 159 | version "1.6.2" 160 | resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" 161 | integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== 162 | dependencies: 163 | buffer-from "^1.0.0" 164 | inherits "^2.0.3" 165 | readable-stream "^2.2.2" 166 | typedarray "^0.0.6" 167 | 168 | core-util-is@~1.0.0: 169 | version "1.0.3" 170 | resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" 171 | integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== 172 | 173 | deep-is@~0.1.3: 174 | version "0.1.4" 175 | resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" 176 | integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== 177 | 178 | duplexify@^3.4.5: 179 | version "3.7.1" 180 | resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" 181 | integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g== 182 | dependencies: 183 | end-of-stream "^1.0.0" 184 | inherits "^2.0.1" 185 | readable-stream "^2.0.0" 186 | stream-shift "^1.0.0" 187 | 188 | end-of-stream@^1.0.0: 189 | version "1.4.4" 190 | resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" 191 | integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== 192 | dependencies: 193 | once "^1.4.0" 194 | 195 | esbuild@^0.18.10: 196 | version "0.18.20" 197 | resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.18.20.tgz#4709f5a34801b43b799ab7d6d82f7284a9b7a7a6" 198 | integrity sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA== 199 | optionalDependencies: 200 | "@esbuild/android-arm" "0.18.20" 201 | "@esbuild/android-arm64" "0.18.20" 202 | "@esbuild/android-x64" "0.18.20" 203 | "@esbuild/darwin-arm64" "0.18.20" 204 | "@esbuild/darwin-x64" "0.18.20" 205 | "@esbuild/freebsd-arm64" "0.18.20" 206 | "@esbuild/freebsd-x64" "0.18.20" 207 | "@esbuild/linux-arm" "0.18.20" 208 | "@esbuild/linux-arm64" "0.18.20" 209 | "@esbuild/linux-ia32" "0.18.20" 210 | "@esbuild/linux-loong64" "0.18.20" 211 | "@esbuild/linux-mips64el" "0.18.20" 212 | "@esbuild/linux-ppc64" "0.18.20" 213 | "@esbuild/linux-riscv64" "0.18.20" 214 | "@esbuild/linux-s390x" "0.18.20" 215 | "@esbuild/linux-x64" "0.18.20" 216 | "@esbuild/netbsd-x64" "0.18.20" 217 | "@esbuild/openbsd-x64" "0.18.20" 218 | "@esbuild/sunos-x64" "0.18.20" 219 | "@esbuild/win32-arm64" "0.18.20" 220 | "@esbuild/win32-ia32" "0.18.20" 221 | "@esbuild/win32-x64" "0.18.20" 222 | 223 | escodegen@^1.11.1: 224 | version "1.14.3" 225 | resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503" 226 | integrity sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw== 227 | dependencies: 228 | esprima "^4.0.1" 229 | estraverse "^4.2.0" 230 | esutils "^2.0.2" 231 | optionator "^0.8.1" 232 | optionalDependencies: 233 | source-map "~0.6.1" 234 | 235 | esprima@^4.0.1: 236 | version "4.0.1" 237 | resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" 238 | integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== 239 | 240 | estraverse@^4.2.0: 241 | version "4.3.0" 242 | resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" 243 | integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== 244 | 245 | estree-walker@^2.0.1: 246 | version "2.0.2" 247 | resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" 248 | integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== 249 | 250 | esutils@^2.0.2: 251 | version "2.0.3" 252 | resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" 253 | integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== 254 | 255 | events@^3.2.0: 256 | version "3.3.0" 257 | resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" 258 | integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== 259 | 260 | falafel@^2.1.0: 261 | version "2.2.5" 262 | resolved "https://registry.yarnpkg.com/falafel/-/falafel-2.2.5.tgz#3ccb4970a09b094e9e54fead2deee64b4a589d56" 263 | integrity sha512-HuC1qF9iTnHDnML9YZAdCDQwT0yKl/U55K4XSUXqGAA2GLoafFgWRqdAbhWJxXaYD4pyoVxAJ8wH670jMpI9DQ== 264 | dependencies: 265 | acorn "^7.1.1" 266 | isarray "^2.0.1" 267 | 268 | fast-levenshtein@~2.0.6: 269 | version "2.0.6" 270 | resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" 271 | integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== 272 | 273 | from2@^2.3.0: 274 | version "2.3.0" 275 | resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" 276 | integrity sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g== 277 | dependencies: 278 | inherits "^2.0.1" 279 | readable-stream "^2.0.0" 280 | 281 | fsevents@~2.3.2: 282 | version "2.3.3" 283 | resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" 284 | integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== 285 | 286 | function-bind@^1.1.2: 287 | version "1.1.2" 288 | resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" 289 | integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== 290 | 291 | glsl-easings@^1.0.0: 292 | version "1.0.0" 293 | resolved "https://registry.yarnpkg.com/glsl-easings/-/glsl-easings-1.0.0.tgz#d4f7b499915e922921f4f03d0f8089724bdf5b8e" 294 | integrity sha512-blfWMqztNRVI4sJNyPlA9uV4T7xIm//Ie6fGGtnQPs3FpCj5YOWt/QIVFRMWpsBQhehRRGoaKG2yDw6tkAlmeA== 295 | 296 | glsl-inject-defines@^1.0.1: 297 | version "1.0.3" 298 | resolved "https://registry.yarnpkg.com/glsl-inject-defines/-/glsl-inject-defines-1.0.3.tgz#dd1aacc2c17fcb2bd3fc32411c6633d0d7b60fd4" 299 | integrity sha512-W49jIhuDtF6w+7wCMcClk27a2hq8znvHtlGnrYkSWEr8tHe9eA2dcnohlcAmxLYBSpSSdzOkRdyPTrx9fw49+A== 300 | dependencies: 301 | glsl-token-inject-block "^1.0.0" 302 | glsl-token-string "^1.0.1" 303 | glsl-tokenizer "^2.0.2" 304 | 305 | glsl-resolve@0.0.1: 306 | version "0.0.1" 307 | resolved "https://registry.yarnpkg.com/glsl-resolve/-/glsl-resolve-0.0.1.tgz#894bef73910d792c81b5143180035d0a78af76d3" 308 | integrity sha512-xxFNsfnhZTK9NBhzJjSBGX6IOqYpvBHxxmo+4vapiljyGNCY0Bekzn0firQkQrazK59c1hYxMDxYS8MDlhw4gA== 309 | dependencies: 310 | resolve "^0.6.1" 311 | xtend "^2.1.2" 312 | 313 | glsl-token-assignments@^2.0.0: 314 | version "2.0.2" 315 | resolved "https://registry.yarnpkg.com/glsl-token-assignments/-/glsl-token-assignments-2.0.2.tgz#a5d82ab78499c2e8a6b83cb69495e6e665ce019f" 316 | integrity sha512-OwXrxixCyHzzA0U2g4btSNAyB2Dx8XrztY5aVUCjRSh4/D0WoJn8Qdps7Xub3sz6zE73W3szLrmWtQ7QMpeHEQ== 317 | 318 | glsl-token-defines@^1.0.0: 319 | version "1.0.0" 320 | resolved "https://registry.yarnpkg.com/glsl-token-defines/-/glsl-token-defines-1.0.0.tgz#cb892aa959936231728470d4f74032489697fa9d" 321 | integrity sha512-Vb5QMVeLjmOwvvOJuPNg3vnRlffscq2/qvIuTpMzuO/7s5kT+63iL6Dfo2FYLWbzuiycWpbC0/KV0biqFwHxaQ== 322 | dependencies: 323 | glsl-tokenizer "^2.0.0" 324 | 325 | glsl-token-depth@^1.1.0, glsl-token-depth@^1.1.1: 326 | version "1.1.2" 327 | resolved "https://registry.yarnpkg.com/glsl-token-depth/-/glsl-token-depth-1.1.2.tgz#23c5e30ee2bd255884b4a28bc850b8f791e95d84" 328 | integrity sha512-eQnIBLc7vFf8axF9aoi/xW37LSWd2hCQr/3sZui8aBJnksq9C7zMeUYHVJWMhFzXrBU7fgIqni4EhXVW4/krpg== 329 | 330 | glsl-token-descope@^1.0.2: 331 | version "1.0.2" 332 | resolved "https://registry.yarnpkg.com/glsl-token-descope/-/glsl-token-descope-1.0.2.tgz#0fc90ab326186b82f597b2e77dc9e21efcd32076" 333 | integrity sha512-kS2PTWkvi/YOeicVjXGgX5j7+8N7e56srNDEHDTVZ1dcESmbmpmgrnpjPcjxJjMxh56mSXYoFdZqb90gXkGjQw== 334 | dependencies: 335 | glsl-token-assignments "^2.0.0" 336 | glsl-token-depth "^1.1.0" 337 | glsl-token-properties "^1.0.0" 338 | glsl-token-scope "^1.1.0" 339 | 340 | glsl-token-inject-block@^1.0.0: 341 | version "1.1.0" 342 | resolved "https://registry.yarnpkg.com/glsl-token-inject-block/-/glsl-token-inject-block-1.1.0.tgz#e1015f5980c1091824adaa2625f1dfde8bd00034" 343 | integrity sha512-q/m+ukdUBuHCOtLhSr0uFb/qYQr4/oKrPSdIK2C4TD+qLaJvqM9wfXIF/OOBjuSA3pUoYHurVRNao6LTVVUPWA== 344 | 345 | glsl-token-properties@^1.0.0: 346 | version "1.0.1" 347 | resolved "https://registry.yarnpkg.com/glsl-token-properties/-/glsl-token-properties-1.0.1.tgz#483dc3d839f0d4b5c6171d1591f249be53c28a9e" 348 | integrity sha512-dSeW1cOIzbuUoYH0y+nxzwK9S9O3wsjttkq5ij9ZGw0OS41BirKJzzH48VLm8qLg+au6b0sINxGC0IrGwtQUcA== 349 | 350 | glsl-token-scope@^1.1.0, glsl-token-scope@^1.1.1: 351 | version "1.1.2" 352 | resolved "https://registry.yarnpkg.com/glsl-token-scope/-/glsl-token-scope-1.1.2.tgz#a1728e78df24444f9cb93fd18ef0f75503a643b1" 353 | integrity sha512-YKyOMk1B/tz9BwYUdfDoHvMIYTGtVv2vbDSLh94PT4+f87z21FVdou1KNKgF+nECBTo0fJ20dpm0B1vZB1Q03A== 354 | 355 | glsl-token-string@^1.0.1: 356 | version "1.0.1" 357 | resolved "https://registry.yarnpkg.com/glsl-token-string/-/glsl-token-string-1.0.1.tgz#59441d2f857de7c3449c945666021ece358e48ec" 358 | integrity sha512-1mtQ47Uxd47wrovl+T6RshKGkRRCYWhnELmkEcUAPALWGTFe2XZpH3r45XAwL2B6v+l0KNsCnoaZCSnhzKEksg== 359 | 360 | glsl-token-whitespace-trim@^1.0.0: 361 | version "1.0.0" 362 | resolved "https://registry.yarnpkg.com/glsl-token-whitespace-trim/-/glsl-token-whitespace-trim-1.0.0.tgz#46d1dfe98c75bd7d504c05d7d11b1b3e9cc93b10" 363 | integrity sha512-ZJtsPut/aDaUdLUNtmBYhaCmhIjpKNg7IgZSfX5wFReMc2vnj8zok+gB/3Quqs0TsBSX/fGnqUUYZDqyuc2xLQ== 364 | 365 | glsl-tokenizer@^2.0.0, glsl-tokenizer@^2.0.2: 366 | version "2.1.5" 367 | resolved "https://registry.yarnpkg.com/glsl-tokenizer/-/glsl-tokenizer-2.1.5.tgz#1c2e78c16589933c274ba278d0a63b370c5fee1a" 368 | integrity sha512-XSZEJ/i4dmz3Pmbnpsy3cKh7cotvFlBiZnDOwnj/05EwNp2XrhQ4XKJxT7/pDt4kp4YcpRSKz8eTV7S+mwV6MA== 369 | dependencies: 370 | through2 "^0.6.3" 371 | 372 | glslify-bundle@^5.0.0: 373 | version "5.1.1" 374 | resolved "https://registry.yarnpkg.com/glslify-bundle/-/glslify-bundle-5.1.1.tgz#30d2ddf2e6b935bf44d1299321e3b729782c409a" 375 | integrity sha512-plaAOQPv62M1r3OsWf2UbjN0hUYAB7Aph5bfH58VxJZJhloRNbxOL9tl/7H71K7OLJoSJ2ZqWOKk3ttQ6wy24A== 376 | dependencies: 377 | glsl-inject-defines "^1.0.1" 378 | glsl-token-defines "^1.0.0" 379 | glsl-token-depth "^1.1.1" 380 | glsl-token-descope "^1.0.2" 381 | glsl-token-scope "^1.1.1" 382 | glsl-token-string "^1.0.1" 383 | glsl-token-whitespace-trim "^1.0.0" 384 | glsl-tokenizer "^2.0.2" 385 | murmurhash-js "^1.0.0" 386 | shallow-copy "0.0.1" 387 | 388 | glslify-deps@^1.2.5: 389 | version "1.3.2" 390 | resolved "https://registry.yarnpkg.com/glslify-deps/-/glslify-deps-1.3.2.tgz#c09ee945352bfc07ac2d8a1cc9e3de776328c72b" 391 | integrity sha512-7S7IkHWygJRjcawveXQjRXLO2FTjijPDYC7QfZyAQanY+yGLCFHYnPtsGT9bdyHiwPTw/5a1m1M9hamT2aBpag== 392 | dependencies: 393 | "@choojs/findup" "^0.2.0" 394 | events "^3.2.0" 395 | glsl-resolve "0.0.1" 396 | glsl-tokenizer "^2.0.0" 397 | graceful-fs "^4.1.2" 398 | inherits "^2.0.1" 399 | map-limit "0.0.1" 400 | resolve "^1.0.0" 401 | 402 | glslify@^7.1.1: 403 | version "7.1.1" 404 | resolved "https://registry.yarnpkg.com/glslify/-/glslify-7.1.1.tgz#454d9172b410cb49864029c86d5613947fefd30b" 405 | integrity sha512-bud98CJ6kGZcP9Yxcsi7Iz647wuDz3oN+IZsjCRi5X1PI7t/xPKeL0mOwXJjo+CRZMqvq0CkSJiywCcY7kVYog== 406 | dependencies: 407 | bl "^2.2.1" 408 | concat-stream "^1.5.2" 409 | duplexify "^3.4.5" 410 | falafel "^2.1.0" 411 | from2 "^2.3.0" 412 | glsl-resolve "0.0.1" 413 | glsl-token-whitespace-trim "^1.0.0" 414 | glslify-bundle "^5.0.0" 415 | glslify-deps "^1.2.5" 416 | minimist "^1.2.5" 417 | resolve "^1.1.5" 418 | stack-trace "0.0.9" 419 | static-eval "^2.0.5" 420 | through2 "^2.0.1" 421 | xtend "^4.0.0" 422 | 423 | graceful-fs@^4.1.2: 424 | version "4.2.11" 425 | resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" 426 | integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== 427 | 428 | gsap@^3.12.2: 429 | version "3.12.2" 430 | resolved "https://registry.yarnpkg.com/gsap/-/gsap-3.12.2.tgz#6e88203eed360761cbf2a2cb3a8d702aa87f3f6d" 431 | integrity sha512-EkYnpG8qHgYBFAwsgsGEqvT1WUidX0tt/ijepx7z8EUJHElykg91RvW1XbkT59T0gZzzszOpjQv7SE41XuIXyQ== 432 | 433 | hasown@^2.0.0: 434 | version "2.0.0" 435 | resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c" 436 | integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA== 437 | dependencies: 438 | function-bind "^1.1.2" 439 | 440 | inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3: 441 | version "2.0.4" 442 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 443 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 444 | 445 | is-core-module@^2.13.0: 446 | version "2.13.1" 447 | resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" 448 | integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== 449 | dependencies: 450 | hasown "^2.0.0" 451 | 452 | isarray@0.0.1: 453 | version "0.0.1" 454 | resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" 455 | integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== 456 | 457 | isarray@^2.0.1: 458 | version "2.0.5" 459 | resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" 460 | integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== 461 | 462 | isarray@~1.0.0: 463 | version "1.0.0" 464 | resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" 465 | integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== 466 | 467 | levn@~0.3.0: 468 | version "0.3.0" 469 | resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" 470 | integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== 471 | dependencies: 472 | prelude-ls "~1.1.2" 473 | type-check "~0.3.2" 474 | 475 | magic-string@^0.25.7: 476 | version "0.25.9" 477 | resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c" 478 | integrity sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ== 479 | dependencies: 480 | sourcemap-codec "^1.4.8" 481 | 482 | map-limit@0.0.1: 483 | version "0.0.1" 484 | resolved "https://registry.yarnpkg.com/map-limit/-/map-limit-0.0.1.tgz#eb7961031c0f0e8d001bf2d56fab685d58822f38" 485 | integrity sha512-pJpcfLPnIF/Sk3taPW21G/RQsEEirGaFpCW3oXRwH9dnFHPHNGjNyvh++rdmC2fNqEaTw2MhYJraoJWAHx8kEg== 486 | dependencies: 487 | once "~1.3.0" 488 | 489 | minimist@^1.2.5: 490 | version "1.2.8" 491 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" 492 | integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== 493 | 494 | murmurhash-js@^1.0.0: 495 | version "1.0.0" 496 | resolved "https://registry.yarnpkg.com/murmurhash-js/-/murmurhash-js-1.0.0.tgz#b06278e21fc6c37fa5313732b0412bcb6ae15f51" 497 | integrity sha512-TvmkNhkv8yct0SVBSy+o8wYzXjE4Zz3PCesbfs8HiCXXdcTuocApFv11UWlNFWKYsP2okqrhb7JNlSm9InBhIw== 498 | 499 | n8ao@^1.7.0: 500 | version "1.7.0" 501 | resolved "https://registry.yarnpkg.com/n8ao/-/n8ao-1.7.0.tgz#43b42d66f3bb2333522d7fb8d8c6750ea5e8a32b" 502 | integrity sha512-0Ne+dnzlKByj4UR+OfPU04CanmbNPPtYcqJqWWcPw00CiMOLhkE23/gwoROLACKMRLuWsqhW2cMf5pYlywrIAQ== 503 | 504 | nanoid@^3.3.6: 505 | version "3.3.7" 506 | resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" 507 | integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== 508 | 509 | once@^1.4.0: 510 | version "1.4.0" 511 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 512 | integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== 513 | dependencies: 514 | wrappy "1" 515 | 516 | once@~1.3.0: 517 | version "1.3.3" 518 | resolved "https://registry.yarnpkg.com/once/-/once-1.3.3.tgz#b2e261557ce4c314ec8304f3fa82663e4297ca20" 519 | integrity sha512-6vaNInhu+CHxtONf3zw3vq4SP2DOQhjBvIa3rNcG0+P7eKWlYH6Peu7rHizSloRU2EwMz6GraLieis9Ac9+p1w== 520 | dependencies: 521 | wrappy "1" 522 | 523 | optionator@^0.8.1: 524 | version "0.8.3" 525 | resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" 526 | integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== 527 | dependencies: 528 | deep-is "~0.1.3" 529 | fast-levenshtein "~2.0.6" 530 | levn "~0.3.0" 531 | prelude-ls "~1.1.2" 532 | type-check "~0.3.2" 533 | word-wrap "~1.2.3" 534 | 535 | path-parse@^1.0.7: 536 | version "1.0.7" 537 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" 538 | integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== 539 | 540 | picocolors@^1.0.0: 541 | version "1.0.0" 542 | resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" 543 | integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== 544 | 545 | picomatch@^2.2.2: 546 | version "2.3.1" 547 | resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" 548 | integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== 549 | 550 | postcss@^8.4.27: 551 | version "8.4.31" 552 | resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d" 553 | integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ== 554 | dependencies: 555 | nanoid "^3.3.6" 556 | picocolors "^1.0.0" 557 | source-map-js "^1.0.2" 558 | 559 | postprocessing@^6.33.3: 560 | version "6.33.3" 561 | resolved "https://registry.yarnpkg.com/postprocessing/-/postprocessing-6.33.3.tgz#d80103f6e68581263557aa2e5d9e26af3e0d7cfd" 562 | integrity sha512-zQAVvcMf7bfeggQNQeVErD/UFd1XHBi2X6+yxwIv9PjhGCLAYKue3UuzVyu95O7ZUvkDwF0TyTzKdxoaVwYi7w== 563 | 564 | prelude-ls@~1.1.2: 565 | version "1.1.2" 566 | resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" 567 | integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== 568 | 569 | process-nextick-args@~2.0.0: 570 | version "2.0.1" 571 | resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" 572 | integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== 573 | 574 | "readable-stream@>=1.0.33-1 <1.1.0-0": 575 | version "1.0.34" 576 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" 577 | integrity sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg== 578 | dependencies: 579 | core-util-is "~1.0.0" 580 | inherits "~2.0.1" 581 | isarray "0.0.1" 582 | string_decoder "~0.10.x" 583 | 584 | readable-stream@^2.0.0, readable-stream@^2.2.2, readable-stream@^2.3.5, readable-stream@~2.3.6: 585 | version "2.3.8" 586 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" 587 | integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== 588 | dependencies: 589 | core-util-is "~1.0.0" 590 | inherits "~2.0.3" 591 | isarray "~1.0.0" 592 | process-nextick-args "~2.0.0" 593 | safe-buffer "~5.1.1" 594 | string_decoder "~1.1.1" 595 | util-deprecate "~1.0.1" 596 | 597 | resolve@^0.6.1: 598 | version "0.6.3" 599 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-0.6.3.tgz#dd957982e7e736debdf53b58a4dd91754575dd46" 600 | integrity sha512-UHBY3viPlJKf85YijDUcikKX6tmF4SokIDp518ZDVT92JNDcG5uKIthaT/owt3Sar0lwtOafsQuwrg22/v2Dwg== 601 | 602 | resolve@^1.0.0, resolve@^1.1.5: 603 | version "1.22.8" 604 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" 605 | integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== 606 | dependencies: 607 | is-core-module "^2.13.0" 608 | path-parse "^1.0.7" 609 | supports-preserve-symlinks-flag "^1.0.0" 610 | 611 | rollup@^3.27.1: 612 | version "3.29.4" 613 | resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.29.4.tgz#4d70c0f9834146df8705bfb69a9a19c9e1109981" 614 | integrity sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw== 615 | optionalDependencies: 616 | fsevents "~2.3.2" 617 | 618 | safe-buffer@^5.1.1: 619 | version "5.2.1" 620 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" 621 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== 622 | 623 | safe-buffer@~5.1.0, safe-buffer@~5.1.1: 624 | version "5.1.2" 625 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" 626 | integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== 627 | 628 | shallow-copy@0.0.1: 629 | version "0.0.1" 630 | resolved "https://registry.yarnpkg.com/shallow-copy/-/shallow-copy-0.0.1.tgz#415f42702d73d810330292cc5ee86eae1a11a170" 631 | integrity sha512-b6i4ZpVuUxB9h5gfCxPiusKYkqTMOjEbBs4wMaFbkfia4yFv92UKZ6Df8WXcKbn08JNL/abvg3FnMAOfakDvUw== 632 | 633 | source-map-js@^1.0.2: 634 | version "1.0.2" 635 | resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" 636 | integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== 637 | 638 | source-map@~0.6.1: 639 | version "0.6.1" 640 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" 641 | integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== 642 | 643 | sourcemap-codec@^1.4.8: 644 | version "1.4.8" 645 | resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" 646 | integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== 647 | 648 | stack-trace@0.0.9: 649 | version "0.0.9" 650 | resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.9.tgz#a8f6eaeca90674c333e7c43953f275b451510695" 651 | integrity sha512-vjUc6sfgtgY0dxCdnc40mK6Oftjo9+2K8H/NG81TMhgL392FtiPA9tn9RLyTxXmTLPJPjF3VyzFp6bsWFLisMQ== 652 | 653 | static-eval@^2.0.5: 654 | version "2.1.0" 655 | resolved "https://registry.yarnpkg.com/static-eval/-/static-eval-2.1.0.tgz#a16dbe54522d7fa5ef1389129d813fd47b148014" 656 | integrity sha512-agtxZ/kWSsCkI5E4QifRwsaPs0P0JmZV6dkLz6ILYfFYQGn+5plctanRN+IC8dJRiFkyXHrwEE3W9Wmx67uDbw== 657 | dependencies: 658 | escodegen "^1.11.1" 659 | 660 | stats-js@^1.0.1: 661 | version "1.0.1" 662 | resolved "https://registry.yarnpkg.com/stats-js/-/stats-js-1.0.1.tgz#377c36490c1935b9a4e68bf3acc3afeb59878f66" 663 | integrity sha512-EAwEFghGNv8mlYC4CZzI5kWghsnP8uBKXw6VLRHtXkOk5xySfUKLTqTkjgJFfDluIkf/O7eZwi5MXP50VeTbUg== 664 | 665 | stream-shift@^1.0.0: 666 | version "1.0.1" 667 | resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" 668 | integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== 669 | 670 | string_decoder@~0.10.x: 671 | version "0.10.31" 672 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" 673 | integrity sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ== 674 | 675 | string_decoder@~1.1.1: 676 | version "1.1.1" 677 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" 678 | integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== 679 | dependencies: 680 | safe-buffer "~5.1.0" 681 | 682 | supports-preserve-symlinks-flag@^1.0.0: 683 | version "1.0.0" 684 | resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" 685 | integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== 686 | 687 | three@^0.155.0: 688 | version "0.155.0" 689 | resolved "https://registry.yarnpkg.com/three/-/three-0.155.0.tgz#cca9b8ad817830c8b4fdd8f0d9a12a2e413a2672" 690 | integrity sha512-sNgCYmDijnIqkD/bMfk+1pHg3YzsxW7V2ChpuP6HCQ8NiZr3RufsXQr8M3SSUMjW4hG+sUk7YbyuY0DncaDTJQ== 691 | 692 | through2@^0.6.3: 693 | version "0.6.5" 694 | resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48" 695 | integrity sha512-RkK/CCESdTKQZHdmKICijdKKsCRVHs5KsLZ6pACAmF/1GPUQhonHSXWNERctxEp7RmvjdNbZTL5z9V7nSCXKcg== 696 | dependencies: 697 | readable-stream ">=1.0.33-1 <1.1.0-0" 698 | xtend ">=4.0.0 <4.1.0-0" 699 | 700 | through2@^2.0.1: 701 | version "2.0.5" 702 | resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" 703 | integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== 704 | dependencies: 705 | readable-stream "~2.3.6" 706 | xtend "~4.0.1" 707 | 708 | type-check@~0.3.2: 709 | version "0.3.2" 710 | resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" 711 | integrity sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg== 712 | dependencies: 713 | prelude-ls "~1.1.2" 714 | 715 | typedarray@^0.0.6: 716 | version "0.0.6" 717 | resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" 718 | integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== 719 | 720 | util-deprecate@~1.0.1: 721 | version "1.0.2" 722 | resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" 723 | integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== 724 | 725 | vite-plugin-glslify@^2.0.2: 726 | version "2.0.2" 727 | resolved "https://registry.yarnpkg.com/vite-plugin-glslify/-/vite-plugin-glslify-2.0.2.tgz#d04c7a960a19f015c0a91c238382131a45037eab" 728 | integrity sha512-b91F5PFkmYA21gSJF8iws4RvY1WbmJl9ewuAX/zm0JKV2vzAP8l2LzgRBbNVG96e0BDczJqFLNBG9A0dYALZyg== 729 | dependencies: 730 | "@rollup/pluginutils" "^4.1.1" 731 | astring "^1.7.5" 732 | glslify "^7.1.1" 733 | magic-string "^0.25.7" 734 | 735 | vite@^4.4.5: 736 | version "4.5.0" 737 | resolved "https://registry.yarnpkg.com/vite/-/vite-4.5.0.tgz#ec406295b4167ac3bc23e26f9c8ff559287cff26" 738 | integrity sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw== 739 | dependencies: 740 | esbuild "^0.18.10" 741 | postcss "^8.4.27" 742 | rollup "^3.27.1" 743 | optionalDependencies: 744 | fsevents "~2.3.2" 745 | 746 | word-wrap@~1.2.3: 747 | version "1.2.5" 748 | resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" 749 | integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== 750 | 751 | wrappy@1: 752 | version "1.0.2" 753 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 754 | integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== 755 | 756 | "xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.0, xtend@~4.0.1: 757 | version "4.0.2" 758 | resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" 759 | integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== 760 | 761 | xtend@^2.1.2: 762 | version "2.2.0" 763 | resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.2.0.tgz#eef6b1f198c1c8deafad8b1765a04dad4a01c5a9" 764 | integrity sha512-SLt5uylT+4aoXxXuwtQp5ZnMMzhDb1Xkg4pEqc00WUJCQifPfV9Ub1VrNhp9kXkrjZD2I2Hl8WnjP37jzZLPZw== 765 | --------------------------------------------------------------------------------