├── .gitignore ├── index.html ├── package-lock.json ├── package.json ├── public ├── LeePerrySmith │ ├── LeePerrySmith.glb │ ├── LeePerrySmith_License.txt │ ├── color.jpg │ └── normal.jpg ├── chars.png ├── david_head │ ├── license.txt │ ├── scene.bin │ └── scene.gltf └── vite.svg ├── src ├── canvas.ts ├── components │ └── model.ts ├── main.ts ├── shaders │ └── ascii │ │ └── ascii.glsl ├── style.css ├── types │ └── types.ts └── utils │ └── ascii-effect.ts ├── tsconfig.json └── vite.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + TS 8 | 9 | 10 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "three-js-boilerplate", 3 | "version": "0.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "three-js-boilerplate", 9 | "version": "0.0.0", 10 | "dependencies": { 11 | "lil-gui": "^0.19.2", 12 | "three": "^0.167.0", 13 | "vite-plugin-glsl": "^1.3.0" 14 | }, 15 | "devDependencies": { 16 | "@types/three": "^0.167.1", 17 | "typescript": "^5.2.2", 18 | "vite": "^5.3.4" 19 | } 20 | }, 21 | "node_modules/@esbuild/aix-ppc64": { 22 | "version": "0.21.5", 23 | "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", 24 | "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", 25 | "cpu": [ 26 | "ppc64" 27 | ], 28 | "optional": true, 29 | "os": [ 30 | "aix" 31 | ], 32 | "engines": { 33 | "node": ">=12" 34 | } 35 | }, 36 | "node_modules/@esbuild/android-arm": { 37 | "version": "0.21.5", 38 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", 39 | "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", 40 | "cpu": [ 41 | "arm" 42 | ], 43 | "optional": true, 44 | "os": [ 45 | "android" 46 | ], 47 | "engines": { 48 | "node": ">=12" 49 | } 50 | }, 51 | "node_modules/@esbuild/android-arm64": { 52 | "version": "0.21.5", 53 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", 54 | "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", 55 | "cpu": [ 56 | "arm64" 57 | ], 58 | "optional": true, 59 | "os": [ 60 | "android" 61 | ], 62 | "engines": { 63 | "node": ">=12" 64 | } 65 | }, 66 | "node_modules/@esbuild/android-x64": { 67 | "version": "0.21.5", 68 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", 69 | "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", 70 | "cpu": [ 71 | "x64" 72 | ], 73 | "optional": true, 74 | "os": [ 75 | "android" 76 | ], 77 | "engines": { 78 | "node": ">=12" 79 | } 80 | }, 81 | "node_modules/@esbuild/darwin-arm64": { 82 | "version": "0.21.5", 83 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", 84 | "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", 85 | "cpu": [ 86 | "arm64" 87 | ], 88 | "optional": true, 89 | "os": [ 90 | "darwin" 91 | ], 92 | "engines": { 93 | "node": ">=12" 94 | } 95 | }, 96 | "node_modules/@esbuild/darwin-x64": { 97 | "version": "0.21.5", 98 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", 99 | "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", 100 | "cpu": [ 101 | "x64" 102 | ], 103 | "optional": true, 104 | "os": [ 105 | "darwin" 106 | ], 107 | "engines": { 108 | "node": ">=12" 109 | } 110 | }, 111 | "node_modules/@esbuild/freebsd-arm64": { 112 | "version": "0.21.5", 113 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", 114 | "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", 115 | "cpu": [ 116 | "arm64" 117 | ], 118 | "optional": true, 119 | "os": [ 120 | "freebsd" 121 | ], 122 | "engines": { 123 | "node": ">=12" 124 | } 125 | }, 126 | "node_modules/@esbuild/freebsd-x64": { 127 | "version": "0.21.5", 128 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", 129 | "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", 130 | "cpu": [ 131 | "x64" 132 | ], 133 | "optional": true, 134 | "os": [ 135 | "freebsd" 136 | ], 137 | "engines": { 138 | "node": ">=12" 139 | } 140 | }, 141 | "node_modules/@esbuild/linux-arm": { 142 | "version": "0.21.5", 143 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", 144 | "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", 145 | "cpu": [ 146 | "arm" 147 | ], 148 | "optional": true, 149 | "os": [ 150 | "linux" 151 | ], 152 | "engines": { 153 | "node": ">=12" 154 | } 155 | }, 156 | "node_modules/@esbuild/linux-arm64": { 157 | "version": "0.21.5", 158 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", 159 | "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", 160 | "cpu": [ 161 | "arm64" 162 | ], 163 | "optional": true, 164 | "os": [ 165 | "linux" 166 | ], 167 | "engines": { 168 | "node": ">=12" 169 | } 170 | }, 171 | "node_modules/@esbuild/linux-ia32": { 172 | "version": "0.21.5", 173 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", 174 | "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", 175 | "cpu": [ 176 | "ia32" 177 | ], 178 | "optional": true, 179 | "os": [ 180 | "linux" 181 | ], 182 | "engines": { 183 | "node": ">=12" 184 | } 185 | }, 186 | "node_modules/@esbuild/linux-loong64": { 187 | "version": "0.21.5", 188 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", 189 | "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", 190 | "cpu": [ 191 | "loong64" 192 | ], 193 | "optional": true, 194 | "os": [ 195 | "linux" 196 | ], 197 | "engines": { 198 | "node": ">=12" 199 | } 200 | }, 201 | "node_modules/@esbuild/linux-mips64el": { 202 | "version": "0.21.5", 203 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", 204 | "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", 205 | "cpu": [ 206 | "mips64el" 207 | ], 208 | "optional": true, 209 | "os": [ 210 | "linux" 211 | ], 212 | "engines": { 213 | "node": ">=12" 214 | } 215 | }, 216 | "node_modules/@esbuild/linux-ppc64": { 217 | "version": "0.21.5", 218 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", 219 | "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", 220 | "cpu": [ 221 | "ppc64" 222 | ], 223 | "optional": true, 224 | "os": [ 225 | "linux" 226 | ], 227 | "engines": { 228 | "node": ">=12" 229 | } 230 | }, 231 | "node_modules/@esbuild/linux-riscv64": { 232 | "version": "0.21.5", 233 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", 234 | "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", 235 | "cpu": [ 236 | "riscv64" 237 | ], 238 | "optional": true, 239 | "os": [ 240 | "linux" 241 | ], 242 | "engines": { 243 | "node": ">=12" 244 | } 245 | }, 246 | "node_modules/@esbuild/linux-s390x": { 247 | "version": "0.21.5", 248 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", 249 | "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", 250 | "cpu": [ 251 | "s390x" 252 | ], 253 | "optional": true, 254 | "os": [ 255 | "linux" 256 | ], 257 | "engines": { 258 | "node": ">=12" 259 | } 260 | }, 261 | "node_modules/@esbuild/linux-x64": { 262 | "version": "0.21.5", 263 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", 264 | "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", 265 | "cpu": [ 266 | "x64" 267 | ], 268 | "optional": true, 269 | "os": [ 270 | "linux" 271 | ], 272 | "engines": { 273 | "node": ">=12" 274 | } 275 | }, 276 | "node_modules/@esbuild/netbsd-x64": { 277 | "version": "0.21.5", 278 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", 279 | "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", 280 | "cpu": [ 281 | "x64" 282 | ], 283 | "optional": true, 284 | "os": [ 285 | "netbsd" 286 | ], 287 | "engines": { 288 | "node": ">=12" 289 | } 290 | }, 291 | "node_modules/@esbuild/openbsd-x64": { 292 | "version": "0.21.5", 293 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", 294 | "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", 295 | "cpu": [ 296 | "x64" 297 | ], 298 | "optional": true, 299 | "os": [ 300 | "openbsd" 301 | ], 302 | "engines": { 303 | "node": ">=12" 304 | } 305 | }, 306 | "node_modules/@esbuild/sunos-x64": { 307 | "version": "0.21.5", 308 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", 309 | "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", 310 | "cpu": [ 311 | "x64" 312 | ], 313 | "optional": true, 314 | "os": [ 315 | "sunos" 316 | ], 317 | "engines": { 318 | "node": ">=12" 319 | } 320 | }, 321 | "node_modules/@esbuild/win32-arm64": { 322 | "version": "0.21.5", 323 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", 324 | "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", 325 | "cpu": [ 326 | "arm64" 327 | ], 328 | "optional": true, 329 | "os": [ 330 | "win32" 331 | ], 332 | "engines": { 333 | "node": ">=12" 334 | } 335 | }, 336 | "node_modules/@esbuild/win32-ia32": { 337 | "version": "0.21.5", 338 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", 339 | "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", 340 | "cpu": [ 341 | "ia32" 342 | ], 343 | "optional": true, 344 | "os": [ 345 | "win32" 346 | ], 347 | "engines": { 348 | "node": ">=12" 349 | } 350 | }, 351 | "node_modules/@esbuild/win32-x64": { 352 | "version": "0.21.5", 353 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", 354 | "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", 355 | "cpu": [ 356 | "x64" 357 | ], 358 | "optional": true, 359 | "os": [ 360 | "win32" 361 | ], 362 | "engines": { 363 | "node": ">=12" 364 | } 365 | }, 366 | "node_modules/@rollup/pluginutils": { 367 | "version": "5.1.0", 368 | "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz", 369 | "integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==", 370 | "dependencies": { 371 | "@types/estree": "^1.0.0", 372 | "estree-walker": "^2.0.2", 373 | "picomatch": "^2.3.1" 374 | }, 375 | "engines": { 376 | "node": ">=14.0.0" 377 | }, 378 | "peerDependencies": { 379 | "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" 380 | }, 381 | "peerDependenciesMeta": { 382 | "rollup": { 383 | "optional": true 384 | } 385 | } 386 | }, 387 | "node_modules/@rollup/rollup-android-arm-eabi": { 388 | "version": "4.21.1", 389 | "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.21.1.tgz", 390 | "integrity": "sha512-2thheikVEuU7ZxFXubPDOtspKn1x0yqaYQwvALVtEcvFhMifPADBrgRPyHV0TF3b+9BgvgjgagVyvA/UqPZHmg==", 391 | "cpu": [ 392 | "arm" 393 | ], 394 | "optional": true, 395 | "os": [ 396 | "android" 397 | ] 398 | }, 399 | "node_modules/@rollup/rollup-android-arm64": { 400 | "version": "4.21.1", 401 | "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.21.1.tgz", 402 | "integrity": "sha512-t1lLYn4V9WgnIFHXy1d2Di/7gyzBWS8G5pQSXdZqfrdCGTwi1VasRMSS81DTYb+avDs/Zz4A6dzERki5oRYz1g==", 403 | "cpu": [ 404 | "arm64" 405 | ], 406 | "optional": true, 407 | "os": [ 408 | "android" 409 | ] 410 | }, 411 | "node_modules/@rollup/rollup-darwin-arm64": { 412 | "version": "4.21.1", 413 | "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.21.1.tgz", 414 | "integrity": "sha512-AH/wNWSEEHvs6t4iJ3RANxW5ZCK3fUnmf0gyMxWCesY1AlUj8jY7GC+rQE4wd3gwmZ9XDOpL0kcFnCjtN7FXlA==", 415 | "cpu": [ 416 | "arm64" 417 | ], 418 | "optional": true, 419 | "os": [ 420 | "darwin" 421 | ] 422 | }, 423 | "node_modules/@rollup/rollup-darwin-x64": { 424 | "version": "4.21.1", 425 | "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.21.1.tgz", 426 | "integrity": "sha512-dO0BIz/+5ZdkLZrVgQrDdW7m2RkrLwYTh2YMFG9IpBtlC1x1NPNSXkfczhZieOlOLEqgXOFH3wYHB7PmBtf+Bg==", 427 | "cpu": [ 428 | "x64" 429 | ], 430 | "optional": true, 431 | "os": [ 432 | "darwin" 433 | ] 434 | }, 435 | "node_modules/@rollup/rollup-linux-arm-gnueabihf": { 436 | "version": "4.21.1", 437 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.21.1.tgz", 438 | "integrity": "sha512-sWWgdQ1fq+XKrlda8PsMCfut8caFwZBmhYeoehJ05FdI0YZXk6ZyUjWLrIgbR/VgiGycrFKMMgp7eJ69HOF2pQ==", 439 | "cpu": [ 440 | "arm" 441 | ], 442 | "optional": true, 443 | "os": [ 444 | "linux" 445 | ] 446 | }, 447 | "node_modules/@rollup/rollup-linux-arm-musleabihf": { 448 | "version": "4.21.1", 449 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.21.1.tgz", 450 | "integrity": "sha512-9OIiSuj5EsYQlmwhmFRA0LRO0dRRjdCVZA3hnmZe1rEwRk11Jy3ECGGq3a7RrVEZ0/pCsYWx8jG3IvcrJ6RCew==", 451 | "cpu": [ 452 | "arm" 453 | ], 454 | "optional": true, 455 | "os": [ 456 | "linux" 457 | ] 458 | }, 459 | "node_modules/@rollup/rollup-linux-arm64-gnu": { 460 | "version": "4.21.1", 461 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.21.1.tgz", 462 | "integrity": "sha512-0kuAkRK4MeIUbzQYu63NrJmfoUVicajoRAL1bpwdYIYRcs57iyIV9NLcuyDyDXE2GiZCL4uhKSYAnyWpjZkWow==", 463 | "cpu": [ 464 | "arm64" 465 | ], 466 | "optional": true, 467 | "os": [ 468 | "linux" 469 | ] 470 | }, 471 | "node_modules/@rollup/rollup-linux-arm64-musl": { 472 | "version": "4.21.1", 473 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.21.1.tgz", 474 | "integrity": "sha512-/6dYC9fZtfEY0vozpc5bx1RP4VrtEOhNQGb0HwvYNwXD1BBbwQ5cKIbUVVU7G2d5WRE90NfB922elN8ASXAJEA==", 475 | "cpu": [ 476 | "arm64" 477 | ], 478 | "optional": true, 479 | "os": [ 480 | "linux" 481 | ] 482 | }, 483 | "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { 484 | "version": "4.21.1", 485 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.21.1.tgz", 486 | "integrity": "sha512-ltUWy+sHeAh3YZ91NUsV4Xg3uBXAlscQe8ZOXRCVAKLsivGuJsrkawYPUEyCV3DYa9urgJugMLn8Z3Z/6CeyRQ==", 487 | "cpu": [ 488 | "ppc64" 489 | ], 490 | "optional": true, 491 | "os": [ 492 | "linux" 493 | ] 494 | }, 495 | "node_modules/@rollup/rollup-linux-riscv64-gnu": { 496 | "version": "4.21.1", 497 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.21.1.tgz", 498 | "integrity": "sha512-BggMndzI7Tlv4/abrgLwa/dxNEMn2gC61DCLrTzw8LkpSKel4o+O+gtjbnkevZ18SKkeN3ihRGPuBxjaetWzWg==", 499 | "cpu": [ 500 | "riscv64" 501 | ], 502 | "optional": true, 503 | "os": [ 504 | "linux" 505 | ] 506 | }, 507 | "node_modules/@rollup/rollup-linux-s390x-gnu": { 508 | "version": "4.21.1", 509 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.21.1.tgz", 510 | "integrity": "sha512-z/9rtlGd/OMv+gb1mNSjElasMf9yXusAxnRDrBaYB+eS1shFm6/4/xDH1SAISO5729fFKUkJ88TkGPRUh8WSAA==", 511 | "cpu": [ 512 | "s390x" 513 | ], 514 | "optional": true, 515 | "os": [ 516 | "linux" 517 | ] 518 | }, 519 | "node_modules/@rollup/rollup-linux-x64-gnu": { 520 | "version": "4.21.1", 521 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.21.1.tgz", 522 | "integrity": "sha512-kXQVcWqDcDKw0S2E0TmhlTLlUgAmMVqPrJZR+KpH/1ZaZhLSl23GZpQVmawBQGVhyP5WXIsIQ/zqbDBBYmxm5w==", 523 | "cpu": [ 524 | "x64" 525 | ], 526 | "optional": true, 527 | "os": [ 528 | "linux" 529 | ] 530 | }, 531 | "node_modules/@rollup/rollup-linux-x64-musl": { 532 | "version": "4.21.1", 533 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.21.1.tgz", 534 | "integrity": "sha512-CbFv/WMQsSdl+bpX6rVbzR4kAjSSBuDgCqb1l4J68UYsQNalz5wOqLGYj4ZI0thGpyX5kc+LLZ9CL+kpqDovZA==", 535 | "cpu": [ 536 | "x64" 537 | ], 538 | "optional": true, 539 | "os": [ 540 | "linux" 541 | ] 542 | }, 543 | "node_modules/@rollup/rollup-win32-arm64-msvc": { 544 | "version": "4.21.1", 545 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.21.1.tgz", 546 | "integrity": "sha512-3Q3brDgA86gHXWHklrwdREKIrIbxC0ZgU8lwpj0eEKGBQH+31uPqr0P2v11pn0tSIxHvcdOWxa4j+YvLNx1i6g==", 547 | "cpu": [ 548 | "arm64" 549 | ], 550 | "optional": true, 551 | "os": [ 552 | "win32" 553 | ] 554 | }, 555 | "node_modules/@rollup/rollup-win32-ia32-msvc": { 556 | "version": "4.21.1", 557 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.21.1.tgz", 558 | "integrity": "sha512-tNg+jJcKR3Uwe4L0/wY3Ro0H+u3nrb04+tcq1GSYzBEmKLeOQF2emk1whxlzNqb6MMrQ2JOcQEpuuiPLyRcSIw==", 559 | "cpu": [ 560 | "ia32" 561 | ], 562 | "optional": true, 563 | "os": [ 564 | "win32" 565 | ] 566 | }, 567 | "node_modules/@rollup/rollup-win32-x64-msvc": { 568 | "version": "4.21.1", 569 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.21.1.tgz", 570 | "integrity": "sha512-xGiIH95H1zU7naUyTKEyOA/I0aexNMUdO9qRv0bLKN3qu25bBdrxZHqA3PTJ24YNN/GdMzG4xkDcd/GvjuhfLg==", 571 | "cpu": [ 572 | "x64" 573 | ], 574 | "optional": true, 575 | "os": [ 576 | "win32" 577 | ] 578 | }, 579 | "node_modules/@tweenjs/tween.js": { 580 | "version": "23.1.3", 581 | "resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-23.1.3.tgz", 582 | "integrity": "sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA==", 583 | "dev": true 584 | }, 585 | "node_modules/@types/estree": { 586 | "version": "1.0.5", 587 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", 588 | "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" 589 | }, 590 | "node_modules/@types/stats.js": { 591 | "version": "0.17.3", 592 | "resolved": "https://registry.npmjs.org/@types/stats.js/-/stats.js-0.17.3.tgz", 593 | "integrity": "sha512-pXNfAD3KHOdif9EQXZ9deK82HVNaXP5ZIF5RP2QG6OQFNTaY2YIetfrE9t528vEreGQvEPRDDc8muaoYeK0SxQ==", 594 | "dev": true 595 | }, 596 | "node_modules/@types/three": { 597 | "version": "0.167.2", 598 | "resolved": "https://registry.npmjs.org/@types/three/-/three-0.167.2.tgz", 599 | "integrity": "sha512-onxnIUNYpXcZJ5DTiIsxfnr4F9kAWkkxAUWx5yqzz/u0a4IygCLCjMuOl2DEeCxyJdJ2nOJZvKpu48sBMqfmkQ==", 600 | "dev": true, 601 | "dependencies": { 602 | "@tweenjs/tween.js": "~23.1.2", 603 | "@types/stats.js": "*", 604 | "@types/webxr": "*", 605 | "fflate": "~0.8.2", 606 | "meshoptimizer": "~0.18.1" 607 | } 608 | }, 609 | "node_modules/@types/webxr": { 610 | "version": "0.5.20", 611 | "resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.20.tgz", 612 | "integrity": "sha512-JGpU6qiIJQKUuVSKx1GtQnHJGxRjtfGIhzO2ilq43VZZS//f1h1Sgexbdk+Lq+7569a6EYhOWrUpIruR/1Enmg==", 613 | "dev": true 614 | }, 615 | "node_modules/esbuild": { 616 | "version": "0.21.5", 617 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", 618 | "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", 619 | "hasInstallScript": true, 620 | "bin": { 621 | "esbuild": "bin/esbuild" 622 | }, 623 | "engines": { 624 | "node": ">=12" 625 | }, 626 | "optionalDependencies": { 627 | "@esbuild/aix-ppc64": "0.21.5", 628 | "@esbuild/android-arm": "0.21.5", 629 | "@esbuild/android-arm64": "0.21.5", 630 | "@esbuild/android-x64": "0.21.5", 631 | "@esbuild/darwin-arm64": "0.21.5", 632 | "@esbuild/darwin-x64": "0.21.5", 633 | "@esbuild/freebsd-arm64": "0.21.5", 634 | "@esbuild/freebsd-x64": "0.21.5", 635 | "@esbuild/linux-arm": "0.21.5", 636 | "@esbuild/linux-arm64": "0.21.5", 637 | "@esbuild/linux-ia32": "0.21.5", 638 | "@esbuild/linux-loong64": "0.21.5", 639 | "@esbuild/linux-mips64el": "0.21.5", 640 | "@esbuild/linux-ppc64": "0.21.5", 641 | "@esbuild/linux-riscv64": "0.21.5", 642 | "@esbuild/linux-s390x": "0.21.5", 643 | "@esbuild/linux-x64": "0.21.5", 644 | "@esbuild/netbsd-x64": "0.21.5", 645 | "@esbuild/openbsd-x64": "0.21.5", 646 | "@esbuild/sunos-x64": "0.21.5", 647 | "@esbuild/win32-arm64": "0.21.5", 648 | "@esbuild/win32-ia32": "0.21.5", 649 | "@esbuild/win32-x64": "0.21.5" 650 | } 651 | }, 652 | "node_modules/estree-walker": { 653 | "version": "2.0.2", 654 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", 655 | "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" 656 | }, 657 | "node_modules/fflate": { 658 | "version": "0.8.2", 659 | "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", 660 | "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", 661 | "dev": true 662 | }, 663 | "node_modules/fsevents": { 664 | "version": "2.3.3", 665 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 666 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 667 | "hasInstallScript": true, 668 | "optional": true, 669 | "os": [ 670 | "darwin" 671 | ], 672 | "engines": { 673 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 674 | } 675 | }, 676 | "node_modules/lil-gui": { 677 | "version": "0.19.2", 678 | "resolved": "https://registry.npmjs.org/lil-gui/-/lil-gui-0.19.2.tgz", 679 | "integrity": "sha512-nU8j4ND702ouGfQZoaTN4dfXxacvGOAVK0DtmZBVcUYUAeYQXLQAjAN50igMHiba3T5jZyKEjXZU+Ntm1Qs6ZQ==" 680 | }, 681 | "node_modules/meshoptimizer": { 682 | "version": "0.18.1", 683 | "resolved": "https://registry.npmjs.org/meshoptimizer/-/meshoptimizer-0.18.1.tgz", 684 | "integrity": "sha512-ZhoIoL7TNV4s5B6+rx5mC//fw8/POGyNxS/DZyCJeiZ12ScLfVwRE/GfsxwiTkMYYD5DmK2/JXnEVXqL4rF+Sw==", 685 | "dev": true 686 | }, 687 | "node_modules/nanoid": { 688 | "version": "3.3.7", 689 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", 690 | "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", 691 | "funding": [ 692 | { 693 | "type": "github", 694 | "url": "https://github.com/sponsors/ai" 695 | } 696 | ], 697 | "bin": { 698 | "nanoid": "bin/nanoid.cjs" 699 | }, 700 | "engines": { 701 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 702 | } 703 | }, 704 | "node_modules/picocolors": { 705 | "version": "1.0.1", 706 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", 707 | "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" 708 | }, 709 | "node_modules/picomatch": { 710 | "version": "2.3.1", 711 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 712 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 713 | "engines": { 714 | "node": ">=8.6" 715 | }, 716 | "funding": { 717 | "url": "https://github.com/sponsors/jonschlinkert" 718 | } 719 | }, 720 | "node_modules/postcss": { 721 | "version": "8.4.41", 722 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz", 723 | "integrity": "sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==", 724 | "funding": [ 725 | { 726 | "type": "opencollective", 727 | "url": "https://opencollective.com/postcss/" 728 | }, 729 | { 730 | "type": "tidelift", 731 | "url": "https://tidelift.com/funding/github/npm/postcss" 732 | }, 733 | { 734 | "type": "github", 735 | "url": "https://github.com/sponsors/ai" 736 | } 737 | ], 738 | "dependencies": { 739 | "nanoid": "^3.3.7", 740 | "picocolors": "^1.0.1", 741 | "source-map-js": "^1.2.0" 742 | }, 743 | "engines": { 744 | "node": "^10 || ^12 || >=14" 745 | } 746 | }, 747 | "node_modules/rollup": { 748 | "version": "4.21.1", 749 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.21.1.tgz", 750 | "integrity": "sha512-ZnYyKvscThhgd3M5+Qt3pmhO4jIRR5RGzaSovB6Q7rGNrK5cUncrtLmcTTJVSdcKXyZjW8X8MB0JMSuH9bcAJg==", 751 | "dependencies": { 752 | "@types/estree": "1.0.5" 753 | }, 754 | "bin": { 755 | "rollup": "dist/bin/rollup" 756 | }, 757 | "engines": { 758 | "node": ">=18.0.0", 759 | "npm": ">=8.0.0" 760 | }, 761 | "optionalDependencies": { 762 | "@rollup/rollup-android-arm-eabi": "4.21.1", 763 | "@rollup/rollup-android-arm64": "4.21.1", 764 | "@rollup/rollup-darwin-arm64": "4.21.1", 765 | "@rollup/rollup-darwin-x64": "4.21.1", 766 | "@rollup/rollup-linux-arm-gnueabihf": "4.21.1", 767 | "@rollup/rollup-linux-arm-musleabihf": "4.21.1", 768 | "@rollup/rollup-linux-arm64-gnu": "4.21.1", 769 | "@rollup/rollup-linux-arm64-musl": "4.21.1", 770 | "@rollup/rollup-linux-powerpc64le-gnu": "4.21.1", 771 | "@rollup/rollup-linux-riscv64-gnu": "4.21.1", 772 | "@rollup/rollup-linux-s390x-gnu": "4.21.1", 773 | "@rollup/rollup-linux-x64-gnu": "4.21.1", 774 | "@rollup/rollup-linux-x64-musl": "4.21.1", 775 | "@rollup/rollup-win32-arm64-msvc": "4.21.1", 776 | "@rollup/rollup-win32-ia32-msvc": "4.21.1", 777 | "@rollup/rollup-win32-x64-msvc": "4.21.1", 778 | "fsevents": "~2.3.2" 779 | } 780 | }, 781 | "node_modules/source-map-js": { 782 | "version": "1.2.0", 783 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", 784 | "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", 785 | "engines": { 786 | "node": ">=0.10.0" 787 | } 788 | }, 789 | "node_modules/three": { 790 | "version": "0.167.1", 791 | "resolved": "https://registry.npmjs.org/three/-/three-0.167.1.tgz", 792 | "integrity": "sha512-gYTLJA/UQip6J/tJvl91YYqlZF47+D/kxiWrbTon35ZHlXEN0VOo+Qke2walF1/x92v55H6enomymg4Dak52kw==" 793 | }, 794 | "node_modules/typescript": { 795 | "version": "5.5.4", 796 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", 797 | "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", 798 | "dev": true, 799 | "bin": { 800 | "tsc": "bin/tsc", 801 | "tsserver": "bin/tsserver" 802 | }, 803 | "engines": { 804 | "node": ">=14.17" 805 | } 806 | }, 807 | "node_modules/vite": { 808 | "version": "5.4.2", 809 | "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.2.tgz", 810 | "integrity": "sha512-dDrQTRHp5C1fTFzcSaMxjk6vdpKvT+2/mIdE07Gw2ykehT49O0z/VHS3zZ8iV/Gh8BJJKHWOe5RjaNrW5xf/GA==", 811 | "dependencies": { 812 | "esbuild": "^0.21.3", 813 | "postcss": "^8.4.41", 814 | "rollup": "^4.20.0" 815 | }, 816 | "bin": { 817 | "vite": "bin/vite.js" 818 | }, 819 | "engines": { 820 | "node": "^18.0.0 || >=20.0.0" 821 | }, 822 | "funding": { 823 | "url": "https://github.com/vitejs/vite?sponsor=1" 824 | }, 825 | "optionalDependencies": { 826 | "fsevents": "~2.3.3" 827 | }, 828 | "peerDependencies": { 829 | "@types/node": "^18.0.0 || >=20.0.0", 830 | "less": "*", 831 | "lightningcss": "^1.21.0", 832 | "sass": "*", 833 | "sass-embedded": "*", 834 | "stylus": "*", 835 | "sugarss": "*", 836 | "terser": "^5.4.0" 837 | }, 838 | "peerDependenciesMeta": { 839 | "@types/node": { 840 | "optional": true 841 | }, 842 | "less": { 843 | "optional": true 844 | }, 845 | "lightningcss": { 846 | "optional": true 847 | }, 848 | "sass": { 849 | "optional": true 850 | }, 851 | "sass-embedded": { 852 | "optional": true 853 | }, 854 | "stylus": { 855 | "optional": true 856 | }, 857 | "sugarss": { 858 | "optional": true 859 | }, 860 | "terser": { 861 | "optional": true 862 | } 863 | } 864 | }, 865 | "node_modules/vite-plugin-glsl": { 866 | "version": "1.3.0", 867 | "resolved": "https://registry.npmjs.org/vite-plugin-glsl/-/vite-plugin-glsl-1.3.0.tgz", 868 | "integrity": "sha512-SzEoLet9Bp5VSozjrhUiSc3xX1+u7rCTjXAsq4qWM3u8UjilI76A9ucX/T+CRGQCe25j50GSY+9mKSGUVPET1w==", 869 | "dependencies": { 870 | "@rollup/pluginutils": "^5.1.0" 871 | }, 872 | "engines": { 873 | "node": ">= 16.15.1", 874 | "npm": ">= 8.11.0" 875 | }, 876 | "peerDependencies": { 877 | "vite": "^3.0.0 || ^4.0.0 || ^5.0.0" 878 | } 879 | } 880 | } 881 | } 882 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "three-js-boilerplate", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "tsc && vite build", 9 | "preview": "vite preview" 10 | }, 11 | "devDependencies": { 12 | "@types/three": "^0.167.1", 13 | "typescript": "^5.2.2", 14 | "vite": "^5.3.4" 15 | }, 16 | "dependencies": { 17 | "lil-gui": "^0.19.2", 18 | "three": "^0.167.0", 19 | "vite-plugin-glsl": "^1.3.0" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /public/LeePerrySmith/LeePerrySmith.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/J0SUKE/ASCII-postprocessing/95bc63d0f69105538edca398382973f7cd3f8626/public/LeePerrySmith/LeePerrySmith.glb -------------------------------------------------------------------------------- /public/LeePerrySmith/LeePerrySmith_License.txt: -------------------------------------------------------------------------------- 1 | Creative Commons Licence 2 | Infinite, 3D Head Scan by Lee Perry-Smith is licensed under a Creative Commons Attribution 3.0 Unported License. 3 | Based on a work at www.triplegangers.com. 4 | File named modified by Bruno SIMON to simplify importing. 5 | Permissions beyond the scope of this license may be available at http://www.ir-ltd.net/ 6 | Please remember: Do what you want with the files, but always mention where you got them from... 7 | -------------------------------------------------------------------------------- /public/LeePerrySmith/color.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/J0SUKE/ASCII-postprocessing/95bc63d0f69105538edca398382973f7cd3f8626/public/LeePerrySmith/color.jpg -------------------------------------------------------------------------------- /public/LeePerrySmith/normal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/J0SUKE/ASCII-postprocessing/95bc63d0f69105538edca398382973f7cd3f8626/public/LeePerrySmith/normal.jpg -------------------------------------------------------------------------------- /public/chars.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/J0SUKE/ASCII-postprocessing/95bc63d0f69105538edca398382973f7cd3f8626/public/chars.png -------------------------------------------------------------------------------- /public/david_head/license.txt: -------------------------------------------------------------------------------- 1 | Model Information: 2 | * title: David Head 3 | * source: https://sketchfab.com/3d-models/david-head-39a4d01bef37495cac8d8f0009728871 4 | * author: 1d_inc (https://sketchfab.com/1d_inc) 5 | 6 | Model License: 7 | * license type: CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/) 8 | * requirements: Author must be credited. Commercial use is allowed. 9 | 10 | If you use this 3D model in your project be sure to copy paste this credit wherever you share it: 11 | This work is based on "David Head" (https://sketchfab.com/3d-models/david-head-39a4d01bef37495cac8d8f0009728871) by 1d_inc (https://sketchfab.com/1d_inc) licensed under CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/) -------------------------------------------------------------------------------- /public/david_head/scene.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/J0SUKE/ASCII-postprocessing/95bc63d0f69105538edca398382973f7cd3f8626/public/david_head/scene.bin -------------------------------------------------------------------------------- /public/david_head/scene.gltf: -------------------------------------------------------------------------------- 1 | { 2 | "accessors": [ 3 | { 4 | "bufferView": 2, 5 | "componentType": 5126, 6 | "count": 24011, 7 | "max": [ 8 | 72.03296661376953, 9 | 120.36872863769531, 10 | 99.9263916015625 11 | ], 12 | "min": [ 13 | -58.47863006591797, 14 | -30.07625961303711, 15 | -97.18975067138672 16 | ], 17 | "type": "VEC3" 18 | }, 19 | { 20 | "bufferView": 2, 21 | "byteOffset": 288132, 22 | "componentType": 5126, 23 | "count": 24011, 24 | "max": [ 25 | 0.9999601244926453, 26 | 0.9999906420707703, 27 | 0.9999125003814697 28 | ], 29 | "min": [ 30 | -0.9999507069587708, 31 | -0.9999876618385315, 32 | -0.9999999403953552 33 | ], 34 | "type": "VEC3" 35 | }, 36 | { 37 | "bufferView": 1, 38 | "componentType": 5126, 39 | "count": 24011, 40 | "max": [ 41 | 0.9793000221252441, 42 | 0.999809980392456 43 | ], 44 | "min": [ 45 | 0.0001900000061141327, 46 | 0.0001900000061141327 47 | ], 48 | "type": "VEC2" 49 | }, 50 | { 51 | "bufferView": 0, 52 | "componentType": 5125, 53 | "count": 139992, 54 | "type": "SCALAR" 55 | } 56 | ], 57 | "asset": { 58 | "extras": { 59 | "author": "1d_inc (https://sketchfab.com/1d_inc)", 60 | "license": "CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)", 61 | "source": "https://sketchfab.com/3d-models/david-head-39a4d01bef37495cac8d8f0009728871", 62 | "title": "David Head" 63 | }, 64 | "generator": "Sketchfab-15.33.0", 65 | "version": "2.0" 66 | }, 67 | "bufferViews": [ 68 | { 69 | "buffer": 0, 70 | "byteLength": 559968, 71 | "name": "floatBufferViews", 72 | "target": 34963 73 | }, 74 | { 75 | "buffer": 0, 76 | "byteLength": 192088, 77 | "byteOffset": 559968, 78 | "byteStride": 8, 79 | "name": "floatBufferViews", 80 | "target": 34962 81 | }, 82 | { 83 | "buffer": 0, 84 | "byteLength": 576264, 85 | "byteOffset": 752056, 86 | "byteStride": 12, 87 | "name": "floatBufferViews", 88 | "target": 34962 89 | } 90 | ], 91 | "buffers": [ 92 | { 93 | "byteLength": 1328320, 94 | "uri": "scene.bin" 95 | } 96 | ], 97 | "materials": [ 98 | { 99 | "doubleSided": true, 100 | "name": "Scene_-_Root", 101 | "pbrMetallicRoughness": { 102 | "baseColorFactor": [ 103 | 0.539777445607042, 104 | 0.539777445607042, 105 | 0.539777445607042, 106 | 1.0 107 | ], 108 | "metallicFactor": 0.0, 109 | "roughnessFactor": 0.6 110 | } 111 | } 112 | ], 113 | "meshes": [ 114 | { 115 | "name": "David head by 1D_0", 116 | "primitives": [ 117 | { 118 | "attributes": { 119 | "NORMAL": 1, 120 | "POSITION": 0, 121 | "TEXCOORD_0": 2 122 | }, 123 | "indices": 3, 124 | "material": 0, 125 | "mode": 4 126 | } 127 | ] 128 | } 129 | ], 130 | "nodes": [ 131 | { 132 | "children": [ 133 | 1 134 | ], 135 | "matrix": [ 136 | 1.0, 137 | 0.0, 138 | 0.0, 139 | 0.0, 140 | 0.0, 141 | 2.220446049250313e-16, 142 | -1.0, 143 | 0.0, 144 | 0.0, 145 | 1.0, 146 | 2.220446049250313e-16, 147 | 0.0, 148 | 0.0, 149 | 0.0, 150 | 0.0, 151 | 1.0 152 | ], 153 | "name": "Sketchfab_model" 154 | }, 155 | { 156 | "children": [ 157 | 2 158 | ], 159 | "name": "Root" 160 | }, 161 | { 162 | "children": [ 163 | 3 164 | ], 165 | "matrix": [ 166 | 1.0, 167 | 0.0, 168 | 0.0, 169 | 0.0, 170 | 0.0, 171 | 1.0, 172 | 0.0, 173 | 0.0, 174 | 0.0, 175 | 0.0, 176 | 1.0, 177 | 0.0, 178 | -0.24123000000000003, 179 | -29.320980000000002, 180 | 97.60269, 181 | 1.0 182 | ], 183 | "name": "David head by 1D" 184 | }, 185 | { 186 | "mesh": 0, 187 | "name": "David head by 1D_0" 188 | } 189 | ], 190 | "scene": 0, 191 | "scenes": [ 192 | { 193 | "name": "Sketchfab_Scene", 194 | "nodes": [ 195 | 0 196 | ] 197 | } 198 | ] 199 | } 200 | -------------------------------------------------------------------------------- /public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/canvas.ts: -------------------------------------------------------------------------------- 1 | import * as THREE from 'three' 2 | import { Dimensions } from './types/types' 3 | import { OrbitControls } from 'three/addons/controls/OrbitControls.js' 4 | import GUI from 'lil-gui' 5 | import Model from './components/model' 6 | 7 | import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js' 8 | import { RenderPass } from 'three/addons/postprocessing/RenderPass.js' 9 | import { OutputPass } from 'three/addons/postprocessing/OutputPass.js' 10 | import AsciiEffect from './utils/ascii-effect' 11 | 12 | export default class Canvas { 13 | element: HTMLCanvasElement 14 | scene: THREE.Scene 15 | camera: THREE.PerspectiveCamera 16 | renderer: THREE.WebGLRenderer 17 | dimensions: Dimensions 18 | time: number 19 | clock: THREE.Clock 20 | orbitControls: OrbitControls 21 | debug: GUI 22 | model: Model 23 | composer: EffectComposer 24 | asciiPass: AsciiEffect 25 | directionalLight: THREE.DirectionalLight 26 | 27 | constructor() { 28 | this.element = document.getElementById('webgl') as HTMLCanvasElement 29 | this.time = 0 30 | this.createClock() 31 | this.createScene() 32 | this.createCamera() 33 | this.createRenderer() 34 | this.createOrbitControls() 35 | this.addEventListeners() 36 | this.createLight() 37 | this.createModel() 38 | this.createPostProcessing() 39 | this.createDebug() 40 | this.render() 41 | } 42 | 43 | createScene() { 44 | this.scene = new THREE.Scene() 45 | } 46 | 47 | createCamera() { 48 | this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 100) 49 | this.scene.add(this.camera) 50 | this.camera.position.z = 6 51 | this.camera.position.x = -2 52 | this.camera.position.y = 1 53 | } 54 | 55 | createOrbitControls() { 56 | this.orbitControls = new OrbitControls(this.camera, this.renderer.domElement) 57 | } 58 | 59 | createRenderer() { 60 | this.dimensions = { 61 | width: window.innerWidth, 62 | height: window.innerHeight, 63 | pixelRatio: Math.min(2, window.devicePixelRatio), 64 | } 65 | 66 | this.renderer = new THREE.WebGLRenderer({ canvas: this.element, alpha: true }) 67 | this.renderer.setSize(this.dimensions.width, this.dimensions.height) 68 | this.renderer.render(this.scene, this.camera) 69 | 70 | this.renderer.setPixelRatio(this.dimensions.pixelRatio) 71 | } 72 | 73 | createPostProcessing() { 74 | this.composer = new EffectComposer(this.renderer) 75 | const renderPass = new RenderPass(this.scene, this.camera) 76 | this.composer.addPass(renderPass) 77 | 78 | this.asciiPass = new AsciiEffect() 79 | this.composer.addPass(this.asciiPass.asciiPass) 80 | 81 | const outputPass = new OutputPass() 82 | this.composer.addPass(outputPass) 83 | } 84 | 85 | createDebug() { 86 | this.debug = new GUI() 87 | 88 | const obj = { 89 | bool: true, 90 | } 91 | 92 | this.debug 93 | .add(obj, 'bool') 94 | .onChange((val: boolean) => { 95 | if (val) { 96 | this.asciiPass.asciiPass.material.uniforms.uShowAscii.value = 1 97 | } else { 98 | this.asciiPass.asciiPass.material.uniforms.uShowAscii.value = 0 99 | } 100 | }) 101 | .listen() 102 | .name('ASCII') 103 | 104 | this.debug.add(this.directionalLight, 'intensity').min(1).max(10).step(0.1).name('Light intensity') 105 | } 106 | 107 | createClock() { 108 | this.clock = new THREE.Clock() 109 | } 110 | 111 | addEventListeners() { 112 | window.addEventListener('resize', this.onResize.bind(this)) 113 | } 114 | 115 | onResize() { 116 | this.dimensions = { 117 | width: window.innerWidth, 118 | height: window.innerHeight, 119 | pixelRatio: Math.min(2, window.devicePixelRatio), 120 | } 121 | 122 | this.camera.aspect = window.innerWidth / window.innerHeight 123 | this.camera.updateProjectionMatrix() 124 | 125 | this.renderer.setPixelRatio(this.dimensions.pixelRatio) 126 | this.renderer.setSize(this.dimensions.width, this.dimensions.height) 127 | } 128 | 129 | createLight() { 130 | this.directionalLight = new THREE.DirectionalLight('white', 1) 131 | this.directionalLight.position.x = 10 132 | this.directionalLight.position.z = 10 133 | this.directionalLight.position.y = 5 134 | 135 | this.scene.add(this.directionalLight) 136 | } 137 | 138 | createModel() { 139 | this.model = new Model({ scene: this.scene }) 140 | } 141 | 142 | render() { 143 | this.time = this.clock.getElapsedTime() 144 | 145 | this.orbitControls.update() 146 | 147 | this.model.render(this.time) 148 | 149 | //this.renderer.render(this.scene, this.camera) 150 | this.composer.render() 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /src/components/model.ts: -------------------------------------------------------------------------------- 1 | import * as THREE from 'three' 2 | import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js' 3 | 4 | interface Props { 5 | scene: THREE.Scene 6 | } 7 | 8 | export default class Model { 9 | loader: GLTFLoader 10 | scene: THREE.Scene 11 | model: null | THREE.Group 12 | //material: CustomShaderMaterial 13 | material: THREE.MeshStandardMaterial 14 | 15 | constructor({ scene }: Props) { 16 | this.scene = scene 17 | this.loader = new GLTFLoader() 18 | this.model = null 19 | this.createMaterial() 20 | this.loadModel() 21 | } 22 | 23 | createMaterial() { 24 | this.material = new THREE.MeshStandardMaterial({ 25 | color: 'white', 26 | }) 27 | } 28 | 29 | loadModel() { 30 | this.loader.load( 31 | // resource URL 32 | '/LeePerrySmith/LeePerrySmith.glb', 33 | //'/david_head/scene.gltf', 34 | (gltf) => { 35 | console.log(gltf) 36 | this.model = gltf.scene 37 | //this.model.scale.set(0.05, 0.05, 0.05) 38 | //this.model.position.y -= 5 39 | const mesh = this.model.children[0] as THREE.Mesh 40 | mesh.material = this.material 41 | this.scene.add(this.model) 42 | } 43 | ) 44 | } 45 | 46 | render(time: number) { 47 | if (this.model) { 48 | //this.model.rotation.y = time * 0.3 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import './style.css' 2 | import Canvas from './canvas' 3 | 4 | class App { 5 | canvas: Canvas 6 | 7 | constructor() { 8 | this.canvas = new Canvas() 9 | 10 | this.render() 11 | } 12 | 13 | render() { 14 | this.canvas.render() 15 | requestAnimationFrame(this.render.bind(this)) 16 | } 17 | } 18 | 19 | export default new App() 20 | -------------------------------------------------------------------------------- /src/shaders/ascii/ascii.glsl: -------------------------------------------------------------------------------- 1 | uniform float opacity; 2 | 3 | uniform sampler2D tDiffuse; 4 | uniform vec2 uResolution; 5 | varying vec2 vUv; 6 | uniform sampler2D uTexture; 7 | uniform vec2 uTextureResolution; 8 | uniform float uShowAscii; 9 | uniform float uSize; 10 | 11 | float random (vec2 st) { 12 | return fract(sin(dot(st.xy, 13 | vec2(12.9898,78.233)))* 14 | 43758.5453123); 15 | } 16 | 17 | void main() { 18 | 19 | float size = uSize; 20 | 21 | float aspectY = max(uResolution.y/uResolution.x,1.); 22 | float aspectX = max(uResolution.x/uResolution.y,1.); 23 | 24 | vec2 sceneUvs = vec2( 25 | floor(vUv.x * size*aspectX)/(size*aspectX), 26 | floor(vUv.y * size*aspectY)/(size*aspectY) 27 | ); 28 | vec2 newUv = vec2( 29 | mod(vUv.x * size*aspectX,1.), 30 | mod(vUv.y * size*aspectY,1.) 31 | ); 32 | 33 | 34 | vec2 finalUvs = newUv; 35 | 36 | 37 | vec4 baseTexel = texture2D(tDiffuse,vUv); 38 | vec4 texel = texture2D( tDiffuse, sceneUvs ); 39 | 40 | float textureAspect = uTextureResolution.y/uTextureResolution.x; 41 | finalUvs.x*=textureAspect; 42 | 43 | //float offset = floor(texel.r*(1./textureAspect)); 44 | float offset = floor(clamp(texel.r,0.,1.)*((1./textureAspect)-1.)); 45 | 46 | finalUvs.x+=offset*textureAspect; 47 | vec4 char = texture2D(uTexture,finalUvs); 48 | 49 | 50 | 51 | gl_FragColor = (1.-step(0.5,uShowAscii))*baseTexel + (step(0.5,uShowAscii))*char; 52 | 53 | } -------------------------------------------------------------------------------- /src/style.css: -------------------------------------------------------------------------------- 1 | html, 2 | body, 3 | div, 4 | span, 5 | applet, 6 | object, 7 | iframe, 8 | h1, 9 | h2, 10 | h3, 11 | h4, 12 | h5, 13 | h6, 14 | p, 15 | blockquote, 16 | pre, 17 | a, 18 | abbr, 19 | acronym, 20 | address, 21 | big, 22 | cite, 23 | code, 24 | del, 25 | dfn, 26 | em, 27 | img, 28 | ins, 29 | kbd, 30 | q, 31 | s, 32 | samp, 33 | small, 34 | strike, 35 | strong, 36 | sub, 37 | sup, 38 | tt, 39 | var, 40 | b, 41 | u, 42 | i, 43 | center, 44 | dl, 45 | dt, 46 | dd, 47 | ol, 48 | ul, 49 | li, 50 | fieldset, 51 | form, 52 | label, 53 | legend, 54 | table, 55 | caption, 56 | tbody, 57 | tfoot, 58 | thead, 59 | tr, 60 | th, 61 | td, 62 | article, 63 | aside, 64 | canvas, 65 | details, 66 | embed, 67 | figure, 68 | figcaption, 69 | footer, 70 | header, 71 | hgroup, 72 | menu, 73 | nav, 74 | output, 75 | ruby, 76 | section, 77 | summary, 78 | time, 79 | mark, 80 | audio, 81 | video { 82 | margin: 0; 83 | padding: 0; 84 | border: 0; 85 | font-size: 100%; 86 | font: inherit; 87 | vertical-align: baseline; 88 | } 89 | /* HTML5 display-role reset for older browsers */ 90 | article, 91 | aside, 92 | details, 93 | figcaption, 94 | figure, 95 | footer, 96 | header, 97 | hgroup, 98 | menu, 99 | nav, 100 | section { 101 | display: block; 102 | } 103 | body { 104 | line-height: 1; 105 | } 106 | ol, 107 | ul { 108 | list-style: none; 109 | } 110 | blockquote, 111 | q { 112 | quotes: none; 113 | } 114 | blockquote:before, 115 | blockquote:after, 116 | q:before, 117 | q:after { 118 | content: ''; 119 | content: none; 120 | } 121 | table { 122 | border-collapse: collapse; 123 | border-spacing: 0; 124 | } 125 | 126 | #webgl { 127 | position: fixed; 128 | inset: 0; 129 | top: 0; 130 | left: 0; 131 | background: rgb(30, 30, 30); 132 | } 133 | -------------------------------------------------------------------------------- /src/types/types.ts: -------------------------------------------------------------------------------- 1 | export interface Size { 2 | width: number 3 | height: number 4 | } 5 | 6 | export interface Dimensions { 7 | width: number 8 | height: number 9 | pixelRatio: number 10 | } 11 | 12 | export interface Position { 13 | x: number 14 | y: number 15 | } 16 | -------------------------------------------------------------------------------- /src/utils/ascii-effect.ts: -------------------------------------------------------------------------------- 1 | import { ShaderPass } from 'three/addons/postprocessing/ShaderPass.js' 2 | import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js' 3 | import asciiFragment from '../../src/shaders/ascii/ascii.glsl' 4 | import * as THREE from 'three' 5 | 6 | export default class AsciiEffect { 7 | composer: EffectComposer 8 | asciiPass: ShaderPass 9 | shader: { 10 | name: string 11 | uniforms: { [name: string]: { value: any } } 12 | vertexShader: string 13 | fragmentShader: string 14 | } 15 | canvas: HTMLCanvasElement 16 | ctx: CanvasRenderingContext2D 17 | characters: string 18 | 19 | constructor() { 20 | //provide a power of 2 number of characters 21 | //8 22 | //16 23 | //32 24 | //64 25 | 26 | //this.characters = " .`-,:;'_~^=+<>i!lI?/|()1{}[]rcvuxzjftnLYJCVoZUwXhkmOa*#MW&8%B@$" //64 27 | this.characters = " .-:'~=