diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..30fd2a8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,64 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Typescript v1 declaration files +typings/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env + +# next.js build output +.next + +dist/bundle.js +dist/bundle.js.map \ No newline at end of file diff --git a/1.jpg b/1.jpg new file mode 100644 index 0000000..557edbc Binary files /dev/null and b/1.jpg differ diff --git a/2.png b/2.png new file mode 100644 index 0000000..0a79fc5 Binary files /dev/null and b/2.png differ diff --git a/3.jpg b/3.jpg new file mode 100644 index 0000000..2eeb364 Binary files /dev/null and b/3.jpg differ diff --git a/README.md b/README.md index 2859b45..2432956 100644 --- a/README.md +++ b/README.md @@ -1,117 +1,161 @@ -# Final Project! +# Greeble Generator based on WebGL -This is it! The culmination of your procedural graphics experience this semester. For your final project, we'd like to give you the time and space to explore a topic of your choosing. You may choose any topic you please, so long as you vet the topic and scope with an instructor or TA. We've provided some suggestions below. The scope of your project should be roughly 1.5 homework assignments). To help structure your time, we're breaking down the project into 4 milestones: +Team: San Jewell and Yilin Liu -## Project planning: Design Doc (due 11/9) -Before submitting your first milestone, _you must get your project idea and scope approved by Rachel, Adam or a TA._ +- [Video Demo](https://clipchamp.com/watch/Pm6bPs0cFJ6) -### Design Doc -Start off by forking this repository. In your README, write a design doc to outline your project goals and implementation plan. It must include the following sections: +- [Live Demo](https://cis566-greeble-pyramid.netlify.app/) + +## Final submission (due 12/5) +|![](/images/clip2.gif) +|:-------:| +Greeble Extrution Variations + + +|![](/images/clip3.gif) +|:-------:| +Various Rows & Columns + + +We implemented a SDF-based greeble pyramid generator using WebGL. We handcrafted SDF for symbols + +|![](/images/final-ui.png) +|:-------:| + UI Options: In "Greeble Control" folder, users can tweak parameters to adjust the greeble generations. In "Animation" folder, users can animate the camera to automatically pan around the pyramid. + + +![](/images/final1.png) + +| Symbol | Image | +| ----------- | ----------- | +| Cross Symbol | ![](/images/symbol1.png) | +| Flake Symbol | ![](/images/symbol2.png) | +| Line Symbol | ![](/images/symbol3.png) | +| Circle Symbol | ![](/images/symbol4.png) | + + + + +## Final features + +It should be stated this was more of a engineering / code challenge rather than a overall beauty achieveing goal. It is modeled entirely with SDFs and frequently broke webGL (more on that later). The high-level project is an attempt to generate greebles of a certain theme. We ended up sticking with the triangles theme by using a pyramid of the base shape. The project can generate an interesting looking shape. It is more of a toy to enjoy messing with, and might be a cool asset to use in a game or cutscene. In general it can be adjusted in the following ways: + +- The overall maximum extrusion depth of all of the triangles on the surface can be adjusted +- The depth multiplier below and above the surface can be independently adjusted. This allows concave and convex triangles or a mix of both. +- The scale of the triangles can be adjusted, so that small triangles or overlapping triangles can be achieved to control the amount of 'busyness' on the surface. +- The number of triangles ('rows') can be adjusted. This will exponentially create a more complex looking surface. +- There was a feature to adjust the number of symbols cut into each triangle, however this created loop-unrolling errors in some webGL implementations, so it is commented out and set to 1 for the purposes of the demo. +- There were variables built in to 'animate' the randomness variables of the surface over time, however, this did not actually end up seeming very useful / good looking, so scrapped the idea. + +There is an animated camera which is useful for easily observing all of the randomness of the creation conveiniently. + +## Problems, rants, and scrapped features + +The project, while not a complete dissappointment, involved a lot of dead ends. + +- There was some effort directed towards a third geometry element on the surface: "handlebar" components that could travel randomly from one triangle center to another without overlapping. However the math with regard to the SDFs ended up being much more complex in the context of how the other dimensions of the triangle face were arranged and needed to be scrapped +- There are a lot of performance problems to make the creator usable at a greater resolution especially with more rows. We only had the time to implement basic optimizations and so better demos were not created +- There was a desire to create a hybrid rendering system to trace both signed distance functions along with pre-generated signed distance fields. This would allow using mesh-based or vector based objects in the scene using a library such as https://pypi.org/project/mesh-to-sdf/ The reason that we wanted to do this was to use actual hieroglyph symbols available in unicode. **The vast majority of this project is completed**, unfortunately, due to an unfamiliarity with webGL, the pipeline for passing the fields was made around uniform vectors. For testing, this seemed to work when using a debugging field of size 8x8, however, as soon as the field was increased to a more realistic size, webGL broke, as it only allows a total number of 1024 uniform floats. After further research we found that this problem can be hacked around by using textures to pass in arrays, however, the boilerplate was so large that we ran out of time to make it realistic. You can see the sample pyramid render using the 8x8x8 field below, as well as the symbol shapes we were hoping to use. + +Unicode Symbols | Can be easily imported into blender +:-------------------------:|:-------------------------: +![](images/wiki_symbols.png) | ![](images/blender_symbols.png) + +8x8x8 low resolution test field render | +:-------------------------:| +![](images/lowres.png) | -#### Introduction -- What motivates your project? -#### Goal -- What do you intend to achieve with this project? +## Design Doc -#### Inspiration/reference: -- You must have some form of reference material for your final project. Your reference may be a research paper, a blog post, some artwork, a video, another class at Penn, etc. -- Include in your design doc links to and images of your reference material. +### Introduction +- I have always been interested in the lore, theocracy, language, and most importantly distinctive artic style of the civilization that thrived on the banks of the Nile Millenia ago: Ancient Egypt. I had a few ideas of how I might apply my interest in this theme in the realm of proceduralism. -#### Specification: -- Outline the main features of your project. +### Goal +- Design a greeble generator both: + + 1) designed to work well on a few specific types of themed structure geometry. + 2) consisting themselves at least partially of recognizable Egyptian themes. -#### Techniques: -- What are the main technical/algorithmic tools you’ll be using? Give an overview, citing specific papers/articles. +### Inspiration/reference: +- In reference to goal #1, these will probably have minimal or no procedural elements. Perhaps a few different base dimensions or heights, or if short on time, the buildings will be completely hand defined. Their shapes are usually relatively simple to model. See a few examples of common structures in this image. In the scope of this project I would probably start with the obelisk or pyramid shapes, possible exploring the larger temple styles if time permits. -#### Design: -- How will your program fit together? Make a simple free-body diagram illustrating the pieces. +![](3.jpg) -#### Timeline: -- Create a week-by-week set of milestones for each person in your group. Make sure you explicitly outline what each group member's duties will be. +- The main goal is #2, that is, generating greebles to fit properly and look pleasant on the surfaces of these structures. I found a few inspiration images for this technique online. The first demonstrates height based greebles divided into a triangle mesh. The second demonstrates the possibility for building lighting on a themed structure. + +| Reference 1 | Reference 2 | +| ----------- | ----------- | +| ![](2.png) | ![](1.jpg) | + + +### Specification: +- For greebles + - be able to select a surface partition type, square or triangle? + - be able to select a scale for the "noise" + - be able to select some kind of mix ratio between generic geometric shapes (i.e. "star wars" greebles) and themed shapes, such as extruded hieroglyphs +- For structures + - be able to choose from one or more pre-defined stereotypical building styles + - (time permitting) be able to apply some kind of noise to generate variants of the chosen building shape + +### Techniques: +- [Procedural Greeble Tutorial](https://lindenreidblog.com/2017/12/13/procedural-greeble-tutorial/) by [Linden Reid](https://lindenreidblog.com/) + +In this tutorial, Linden introduces how he did the greeble effects. Put simply, to extrude a poly, we can create new verticies by translating the old verticies in the direction of the surface normal. + +For more realistic effects, we can add randomness to the extrusion scale and whether or not greeble is applied. + +![](greeble_tutorial.png) + +- [Voronoi Greeble Displacement: ShaderToy](https://www.shadertoy.com/view/NllyWf) by Shane + +In this shadertoy, Shane used a tailored Voronoi algorithm to drive the generation of greeble displacement. + +![](shader_toy_demo.png) + +### Design: + +The scene will consist of two main component, a background scene and a foreground geometry powered by greeble. + +![](diagram.png) + +### Timeline: + +| | San Jewell | Yilin Liu | +| --------------- | --------------- | --------------- | +| Milestone 1, 11/16| General Greeble Generation & Initial structure design | General Greeble Generation & Initial structure design | +| Milestone 2, 11/28| Second level of symbol theming, GUI options | Procedural Background, GUI options | +| Milestone 3, 12/5 | Optimization & Demo Scene Design | Documentation write-up & Demo Scene Design | Submit your Design doc as usual via pull request against this repository. + ## Milestone 1: Implementation part 1 (due 11/16) -Begin implementing your engine! Don't worry too much about polish or parameter tuning -- this week is about getting together the bulk of your generator implemented. By the end of the week, even if your visuals are crude, the majority of your generator's functionality should be done. -Put all your code in your forked repository. +For Milestone1, we worked on a tesselation-based method to divide our pyramid but did not hit the goals. Therefore, we recently switched to the SDF-based method, which is more intuitive. +### DONE +- Implemented the extrusion through a SDF-based method. +- Procedural sky with sun -Submission: Add a new section to your README titled: Milestone #1, which should include -- written description of progress on your project goals. If you haven't hit all your goals, what's giving you trouble? -- Examples of your generators output so far -We'll check your repository for updates. No need to create a new pull request. -## Milestone 3: Implementation part 2 (due 11/28) -We're over halfway there! This week should be about fixing bugs and extending the core of your generator. Make sure by the end of this week _your generator works and is feature complete._ Any core engine features that don't make it in this week should be cut! Don't worry if you haven't managed to exactly hit your goals. We're more interested in seeing proof of your development effort than knowing your planned everything perfectly. +### In Progress +- The greeble Algorithm -Put all your code in your forked repository. +### Screenshot +![](images/img1.png) -Submission: Add a new section to your README titled: Milestone #3, which should include -- written description of progress on your project goals. If you haven't hit all your goals, what did you have to cut and why? -- Detailed output from your generator, images, video, etc. -We'll check your repository for updates. No need to create a new pull request. +## Milestone 2: Implementation part 2 (due 11/28) -Come to class on the due date with a WORKING COPY of your project. We'll be spending time in class critiquing and reviewing your work so far. +### DONE -## Final submission (due 12/5) -Time to polish! Spen this last week of your project using your generator to produce beautiful output. Add textures, tune parameters, play with colors, play with camera animation. Take the feedback from class critques and use it to take your project to the next level. - -Submission: -- Push all your code / files to your repository -- Come to class ready to present your finished project -- Update your README with two sections - - final results with images and a live demo if possible - - post mortem: how did your project go overall? Did you accomplish your goals? Did you have to pivot? - -## Topic Suggestions - -### Create a generator in Houdini - -### A CLASSIC 4K DEMO -- In the spirit of the demo scene, create an animation that fits into a 4k executable that runs in real-time. Feel free to take inspiration from the many existing demos. Focus on efficiency and elegance in your implementation. -- Example: - - [cdak by Quite & orange](https://www.youtube.com/watch?v=RCh3Q08HMfs&list=PLA5E2FF8E143DA58C) - -### A RE-IMPLEMENTATION -- Take an academic paper or other pre-existing project and implement it, or a portion of it. -- Examples: - - [2D Wavefunction Collapse Pokémon Town](https://gurtd.github.io/566-final-project/) - - [3D Wavefunction Collapse Dungeon Generator](https://github.com/whaoran0718/3dDungeonGeneration) - - [Reaction Diffusion](https://github.com/charlesliwang/Reaction-Diffusion) - - [WebGL Erosion](https://github.com/LanLou123/Webgl-Erosion) - - [Particle Waterfall](https://github.com/chloele33/particle-waterfall) - - [Voxelized Bread](https://github.com/ChiantiYZY/566-final) - -### A FORGERY -Taking inspiration from a particular natural phenomenon or distinctive set of visuals, implement a detailed, procedural recreation of that aesthetic. This includes modeling, texturing and object placement within your scene. Does not need to be real-time. Focus on detail and visual accuracy in your implementation. -- Examples: - - [The Shrines](https://github.com/byumjin/The-Shrines) - - [Watercolor Shader](https://github.com/gracelgilbert/watercolor-stylization) - - [Sunset Beach](https://github.com/HanmingZhang/homework-final) - - [Sky Whales](https://github.com/WanruZhao/CIS566FinalProject) - - [Snail](https://www.shadertoy.com/view/ld3Gz2) - - [Journey](https://www.shadertoy.com/view/ldlcRf) - - [Big Hero 6 Wormhole](https://2.bp.blogspot.com/-R-6AN2cWjwg/VTyIzIQSQfI/AAAAAAAABLA/GC0yzzz4wHw/s1600/big-hero-6-disneyscreencaps.com-10092.jpg) - -### A GAME LEVEL -- Like generations of game makers before us, create a game which generates an navigable environment (eg. a roguelike dungeon, platforms) and some sort of goal or conflict (eg. enemy agents to avoid or items to collect). Aim to create an experience that will challenge players and vary noticeably in different playthroughs, whether that means procedural dungeon generation, careful resource management or an interesting AI model. Focus on designing a system that is capable of generating complex challenges and goals. -- Examples: - - [Rhythm-based Mario Platformer](https://github.com/sgalban/platformer-gen-2D) - - [Pokémon Ice Puzzle Generator](https://github.com/jwang5675/Ice-Puzzle-Generator) - - [Abstract Exploratory Game](https://github.com/MauKMu/procedural-final-project) - - [Tiny Wings](https://github.com/irovira/TinyWings) - - Spore - - Dwarf Fortress - - Minecraft - - Rogue - -### AN ANIMATED ENVIRONMENT / MUSIC VISUALIZER -- Create an environment full of interactive procedural animation. The goal of this project is to create an environment that feels responsive and alive. Whether or not animations are musically-driven, sound should be an important component. Focus on user interactions, motion design and experimental interfaces. -- Examples: - - [The Darkside](https://github.com/morganherrmann/thedarkside) - - [Music Visualizer](https://yuruwang.github.io/MusicVisualizer/) - - [Abstract Mesh Animation](https://github.com/mgriley/cis566_finalproj) - - [Panoramical](https://www.youtube.com/watch?v=gBTTMNFXHTk) - - [Bound](https://www.youtube.com/watch?v=aE37l6RvF-c) - -### YOUR OWN PROPOSAL -- You are of course welcome to propose your own topic . Regardless of what you choose, you and your team must research your topic and relevant techniques and come up with a detailed plan of execution. You will meet with some subset of the procedural staff before starting implementation for approval. +- The greeble algorithm. + +### In Progress + +- GUI options +- Better visuals + +### Screenshot +![](images/img2.png) + +![](images/img3.png) + +![](images/img_high_dimen.jpeg) diff --git a/diagram.png b/diagram.png new file mode 100644 index 0000000..65f7d56 Binary files /dev/null and b/diagram.png differ diff --git a/dist/index.html b/dist/index.html new file mode 100644 index 0000000..fbbe1d9 --- /dev/null +++ b/dist/index.html @@ -0,0 +1,20 @@ + + + + Greeble Generator | CIS 566 + + + + + + + diff --git a/gen_fields_from_mesh.py b/gen_fields_from_mesh.py new file mode 100644 index 0000000..0bde315 --- /dev/null +++ b/gen_fields_from_mesh.py @@ -0,0 +1,20 @@ +from mesh_to_sdf import mesh_to_voxels + +import trimesh +import skimage + +mesh = trimesh.load('pyramid.obj') + +voxels = mesh_to_voxels(mesh, 8, pad=True) + +import json + +sdfs = {'pyramid': voxels.tolist()} + +with open('src/rendering/gl/sdfs.json', 'w') as f: + json.dump(sdfs, f) + + +# vertices, faces, normals, _ = skimage.measure.marching_cubes(voxels, level=0) +# mesh = trimesh.Trimesh(vertices=vertices, faces=faces, vertex_normals=normals) +# mesh.show() \ No newline at end of file diff --git a/greeble_tutorial.png b/greeble_tutorial.png new file mode 100644 index 0000000..9edc8e6 Binary files /dev/null and b/greeble_tutorial.png differ diff --git a/images/blender_symbols.png b/images/blender_symbols.png new file mode 100644 index 0000000..b3bb9a9 Binary files /dev/null and b/images/blender_symbols.png differ diff --git a/images/blooper1.png b/images/blooper1.png new file mode 100644 index 0000000..f1964ca Binary files /dev/null and b/images/blooper1.png differ diff --git a/images/clip1.gif b/images/clip1.gif new file mode 100644 index 0000000..8d3cfe1 Binary files /dev/null and b/images/clip1.gif differ diff --git a/images/clip2.gif b/images/clip2.gif new file mode 100644 index 0000000..55a1b50 Binary files /dev/null and b/images/clip2.gif differ diff --git a/images/clip3.gif b/images/clip3.gif new file mode 100644 index 0000000..e41efab Binary files /dev/null and b/images/clip3.gif differ diff --git a/images/final-ui.png b/images/final-ui.png new file mode 100644 index 0000000..a59ce79 Binary files /dev/null and b/images/final-ui.png differ diff --git a/images/final1.png b/images/final1.png new file mode 100644 index 0000000..37375a8 Binary files /dev/null and b/images/final1.png differ diff --git a/images/img1.png b/images/img1.png new file mode 100644 index 0000000..1f4c870 Binary files /dev/null and b/images/img1.png differ diff --git a/images/img2.png b/images/img2.png new file mode 100644 index 0000000..dc0beda Binary files /dev/null and b/images/img2.png differ diff --git a/images/img3.png b/images/img3.png new file mode 100644 index 0000000..4898a5e Binary files /dev/null and b/images/img3.png differ diff --git a/images/img_high_dimen.jpeg b/images/img_high_dimen.jpeg new file mode 100644 index 0000000..5a7b971 Binary files /dev/null and b/images/img_high_dimen.jpeg differ diff --git a/images/lowres.png b/images/lowres.png new file mode 100644 index 0000000..bd9d3f9 Binary files /dev/null and b/images/lowres.png differ diff --git a/images/symbol1.png b/images/symbol1.png new file mode 100644 index 0000000..e505244 Binary files /dev/null and b/images/symbol1.png differ diff --git a/images/symbol2.png b/images/symbol2.png new file mode 100644 index 0000000..c00edc4 Binary files /dev/null and b/images/symbol2.png differ diff --git a/images/symbol3.png b/images/symbol3.png new file mode 100644 index 0000000..814512a Binary files /dev/null and b/images/symbol3.png differ diff --git a/images/symbol4.png b/images/symbol4.png new file mode 100644 index 0000000..c4bb771 Binary files /dev/null and b/images/symbol4.png differ diff --git a/images/wiki_symbols.png b/images/wiki_symbols.png new file mode 100644 index 0000000..40d334e Binary files /dev/null and b/images/wiki_symbols.png differ diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..e1a47a3 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,3120 @@ +{ + "requires": true, + "lockfileVersion": 1, + "dependencies": { + "3d-view": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/3d-view/-/3d-view-2.0.1.tgz", + "integrity": "sha512-YSLRHXNpSziaaiK2R0pI5+JKguoJVbtWmIv9YyBFtl0+q42kQwJB/JUulbFR/1zYFm58ifjKQ6kVdgZ6tyKtCA==", + "requires": { + "matrix-camera-controller": "^2.1.1", + "orbit-camera-controller": "^4.0.0", + "turntable-camera-controller": "^3.0.0" + } + }, + "3d-view-controls": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/3d-view-controls/-/3d-view-controls-2.2.2.tgz", + "integrity": "sha512-WL0u3PN41lEx/4qvKqV6bJlweUYoW18FXMshW/qHb41AVdZxDReLoJNGYsI7x6jf9bYelEF62BJPQmO7yEnG2w==", + "requires": { + "3d-view": "^2.0.0", + "has-passive-events": "^1.0.0", + "mouse-change": "^1.1.1", + "mouse-event-offset": "^3.0.2", + "mouse-wheel": "^1.0.2", + "right-now": "^1.0.0" + } + }, + "@discoveryjs/json-ext": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.3.tgz", + "integrity": "sha512-Fxt+AfXgjMoin2maPIYzFZnQjAXjAL0PHscM5pRTtatFqB+vZxAM9tLp2Optnuw3QOQC40jTNeGYFOMvyf7v9g==", + "dev": true + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@types/dat.gui": { + "version": "0.7.7", + "resolved": "https://registry.npmjs.org/@types/dat.gui/-/dat.gui-0.7.7.tgz", + "integrity": "sha512-CxLCme0He5Jk3uQwfO/fGZMyNhb/ypANzqX0yU9lviBQMlen5SOvQTBQ/Cd9x5mFlUAK5Tk8RgvTyLj1nYkz+w==", + "dev": true + }, + "@types/eslint": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.28.0.tgz", + "integrity": "sha512-07XlgzX0YJUn4iG1ocY4IX9DzKSmMGUs6ESKlxWhZRaa0fatIWaHWUVapcuGa8r5HFnTqzj+4OCjd5f7EZ/i/A==", + "dev": true, + "requires": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "@types/eslint-scope": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.1.tgz", + "integrity": "sha512-SCFeogqiptms4Fg29WpOTk5nHIzfpKCemSN63ksBQYKTcXoJEmJagV+DhVmbapZzY4/5YaOV1nZwrsU79fFm1g==", + "dev": true, + "requires": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "@types/estree": { + "version": "0.0.50", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.50.tgz", + "integrity": "sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw==", + "dev": true + }, + "@types/http-proxy": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.7.tgz", + "integrity": "sha512-9hdj6iXH64tHSLTY+Vt2eYOGzSogC+JQ2H7bdPWkuh7KXP5qLllWx++t+K9Wk556c3dkDdPws/SpMRi0sdCT1w==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/json-schema": { + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", + "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", + "dev": true + }, + "@types/node": { + "version": "9.6.61", + "resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.61.tgz", + "integrity": "sha512-/aKAdg5c8n468cYLy2eQrcR5k6chlbNwZNGUj3TboyPa2hcO2QAJcfymlqPzMiRj8B6nYKXjzQz36minFE0RwQ==", + "dev": true + }, + "@types/retry": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz", + "integrity": "sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==", + "dev": true + }, + "@types/webgl2": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@types/webgl2/-/webgl2-0.0.6.tgz", + "integrity": "sha512-50GQhDVTq/herLMiqSQkdtRu+d5q/cWHn4VvKJtrj4DJAjo1MNkWYa2MA41BaBO1q1HgsUjuQvEOk0QHvlnAaQ==", + "dev": true + }, + "@webassemblyjs/ast": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", + "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", + "dev": true, + "requires": { + "@webassemblyjs/helper-numbers": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", + "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", + "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", + "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", + "dev": true + }, + "@webassemblyjs/helper-numbers": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", + "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", + "dev": true, + "requires": { + "@webassemblyjs/floating-point-hex-parser": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", + "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", + "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", + "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", + "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", + "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", + "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/helper-wasm-section": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-opt": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "@webassemblyjs/wast-printer": "1.11.1" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", + "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", + "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", + "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", + "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "@webpack-cli/configtest": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.0.4.tgz", + "integrity": "sha512-cs3XLy+UcxiP6bj0A6u7MLLuwdXJ1c3Dtc0RkKg+wiI1g/Ti1om8+/2hc2A2B60NbBNAbMgyBMHvyymWm/j4wQ==", + "dev": true + }, + "@webpack-cli/info": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.3.0.tgz", + "integrity": "sha512-ASiVB3t9LOKHs5DyVUcxpraBXDOKubYu/ihHhU+t1UPpxsivg6Od2E2qU4gJCekfEddzRBzHhzA/Acyw/mlK/w==", + "dev": true, + "requires": { + "envinfo": "^7.7.3" + } + }, + "@webpack-cli/serve": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.5.2.tgz", + "integrity": "sha512-vgJ5OLWadI8aKjDlOH3rb+dYyPd2GTZuQC/Tihjct6F9GpXGZINo3Y/IVuZVTM1eDQB+/AOsjPUWH/WySDaXvw==", + "dev": true + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dev": true, + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "acorn": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.5.0.tgz", + "integrity": "sha512-yXbYeFy+jUuYd3/CDcg2NkIYE991XYX/bje7LmjJigUciaeO1JR4XxXgCIV1/Zc/dRuFEyw1L0pbA+qynJkW5Q==", + "dev": true + }, + "acorn-import-assertions": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.7.6.tgz", + "integrity": "sha512-FlVvVFA1TX6l3lp8VjDnYYq7R1nyW6x3svAt4nDgrWQ9SBaSh9CnbwgSUTasgfNfOG5HlM1ehugCvM+hjo56LA==", + "dev": true + }, + "aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true + }, + "ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "dev": true + }, + "ansi-regex": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.0.tgz", + "integrity": "sha512-tAaOSrWCHF+1Ear1Z4wnJCXA9GGox4K6Ic85a5qalES2aeEwQGr7UC93mwef49536PkCYjzkp0zIxfFvexJ6zQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", + "dev": true + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", + "dev": true + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true + }, + "binary-search-bounds": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/binary-search-bounds/-/binary-search-bounds-2.0.5.tgz", + "integrity": "sha512-H0ea4Fd3lS1+sTEB2TgcLoK21lLhwEJzlQv3IN47pJS976Gx4zoWe0ak3q+uYh60ppQxg9F16Ri4tS1sfD4+jA==" + }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dev": true, + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "dependencies": { + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true + } + } + }, + "bonjour": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", + "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", + "dev": true, + "requires": { + "array-flatten": "^2.1.0", + "deep-equal": "^1.0.1", + "dns-equal": "^1.0.0", + "dns-txt": "^2.0.2", + "multicast-dns": "^6.0.1", + "multicast-dns-service-types": "^1.1.0" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "browserslist": { + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.17.0.tgz", + "integrity": "sha512-g2BJ2a0nEYvEFQC208q8mVAhfNwpZ5Mu8BwgtCdZKO3qx98HChmeg448fPdUzld8aFmfLgVh7yymqV+q1lJZ5g==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001254", + "colorette": "^1.3.0", + "electron-to-chromium": "^1.3.830", + "escalade": "^3.1.1", + "node-releases": "^1.1.75" + } + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "buffer-indexof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", + "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", + "dev": true + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "dev": true + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "caniuse-lite": { + "version": "1.0.30001255", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001255.tgz", + "integrity": "sha512-F+A3N9jTZL882f/fg/WWVnKSu6IOo3ueLz4zwaOPbPYHNmM/ZaDUyzyJwS1mZhX7Ex5jqTyW599Gdelh5PDYLQ==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "chokidar": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", + "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true + }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true + }, + "clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "colorette": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", + "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==", + "dev": true + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "requires": { + "mime-db": ">= 1.43.0 < 2" + } + }, + "compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dev": true, + "requires": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "connect-history-api-fallback": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", + "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", + "dev": true + }, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "dev": true + }, + "cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "dev": true + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "cubic-hermite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cubic-hermite/-/cubic-hermite-1.0.0.tgz", + "integrity": "sha1-hOOy8nKzFFToOTuZu2rtRRaMFOU=" + }, + "dat.gui": { + "version": "0.7.7", + "resolved": "https://registry.npmjs.org/dat.gui/-/dat.gui-0.7.7.tgz", + "integrity": "sha512-sRl/28gF/XRC5ywC9I4zriATTsQcpSsRG7seXCPnTkK8/EQMIbCu5NPMpICLGxX9ZEUvcXR3ArLYCtgreFoMDw==" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-equal": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", + "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", + "dev": true, + "requires": { + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.1", + "is-regex": "^1.0.4", + "object-is": "^1.0.1", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.2.0" + } + }, + "default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "dev": true, + "requires": { + "execa": "^5.0.0" + } + }, + "define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "del": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/del/-/del-6.0.0.tgz", + "integrity": "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==", + "dev": true, + "requires": { + "globby": "^11.0.1", + "graceful-fs": "^4.2.4", + "is-glob": "^4.0.1", + "is-path-cwd": "^2.2.0", + "is-path-inside": "^3.0.2", + "p-map": "^4.0.0", + "rimraf": "^3.0.2", + "slash": "^3.0.0" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, + "dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=", + "dev": true + }, + "dns-packet": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.4.tgz", + "integrity": "sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA==", + "dev": true, + "requires": { + "ip": "^1.1.0", + "safe-buffer": "^5.0.1" + } + }, + "dns-txt": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", + "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", + "dev": true, + "requires": { + "buffer-indexof": "^1.0.0" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "electron-to-chromium": { + "version": "1.3.832", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.832.tgz", + "integrity": "sha512-x7lO8tGoW0CyV53qON4Lb5Rok9ipDelNdBIAiYUZ03dqy4u9vohMM1qV047+s/hiyJiqUWX/3PNwkX3kexX5ig==", + "dev": true + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true + }, + "enhanced-resolve": { + "version": "5.8.2", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.8.2.tgz", + "integrity": "sha512-F27oB3WuHDzvR2DOGNTaYy0D5o0cnrv8TeI482VM4kYgQd/FT9lUQwuNsJ0oOHtBUq7eiW5ytqzp7nBFknL+GA==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + } + }, + "envinfo": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", + "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==", + "dev": true + }, + "es-module-lexer": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.7.1.tgz", + "integrity": "sha512-MgtWFl5No+4S3TmhDmCz2ObFGm6lEpTnzbQi+Dd+pw4mlTIZTmM2iAs5gRlmx5zS9luzobCSBSI90JM/1/JgOw==", + "dev": true + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "dev": true + }, + "eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true + }, + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + } + }, + "express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "dev": true, + "requires": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "dev": true + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-glob": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", + "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fastest-levenshtein": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", + "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", + "dev": true + }, + "fastq": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.12.0.tgz", + "integrity": "sha512-VNX0QkHK3RsXVKr9KrlUv/FoTa0NdbYoHHl7uXHv2rzyHSlxjdNAKug2twd9luJxpcyNeAgf5iPPMutJO67Dfg==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dev": true, + "requires": { + "websocket-driver": ">=0.5.1" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "filtered-vector": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/filtered-vector/-/filtered-vector-1.2.5.tgz", + "integrity": "sha512-5Vu6wdtQJ1O2nRmz39dIr9m3hEDq1skYby5k1cJQdNWK4dMgvYcUEiA/9j7NcKfNZ5LGxn8w2LSLiigyH7pTAw==", + "requires": { + "binary-search-bounds": "^2.0.0", + "cubic-hermite": "^1.0.0" + } + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "follow-redirects": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.3.tgz", + "integrity": "sha512-3MkHxknWMUtb23apkgz/83fDoe+y+qr0TdgacGIA7bew+QLBo3vdgEN2xEsuXNivpFy4CyDhBBZnNZOtalmenw==", + "dev": true + }, + "forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "dev": true + }, + "fs": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.2.tgz", + "integrity": "sha1-4fJE7zkzwbKmS9R5kTYGDQ9ZFPg=", + "dev": true + }, + "fs-monkey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz", + "integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true + }, + "gl-mat3": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gl-mat3/-/gl-mat3-1.0.0.tgz", + "integrity": "sha1-iWMyGcpCk3mha5GF2V1BcTRTuRI=" + }, + "gl-mat4": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gl-mat4/-/gl-mat4-1.2.0.tgz", + "integrity": "sha512-sT5C0pwB1/e9G9AvAoLsoaJtbMGjfd/jfxo8jMCKqYYEnjZuFvqV5rehqar0538EmssjdDeiEWnKyBSTw7quoA==" + }, + "gl-matrix": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.3.0.tgz", + "integrity": "sha512-COb7LDz+SXaHtl/h4LeaFcNdJdAQSDeVqjiIihSXNrkWObZLhDI4hIkZC11Aeqp7bcE72clzB0BnDXr2SmslRA==" + }, + "gl-quat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gl-quat/-/gl-quat-1.0.0.tgz", + "integrity": "sha1-CUXskjOG9FMpvl3DV7HIwtR1hsU=", + "requires": { + "gl-mat3": "^1.0.0", + "gl-vec3": "^1.0.3", + "gl-vec4": "^1.0.0" + } + }, + "gl-vec3": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/gl-vec3/-/gl-vec3-1.1.3.tgz", + "integrity": "sha512-jduKUqT0SGH02l8Yl+mV1yVsDfYgQAJyXGxkJQGyxPLHRiW25DwVIRPt6uvhrEMHftJfqhqKthRcyZqNEl9Xdw==" + }, + "gl-vec4": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gl-vec4/-/gl-vec4-1.0.1.tgz", + "integrity": "sha1-l9loeCgbFLUyy84QF4Xf0cs0CWQ=" + }, + "glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "globby": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", + "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + } + }, + "graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", + "dev": true + }, + "handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "has-passive-events": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-passive-events/-/has-passive-events-1.0.0.tgz", + "integrity": "sha512-2vSj6IeIsgvsRMyeQ0JaCX5Q3lX4zMn5HpoVc7MEhQ6pv8Iq9rsXjsp+E5ZwaT7T0xhMT0KmU8gtt1EFVdbJiw==", + "requires": { + "is-browser": "^2.0.1" + } + }, + "has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true + }, + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, + "hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "html-entities": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz", + "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==", + "dev": true + }, + "http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", + "dev": true + }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } + } + }, + "http-parser-js": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.3.tgz", + "integrity": "sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg==", + "dev": true + }, + "http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "requires": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, + "http-proxy-middleware": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.1.tgz", + "integrity": "sha512-cfaXRVoZxSed/BmkA7SwBVNI9Kj7HFltaE5rqYOub5kWzWZ+gofV2koVN1j2rMW7pEfSSlCHGJ31xmuyFyfLOg==", + "dev": true, + "requires": { + "@types/http-proxy": "^1.17.5", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + } + }, + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true + }, + "import-local": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz", + "integrity": "sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA==", + "dev": true, + "requires": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + } + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "internal-ip": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-6.2.0.tgz", + "integrity": "sha512-D8WGsR6yDt8uq7vDMu7mjcR+yRMm3dW8yufyChmszWRjcSHuxLBkR3GdS2HZAjodsaGuCvXeEJpueisXJULghg==", + "dev": true, + "requires": { + "default-gateway": "^6.0.0", + "ipaddr.js": "^1.9.1", + "is-ip": "^3.1.0", + "p-event": "^4.2.0" + }, + "dependencies": { + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true + } + } + }, + "interpret": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", + "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", + "dev": true + }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "dev": true + }, + "ip-regex": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz", + "integrity": "sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==", + "dev": true + }, + "ipaddr.js": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz", + "integrity": "sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==", + "dev": true + }, + "is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-browser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-browser/-/is-browser-2.1.0.tgz", + "integrity": "sha512-F5rTJxDQ2sW81fcfOR1GnCXT6sVJC104fCyfj+mjpwNEwaPYSn5fte5jiHmBg3DHsIoL/l8Kvw5VN5SsTRcRFQ==" + }, + "is-core-module": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.6.0.tgz", + "integrity": "sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-ip": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-ip/-/is-ip-3.1.0.tgz", + "integrity": "sha512-35vd5necO7IitFPjd/YBeqwWnyDWbuLH9ZXQdMfDA8TEo7pv5X8yfrvVO3xbJbLUlERCMvf6X0hTUamQxCYJ9Q==", + "dev": true, + "requires": { + "ip-regex": "^4.0.0" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "dev": true + }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true + }, + "is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "dev": true + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true + }, + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "requires": { + "is-docker": "^2.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "jest-worker": { + "version": "27.1.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.1.1.tgz", + "integrity": "sha512-XJKCL7tu+362IUYTWvw8+3S75U7qMiYiRU6u5yqscB48bTvzwN6i8L/7wVTXiFLwkRsxARNM7TISnTvcgv9hxA==", + "dev": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "loader-runner": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", + "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", + "dev": true + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dev": true, + "requires": { + "p-defer": "^1.0.0" + } + }, + "mat4-decompose": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mat4-decompose/-/mat4-decompose-1.0.4.tgz", + "integrity": "sha1-ZetP451wh496RE60Yk1S9+frL68=", + "requires": { + "gl-mat4": "^1.0.1", + "gl-vec3": "^1.0.2" + } + }, + "mat4-interpolate": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mat4-interpolate/-/mat4-interpolate-1.0.4.tgz", + "integrity": "sha1-Vf/p6zw1KV4sDVqfdyXZBoqJ/3Q=", + "requires": { + "gl-mat4": "^1.0.1", + "gl-vec3": "^1.0.2", + "mat4-decompose": "^1.0.3", + "mat4-recompose": "^1.0.3", + "quat-slerp": "^1.0.0" + } + }, + "mat4-recompose": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mat4-recompose/-/mat4-recompose-1.0.4.tgz", + "integrity": "sha1-OVPCMP8kc9x3LuAUpSySXPgbDk0=", + "requires": { + "gl-mat4": "^1.0.1" + } + }, + "matrix-camera-controller": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/matrix-camera-controller/-/matrix-camera-controller-2.1.4.tgz", + "integrity": "sha512-zsPGPONclrKSImNpqqKDTcqFpWLAIwMXEJtCde4IFPOw1dA9udzFg4HOFytOTosOFanchrx7+Hqq6glLATIxBA==", + "requires": { + "binary-search-bounds": "^2.0.0", + "gl-mat4": "^1.1.2", + "gl-vec3": "^1.0.3", + "mat4-interpolate": "^1.0.3" + } + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true + }, + "mem": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/mem/-/mem-8.1.1.tgz", + "integrity": "sha512-qFCFUDs7U3b8mBDPyz5EToEKoAkgCzqquIgi9nkkR9bixxOVOre+09lbuH7+9Kn2NFpm56M3GUWVbU2hQgdACA==", + "dev": true, + "requires": { + "map-age-cleaner": "^0.1.3", + "mimic-fn": "^3.1.0" + }, + "dependencies": { + "mimic-fn": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.1.0.tgz", + "integrity": "sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==", + "dev": true + } + } + }, + "memfs": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.2.4.tgz", + "integrity": "sha512-2mDCPhuduRPOxlfgsXF9V+uqC6Jgz8zt/bNe4d4W7d5f6pCzHrWkxLNr17jKGXd4+j2kQNsAG2HARPnt74sqVQ==", + "dev": true, + "requires": { + "fs-monkey": "1.0.3" + } + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true + }, + "micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, + "mime-db": { + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.49.0.tgz", + "integrity": "sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA==", + "dev": true + }, + "mime-types": { + "version": "2.1.32", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.32.tgz", + "integrity": "sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A==", + "dev": true, + "requires": { + "mime-db": "1.49.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "mouse-change": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/mouse-change/-/mouse-change-1.4.0.tgz", + "integrity": "sha1-wrd+W/o0pDzhRFyBV6Tk3JiVwU8=", + "requires": { + "mouse-event": "^1.0.0" + } + }, + "mouse-event": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/mouse-event/-/mouse-event-1.0.5.tgz", + "integrity": "sha1-s3ie23EJmX1aky0dAdqhVDpQFzI=" + }, + "mouse-event-offset": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mouse-event-offset/-/mouse-event-offset-3.0.2.tgz", + "integrity": "sha1-39hqbiSMa6jK1TuQXVA3ogY+mYQ=" + }, + "mouse-wheel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mouse-wheel/-/mouse-wheel-1.2.0.tgz", + "integrity": "sha1-bSkDseqPtI5h8bU7kDZ3PwQs21w=", + "requires": { + "right-now": "^1.0.0", + "signum": "^1.0.0", + "to-px": "^1.0.1" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "multicast-dns": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", + "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", + "dev": true, + "requires": { + "dns-packet": "^1.3.1", + "thunky": "^1.0.2" + } + }, + "multicast-dns-service-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", + "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", + "dev": true + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "dev": true + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node-forge": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", + "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==", + "dev": true + }, + "node-releases": { + "version": "1.1.75", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.75.tgz", + "integrity": "sha512-Qe5OUajvqrqDSy6wrWFmMwfJ0jVgwiw4T3KqmbTcZ62qW0gQkheXYhcFM1+lOVcGUoRxcEcfyvFMAnDgaF1VWw==", + "dev": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "object-is": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "open": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/open/-/open-8.2.1.tgz", + "integrity": "sha512-rXILpcQlkF/QuFez2BJDf3GsqpjGKbkUUToAIGo9A0Q6ZkoSGogZJulrUdwRkrAsoQvoZsrjCYt8+zblOk7JQQ==", + "dev": true, + "requires": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + } + }, + "orbit-camera-controller": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/orbit-camera-controller/-/orbit-camera-controller-4.0.0.tgz", + "integrity": "sha1-bis28OeHhmPDMPUNqbfOaGwncAU=", + "requires": { + "filtered-vector": "^1.2.1", + "gl-mat4": "^1.0.3" + } + }, + "p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", + "dev": true + }, + "p-event": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/p-event/-/p-event-4.2.0.tgz", + "integrity": "sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ==", + "dev": true, + "requires": { + "p-timeout": "^3.1.0" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + }, + "dependencies": { + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + } + } + }, + "p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "p-retry": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.1.tgz", + "integrity": "sha512-e2xXGNhZOZ0lfgR9kL34iGlU8N/KO0xZnQxVEwdeOvpqNDQfdnxIYizvWtK8RglUa3bGqI8g0R/BdfzLMxRkiA==", + "dev": true, + "requires": { + "@types/retry": "^0.12.0", + "retry": "^0.13.1" + } + }, + "p-timeout": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", + "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", + "dev": true, + "requires": { + "p-finally": "^1.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "parse-unit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-unit/-/parse-unit-1.0.1.tgz", + "integrity": "sha1-fhu21b7zh0wo45JSaiVBFwKR7s8=" + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true + }, + "path": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/path/-/path-0.11.14.tgz", + "integrity": "sha1-y8dWk1XLPIOv60rOQ+z/lSMeWn0=", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", + "dev": true + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "picomatch": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "dev": true + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + }, + "portfinder": { + "version": "1.0.28", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", + "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", + "dev": true, + "requires": { + "async": "^2.6.2", + "debug": "^3.1.1", + "mkdirp": "^0.5.5" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + } + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "requires": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "dependencies": { + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true + } + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true + }, + "quat-slerp": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/quat-slerp/-/quat-slerp-1.0.1.tgz", + "integrity": "sha1-K6oVzjprvcMkHZcusXKDE57Wnyk=", + "requires": { + "gl-quat": "^1.0.0" + } + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true + }, + "raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "dev": true, + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "dependencies": { + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true + } + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "rechoir": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", + "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", + "dev": true, + "requires": { + "resolve": "^1.9.0" + } + }, + "regexp.prototype.flags": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz", + "integrity": "sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, + "resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "requires": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } + }, + "resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "requires": { + "resolve-from": "^5.0.0" + } + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + }, + "retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "dev": true + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "right-now": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/right-now/-/right-now-1.0.0.tgz", + "integrity": "sha1-bolgne69fc2vja7Mmuo5z1haCRg=" + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", + "dev": true + }, + "selfsigned": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.11.tgz", + "integrity": "sha512-aVmbPOfViZqOZPgRBT0+3u4yZFHpmnIghLMlAcb5/xhp5ZtB/RVnKhz5vl2M32CLXAqR4kha9zfhNg0Lf/sxKA==", + "dev": true, + "requires": { + "node-forge": "^0.10.0" + } + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "dev": true, + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "dependencies": { + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "dependencies": { + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + } + } + }, + "serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "dev": true, + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + } + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "dev": true + }, + "shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, + "signum": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/signum/-/signum-1.0.0.tgz", + "integrity": "sha1-dKfSvyogtA66FqkrFSEk8dVZ+nc=" + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "sockjs": { + "version": "0.3.21", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.21.tgz", + "integrity": "sha512-DhbPFGpxjc6Z3I+uX07Id5ZO2XwYsWOrYjaSeieES78cq+JaJvVe5q/m1uvjIQhXinhIeCFRH6JgXe+mvVMyXw==", + "dev": true, + "requires": { + "faye-websocket": "^0.11.3", + "uuid": "^3.4.0", + "websocket-driver": "^0.7.4" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "dependencies": { + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + }, + "dependencies": { + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "stats-js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stats-js/-/stats-js-1.0.1.tgz", + "integrity": "sha512-EAwEFghGNv8mlYC4CZzI5kWghsnP8uBKXw6VLRHtXkOk5xySfUKLTqTkjgJFfDluIkf/O7eZwi5MXP50VeTbUg==" + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "strip-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.0.tgz", + "integrity": "sha512-UhDTSnGF1dc0DRbUqr1aXwNoY3RgVkSWG8BrpnuFIxhP57IqbS7IRta2Gfiavds4yCxc5+fEAVVOgBZWnYkvzg==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.0" + } + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "tapable": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.0.tgz", + "integrity": "sha512-FBk4IesMV1rBxX2tfiK8RAmogtWn53puLOQlvO8XuwlgxcYbP4mVPS9Ph4aeamSyyVjOl24aYWAuc8U5kCVwMw==", + "dev": true + }, + "terser": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.7.2.tgz", + "integrity": "sha512-0Omye+RD4X7X69O0eql3lC4Heh/5iLj3ggxR/B5ketZLOtLiOqukUgjw3q4PDnNQbsrkKr3UMypqStQG3XKRvw==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.7.2", + "source-map-support": "~0.5.19" + }, + "dependencies": { + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + } + } + }, + "terser-webpack-plugin": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.2.3.tgz", + "integrity": "sha512-eDbuaDlXhVaaoKuLD3DTNTozKqln6xOG6Us0SzlKG5tNlazG+/cdl8pm9qiF1Di89iWScTI0HcO+CDcf2dkXiw==", + "dev": true, + "requires": { + "jest-worker": "^27.0.6", + "p-limit": "^3.1.0", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.0", + "source-map": "^0.6.1", + "terser": "^5.7.2" + } + }, + "thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "dev": true + }, + "to-px": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/to-px/-/to-px-1.1.0.tgz", + "integrity": "sha512-bfg3GLYrGoEzrGoE05TAL/Uw+H/qrf2ptr9V3W7U0lkjjyYnIfgxmVLUfhQ1hZpIQwin81uxhDjvUkDYsC0xWw==", + "requires": { + "parse-unit": "^1.0.1" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "dev": true + }, + "ts-loader": { + "version": "9.2.5", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.2.5.tgz", + "integrity": "sha512-al/ATFEffybdRMUIr5zMEWQdVnCGMUA9d3fXJ8dBVvBlzytPvIszoG9kZoR+94k6/i293RnVOXwMaWbXhNy9pQ==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4" + } + }, + "turntable-camera-controller": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/turntable-camera-controller/-/turntable-camera-controller-3.0.1.tgz", + "integrity": "sha1-jb0/4AVQGRxlFky4iJcQSVeK/Zk=", + "requires": { + "filtered-vector": "^1.2.1", + "gl-mat4": "^1.0.2", + "gl-vec3": "^1.0.2" + } + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "typescript": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.2.tgz", + "integrity": "sha512-gzP+t5W4hdy4c+68bfcv0t400HVJMMd2+H9B7gae1nQlBzCqvrXX+6GL/b3GAgyTH966pzrZ70/fRjwAtZksSQ==", + "dev": true + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + }, + "v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true + }, + "watchpack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.2.0.tgz", + "integrity": "sha512-up4YAn/XHgZHIxFBVCdlMiWDj6WaLKpwVeGQk2I5thdYxF/KmF0aaz6TfJZ/hfl1h/XlcDr7k1KH7ThDagpFaA==", + "dev": true, + "requires": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + } + }, + "wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, + "requires": { + "minimalistic-assert": "^1.0.0" + } + }, + "webpack": { + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.52.0.tgz", + "integrity": "sha512-yRZOat8jWGwBwHpco3uKQhVU7HYaNunZiJ4AkAVQkPCUGoZk/tiIXiwG+8HIy/F+qsiZvSOa+GLQOj3q5RKRYg==", + "dev": true, + "requires": { + "@types/eslint-scope": "^3.7.0", + "@types/estree": "^0.0.50", + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/wasm-edit": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "acorn": "^8.4.1", + "acorn-import-assertions": "^1.7.6", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.8.0", + "es-module-lexer": "^0.7.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.4", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.1.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.3", + "watchpack": "^2.2.0", + "webpack-sources": "^3.2.0" + } + }, + "webpack-cli": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.8.0.tgz", + "integrity": "sha512-+iBSWsX16uVna5aAYN6/wjhJy1q/GKk4KjKvfg90/6hykCTSgozbfz5iRgDTSJt/LgSbYxdBX3KBHeobIs+ZEw==", + "dev": true, + "requires": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^1.0.4", + "@webpack-cli/info": "^1.3.0", + "@webpack-cli/serve": "^1.5.2", + "colorette": "^1.2.1", + "commander": "^7.0.0", + "execa": "^5.0.0", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^2.2.0", + "rechoir": "^0.7.0", + "v8-compile-cache": "^2.2.0", + "webpack-merge": "^5.7.3" + }, + "dependencies": { + "commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true + } + } + }, + "webpack-dev-middleware": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.0.0.tgz", + "integrity": "sha512-9zng2Z60pm6A98YoRcA0wSxw1EYn7B7y5owX/Tckyt9KGyULTkLtiavjaXlWqOMkM0YtqGgL3PvMOFgyFLq8vw==", + "dev": true, + "requires": { + "colorette": "^1.2.2", + "mem": "^8.1.1", + "memfs": "^3.2.2", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^3.0.0" + } + }, + "webpack-dev-server": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.1.1.tgz", + "integrity": "sha512-Kl1mnCEw8Cy1Kw173gCxLIB242LfPKEOj9WoKhKz/MbryZTNrILzOJTk8kiczw/YUEPzn3gcltCQv6hDsLudRg==", + "dev": true, + "requires": { + "ansi-html-community": "^0.0.8", + "bonjour": "^3.5.0", + "chokidar": "^3.5.1", + "colorette": "^1.2.2", + "compression": "^1.7.4", + "connect-history-api-fallback": "^1.6.0", + "del": "^6.0.0", + "express": "^4.17.1", + "graceful-fs": "^4.2.6", + "html-entities": "^2.3.2", + "http-proxy-middleware": "^2.0.0", + "internal-ip": "^6.2.0", + "ipaddr.js": "^2.0.1", + "open": "^8.0.9", + "p-retry": "^4.5.0", + "portfinder": "^1.0.28", + "schema-utils": "^3.1.0", + "selfsigned": "^1.10.11", + "serve-index": "^1.9.1", + "sockjs": "^0.3.21", + "spdy": "^4.0.2", + "strip-ansi": "^7.0.0", + "url": "^0.11.0", + "webpack-dev-middleware": "^5.0.0", + "ws": "^8.1.0" + } + }, + "webpack-glsl-loader": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/webpack-glsl-loader/-/webpack-glsl-loader-1.0.1.tgz", + "integrity": "sha1-cqDjAZK9V5R9YNbVBckVvmgNCsw=", + "dev": true, + "requires": { + "fs": "0.0.2", + "path": "^0.11.14" + } + }, + "webpack-merge": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", + "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", + "dev": true, + "requires": { + "clone-deep": "^4.0.1", + "wildcard": "^2.0.0" + } + }, + "webpack-sources": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.0.tgz", + "integrity": "sha512-fahN08Et7P9trej8xz/Z7eRu8ltyiygEo/hnRi9KqBUs80KeDcnf96ZJo++ewWd84fEf3xSX9bp4ZS9hbw0OBw==", + "dev": true + }, + "websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dev": true, + "requires": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + } + }, + "websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "wildcard": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", + "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "ws": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.2.tgz", + "integrity": "sha512-Q6B6H2oc8QY3llc3cB8kVmQ6pnJWVQbP7Q5algTcIxx7YEpc0oU4NBVHlztA7Ekzfhw2r0rPducMUiCGWKQRzw==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..1627791 --- /dev/null +++ b/package.json @@ -0,0 +1,22 @@ +{ + "scripts": { + "start": "webpack-dev-server --no-hot --live-reload", + "build": "webpack" + }, + "devDependencies": { + "@types/dat.gui": "^0.7.7", + "@types/webgl2": "0.0.6", + "ts-loader": "^9.2.5", + "typescript": "^4.4.2", + "webpack": "^5.52.0", + "webpack-cli": "^4.8.0", + "webpack-dev-server": "^4.1.1", + "webpack-glsl-loader": "^1.0.1" + }, + "dependencies": { + "3d-view-controls": "^2.2.2", + "dat.gui": "^0.7.7", + "gl-matrix": "^3.3.0", + "stats-js": "^1.0.1" + } +} diff --git a/shader_toy_demo.png b/shader_toy_demo.png new file mode 100644 index 0000000..91dfb7e Binary files /dev/null and b/shader_toy_demo.png differ diff --git a/src/Camera.ts b/src/Camera.ts new file mode 100644 index 0000000..4d0e234 --- /dev/null +++ b/src/Camera.ts @@ -0,0 +1,48 @@ +var CameraControls = require('3d-view-controls'); +import {vec3, mat4} from 'gl-matrix'; + +class Camera { + controls: any; + projectionMatrix: mat4 = mat4.create(); + viewMatrix: mat4 = mat4.create(); + fovy: number = 30; + aspectRatio: number = 1; + near: number = 0.1; + far: number = 1000; + position: vec3 = vec3.create(); + direction: vec3 = vec3.create(); + target: vec3 = vec3.create(); + up: vec3 = vec3.create(); + + constructor(position: vec3, target: vec3) { + this.controls = CameraControls(document.getElementById('canvas'), { + eye: position, + center: target, + }); + vec3.add(this.target, this.position, this.direction); + mat4.lookAt(this.viewMatrix, this.controls.eye, this.controls.center, this.controls.up); + } + + setAspectRatio(aspectRatio: number) { + this.aspectRatio = aspectRatio; + } + + setPosition(pos: vec3) { + // this.controls.eye = pos; + this.controls.center = pos; + + // console.log(this.position[0]); + } + + updateProjectionMatrix() { + mat4.perspective(this.projectionMatrix, this.fovy, this.aspectRatio, this.near, this.far); + } + + update() { + this.controls.tick(); + vec3.add(this.target, this.position, this.direction); + mat4.lookAt(this.viewMatrix, this.controls.eye, this.controls.center, this.controls.up); + } +}; + +export default Camera; diff --git a/src/geometry/Cube.ts b/src/geometry/Cube.ts new file mode 100644 index 0000000..3cd5e08 --- /dev/null +++ b/src/geometry/Cube.ts @@ -0,0 +1,117 @@ +import {vec3, vec4} from 'gl-matrix'; +import Drawable from '../rendering/gl/Drawable'; +import {gl} from '../globals'; + +class Cube extends Drawable { + indices: Uint32Array; + positions: Float32Array; + normals: Float32Array; + center: vec4; + + constructor(center: vec3) { + super(); // Call the constructor of the super class. This is required. + this.center = vec4.fromValues(center[0], center[1], center[2], 1); + } + + create() { + this.indices = new Uint32Array([0, 1, 2, + 0, 2, 3, + + 4, 5, 6, + 4, 6, 7, + + 8, 9, 10, + 8, 10, 11, + + 12, 13, 14, + 12, 14, 15, + + 16, 17, 18, + 16, 18, 19, + + 20, 21, 22, + 20, 22, 23]); + +this.normals = new Float32Array([ + // front + 0, 0, 1, 0, + 0, 0, 1, 0, + 0, 0, 1, 0, + 0, 0, 1, 0, + // right + 1, 0, 0, 0, + 1, 0, 0, 0, + 1, 0, 0, 0, + 1, 0, 0, 0, + // back + 0, 0, -1, 0, + 0, 0, -1, 0, + 0, 0, -1, 0, + 0, 0, -1, 0, + // left + -1, 0, 0, 0, + -1, 0, 0, 0, + -1, 0, 0, 0, + -1, 0, 0, 0, + // top + 0, 1, 0, 0, + 0, 1, 0, 0, + 0, 1, 0, 0, + 0, 1, 0, 0, + // bottom + 0, -1, 0, 0, + 0, -1, 0, 0, + 0, -1, 0, 0, + 0, -1, 0, 0 + ]); +this.positions = new Float32Array([ + // front + this.center[0] - 1, this.center[1] - 1, this.center[2] + 1, 1, + this.center[0] + 1, this.center[1] - 1, this.center[2] + 1, 1, + this.center[0] + 1, this.center[1] + 1, this.center[2] + 1, 1, + this.center[0] - 1, this.center[1] + 1, this.center[2] + 1, 1, + // right + this.center[0] + 1, this.center[1] - 1, this.center[2] + 1, 1, + this.center[0] + 1, this.center[1] - 1, this.center[2] - 1, 1, + this.center[0] + 1, this.center[1] + 1, this.center[2] - 1, 1, + this.center[0] + 1, this.center[1] + 1, this.center[2] + 1, 1, + // back + this.center[0] - 1, this.center[1] - 1, this.center[2] - 1, 1, + this.center[0] + 1, this.center[1] - 1, this.center[2] - 1, 1, + this.center[0] + 1, this.center[1] + 1, this.center[2] - 1, 1, + this.center[0] - 1, this.center[1] + 1, this.center[2] - 1, 1, + // left + this.center[0] - 1, this.center[1] - 1, this.center[2] + 1, 1, + this.center[0] - 1, this.center[1] - 1, this.center[2] - 1, 1, + this.center[0] - 1, this.center[1] + 1, this.center[2] - 1, 1, + this.center[0] - 1, this.center[1] + 1, this.center[2] + 1, 1, + // top + this.center[0] + 1, this.center[1] + 1, this.center[2] + 1, 1, + this.center[0] + 1, this.center[1] + 1, this.center[2] - 1, 1, + this.center[0] - 1, this.center[1] + 1, this.center[2] - 1, 1, + this.center[0] - 1, this.center[1] + 1, this.center[2] + 1, 1, + // bottom + this.center[0] + 1, this.center[1] - 1, this.center[2] + 1, 1, + this.center[0] - 1, this.center[1] - 1, this.center[2] + 1, 1, + this.center[0] - 1, this.center[1] - 1, this.center[2] - 1, 1, + this.center[0] + 1, this.center[1] - 1, this.center[2] - 1, 1]); + + this.generateIdx(); + this.generatePos(); + this.generateNor(); + + this.count = this.indices.length; + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.bufIdx); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW); + + gl.bindBuffer(gl.ARRAY_BUFFER, this.bufNor); + gl.bufferData(gl.ARRAY_BUFFER, this.normals, gl.STATIC_DRAW); + + gl.bindBuffer(gl.ARRAY_BUFFER, this.bufPos); + gl.bufferData(gl.ARRAY_BUFFER, this.positions, gl.STATIC_DRAW); + + //console.log(`Created Cube`); + } +}; + +export default Cube; diff --git a/src/geometry/Icosphere.ts b/src/geometry/Icosphere.ts new file mode 100644 index 0000000..9345428 --- /dev/null +++ b/src/geometry/Icosphere.ts @@ -0,0 +1,179 @@ +import {vec3, vec4} from 'gl-matrix'; +import Drawable from '../rendering/gl/Drawable'; +import {gl} from '../globals'; + +class Icosphere extends Drawable { + buffer: ArrayBuffer; + indices: Uint32Array; + positions: Float32Array; + normals: Float32Array; + center: vec4; + + constructor(center: vec3, public radius: number, public subdivisions: number) { + super(); // Call the constructor of the super class. This is required. + this.center = vec4.fromValues(center[0], center[1], center[2], 1); + } + + create() { + const X = 0.525731112119133606; + const Z = 0.850650808352039932; + const N = 0; + + let maxIndexCount = 20 * Math.pow(4, this.subdivisions); + let maxVertexCount = 10 * Math.pow(4, this.subdivisions) + 2; + + // Create buffers to back geometry data + // Index data will ping pong back and forth between buffer0 and buffer1 during creation + // All data will be in buffer0 at the end + const buffer0 = new ArrayBuffer( + maxIndexCount * 3 * Uint32Array.BYTES_PER_ELEMENT + + maxVertexCount * 4 * Float32Array.BYTES_PER_ELEMENT + + maxVertexCount * 4 * Float32Array.BYTES_PER_ELEMENT + ); + const buffer1 = new ArrayBuffer( + maxIndexCount * 3 * Uint32Array.BYTES_PER_ELEMENT + ); + const buffers = [buffer0, buffer1]; + let b = 0; + + const indexByteOffset = 0; + const vertexByteOffset = maxIndexCount * 3 * Uint32Array.BYTES_PER_ELEMENT; + const normalByteOffset = vertexByteOffset; + const positionByteOffset = vertexByteOffset + maxVertexCount * 4 * Float32Array.BYTES_PER_ELEMENT; + + // Create 3-uint buffer views into the backing buffer to represent triangles + // The C++ analogy to this would be something like: + // triangles[i] = reinterpret_cast*>(&buffer[offset]); + let triangles: Array = new Array(20); + let nextTriangles: Array = new Array(); + for (let i = 0; i < 20; ++i) { + triangles[i] = new Uint32Array(buffers[b], indexByteOffset + i * 3 * Uint32Array.BYTES_PER_ELEMENT, 3); + } + + // Create 3-float buffer views into the backing buffer to represent positions + let vertices: Array = new Array(12); + for (let i = 0; i < 12; ++i) { + vertices[i] =new Float32Array(buffer0, vertexByteOffset + i * 4 * Float32Array.BYTES_PER_ELEMENT, 4); + } + + // Initialize normals for a 20-sided icosahedron + vertices[0].set([ -X,N,Z,0 ]); + vertices[1].set([ X,N,Z,0 ]); + vertices[2].set([ -X,N,-Z,0 ]); + vertices[3].set([ X,N,-Z,0 ]); + vertices[4].set([ N,Z,X,0 ]); + vertices[5].set([ N,Z,-X,0 ]); + vertices[6].set([ N,-Z,X,0 ]); + vertices[7].set([ N,-Z,-X,0 ]); + vertices[8].set([ Z,X,N,0 ]); + vertices[9].set([ -Z,X, N,0 ]); + vertices[10].set([ Z,-X,N,0 ]); + vertices[11].set([ -Z,-X,N,0 ]); + + // Initialize indices for a 20-sided icosahedron + triangles[0].set([ 0,4,1 ]); + triangles[1].set([ 0,9,4 ]); + triangles[2].set([ 9,5,4 ]); + triangles[3].set([ 4,5,8 ]); + triangles[4].set([ 4,8,1 ]); + triangles[5].set([ 8,10,1 ]); + triangles[6].set([ 8,3,10 ]); + triangles[7].set([ 5,3,8 ]); + triangles[8].set([ 5,2,3 ]); + triangles[9].set([ 2,7,3 ]); + triangles[10].set([ 7,10,3 ]); + triangles[11].set([ 7,6,10 ]); + triangles[12].set([ 7,11,6 ]); + triangles[13].set([ 11,0,6 ]); + triangles[14].set([ 0,1,6 ],); + triangles[15].set([ 6,1,10 ]); + triangles[16].set([ 9,0,11 ]); + triangles[17].set([ 9,11,2 ]); + triangles[18].set([ 9,2,5 ]); + triangles[19].set([ 7,2,11 ]); + + // This loop subdivides the icosahedron + for (let s = 0; s < this.subdivisions; ++s) { + b = 1 - b; + nextTriangles.length = triangles.length * 4; + let triangleIdx = 0; + + // edgeMap maps a pair of vertex indices to a vertex index at their midpoint + // The function `mid` will get that midpoint vertex if it has already been created + // or it will create the vertex and add it to the map + let edgeMap: Map = new Map(); + function mid(v0: number, v1: number): number { + let key = [v0, v1].sort().join('_'); + if (!edgeMap.has(key)) { + let midpoint = new Float32Array(buffer0, vertexByteOffset + vertices.length * 4 * Float32Array.BYTES_PER_ELEMENT, 4); + vec4.add(midpoint, vertices[v0], vertices[v1]); + vec4.normalize(midpoint, midpoint); + edgeMap.set(key, vertices.length); + vertices.push(midpoint); + } + return edgeMap.get(key); + } + + for (let t = 0; t < triangles.length; ++t) { + let v0 = triangles[t][0]; + let v1 = triangles[t][1]; + let v2 = triangles[t][2]; + let v3 = mid(v0, v1); // Get or create a vertex between these two vertices + let v4 = mid(v1, v2); + let v5 = mid(v2, v0); + + let t0 = nextTriangles[triangleIdx] = new Uint32Array(buffers[b], indexByteOffset + (triangleIdx++) * 3 * Uint32Array.BYTES_PER_ELEMENT, 3); + let t1 = nextTriangles[triangleIdx] = new Uint32Array(buffers[b], indexByteOffset + (triangleIdx++) * 3 * Uint32Array.BYTES_PER_ELEMENT, 3); + let t2 = nextTriangles[triangleIdx] = new Uint32Array(buffers[b], indexByteOffset + (triangleIdx++) * 3 * Uint32Array.BYTES_PER_ELEMENT, 3); + let t3 = nextTriangles[triangleIdx] = new Uint32Array(buffers[b], indexByteOffset + (triangleIdx++) * 3 * Uint32Array.BYTES_PER_ELEMENT, 3); + + let triangleOffset = nextTriangles.length; + t0.set([v0, v3, v5]); + t1.set([v3, v4, v5]); + t2.set([v3, v1, v4]); + t3.set([v5, v4, v2]); + } + + // swap buffers + let temp = triangles; + triangles = nextTriangles; + nextTriangles = temp; + } + + if (b === 1) { + // if indices did not end up in buffer0, copy them there now + let temp0 = new Uint32Array(buffer0, 0, 3 * triangles.length); + let temp1 = new Uint32Array(buffer1, 0, 3 * triangles.length); + temp0.set(temp1); + } + + // Populate one position for each normal + for (let i = 0; i < vertices.length; ++i) { + let pos = new Float32Array(buffer0, positionByteOffset + i * 4 * Float32Array.BYTES_PER_ELEMENT, 4); + vec4.scaleAndAdd(pos, this.center, vertices[i], this.radius); + } + + this.buffer = buffer0; + this.indices = new Uint32Array(this.buffer, indexByteOffset, triangles.length * 3); + this.normals = new Float32Array(this.buffer, normalByteOffset, vertices.length * 4); + this.positions = new Float32Array(this.buffer, positionByteOffset, vertices.length * 4); + + this.generateIdx(); + this.generatePos(); + this.generateNor(); + + this.count = this.indices.length; + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.bufIdx); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW); + + gl.bindBuffer(gl.ARRAY_BUFFER, this.bufNor); + gl.bufferData(gl.ARRAY_BUFFER, this.normals, gl.STATIC_DRAW); + + gl.bindBuffer(gl.ARRAY_BUFFER, this.bufPos); + gl.bufferData(gl.ARRAY_BUFFER, this.positions, gl.STATIC_DRAW); + + //console.log(`Created icosphere with ${vertices.length} vertices`); + } +}; + +export default Icosphere; diff --git a/src/geometry/Square.ts b/src/geometry/Square.ts new file mode 100644 index 0000000..cbfa494 --- /dev/null +++ b/src/geometry/Square.ts @@ -0,0 +1,50 @@ +import {vec3, vec4} from 'gl-matrix'; +import Drawable from '../rendering/gl/Drawable'; +import {gl} from '../globals'; + +class Square extends Drawable { + indices: Uint32Array; + positions: Float32Array; + normals: Float32Array; + center: vec4; + scale: vec4; + + constructor(center: vec3, scale: vec3) { + super(); // Call the constructor of the super class. This is required. + this.center = vec4.fromValues(center[0], center[1], center[2], 1); + this.scale = vec4.fromValues(scale[0], scale[1], scale[2], 1); + } + + create() { + + this.indices = new Uint32Array([0, 1, 2, + 0, 2, 3]); + this.normals = new Float32Array([0, 0, 1, 0, + 0, 0, 1, 0, + 0, 0, 1, 0, + 0, 0, 1, 0]); + this.positions = new Float32Array([ + this.center[0] -this.scale[0], this.center[1] -this.scale[1], this.center[2], 1, + this.center[0] + this.scale[0],this.center[1] -this.scale[1], this.center[2], 1, + this.center[0] + this.scale[0],this.center[1] + this.scale[1], this.center[2], 1, + this.center[0] -this.scale[0], this.center[1] + this.scale[1], this.center[2], 1]); + + this.generateIdx(); + this.generatePos(); + this.generateNor(); + + this.count = this.indices.length; + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.bufIdx); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW); + + gl.bindBuffer(gl.ARRAY_BUFFER, this.bufNor); + gl.bufferData(gl.ARRAY_BUFFER, this.normals, gl.STATIC_DRAW); + + gl.bindBuffer(gl.ARRAY_BUFFER, this.bufPos); + gl.bufferData(gl.ARRAY_BUFFER, this.positions, gl.STATIC_DRAW); + + //console.log(`Created square`); + } +}; + +export default Square; diff --git a/src/geometry/SquarePyramid.ts b/src/geometry/SquarePyramid.ts new file mode 100644 index 0000000..883ef3c --- /dev/null +++ b/src/geometry/SquarePyramid.ts @@ -0,0 +1,107 @@ +import {vec3, vec4} from 'gl-matrix'; +import Drawable from '../rendering/gl/Drawable'; +import {gl} from '../globals'; + +class SquarePyramid extends Drawable { + indices: Uint32Array; + positions: Float32Array; + normals: Float32Array; + center: vec4; + + constructor(center: vec3) { + super(); // Call the constructor of the super class. This is required. + this.center = vec4.fromValues(center[0], center[1], center[2], 1); + } + + createTriangulate() { + this.create(); + let idxCount: number = this.indices.length; + + + } + + create() { + this.indices = new Uint32Array([ + // front + 0, 1, 2, + // right + 3, 4, 5, + // back + 6, 7, 8, + // left + 9, 10, 11, + // bottom + 12, 13, 14, + 12, 14, 15 + ]); + +this.normals = new Float32Array([ + // front + 0, 0, 1, 0, + 0, 0, 1, 0, + 0, 0, 1, 0, + // right + 1, 0, 0, 0, + 1, 0, 0, 0, + 1, 0, 0, 0, + // back + 0, 0, -1, 0, + 0, 0, -1, 0, + 0, 0, -1, 0, + // left + -1, 0, 0, 0, + -1, 0, 0, 0, + -1, 0, 0, 0, + + // bottom + 0, -1, 0, 0, + 0, -1, 0, 0, + 0, -1, 0, 0, + 0, -1, 0, 0 + ]); +this.positions = new Float32Array([ + // front + this.center[0] - 1, this.center[1] - 1, this.center[2] + 1, 1, + this.center[0] + 1, this.center[1] - 1, this.center[2] + 1, 1, + this.center[0], this.center[1] + 1, this.center[2], 1, + + // right + this.center[0] + 1, this.center[1] - 1, this.center[2] + 1, 1, + this.center[0] + 1, this.center[1] - 1, this.center[2] - 1, 1, + this.center[0], this.center[1] + 1, this.center[2], 1, + + // back + this.center[0] - 1, this.center[1] - 1, this.center[2] - 1, 1, + this.center[0] + 1, this.center[1] - 1, this.center[2] - 1, 1, + this.center[0], this.center[1] + 1, this.center[2], 1, + + // left + this.center[0] - 1, this.center[1] - 1, this.center[2] + 1, 1, + this.center[0] - 1, this.center[1] - 1, this.center[2] - 1, 1, + this.center[0], this.center[1] + 1, this.center[2], 1, + + // bottom + this.center[0] + 1, this.center[1] - 1, this.center[2] + 1, 1, + this.center[0] - 1, this.center[1] - 1, this.center[2] + 1, 1, + this.center[0] - 1, this.center[1] - 1, this.center[2] - 1, 1, + this.center[0] + 1, this.center[1] - 1, this.center[2] - 1, 1]); + + this.generateIdx(); + this.generatePos(); + this.generateNor(); + + this.count = this.indices.length; + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.bufIdx); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW); + + gl.bindBuffer(gl.ARRAY_BUFFER, this.bufNor); + gl.bufferData(gl.ARRAY_BUFFER, this.normals, gl.STATIC_DRAW); + + gl.bindBuffer(gl.ARRAY_BUFFER, this.bufPos); + gl.bufferData(gl.ARRAY_BUFFER, this.positions, gl.STATIC_DRAW); + + //console.log(`Created Cube`); + } +}; + +export default SquarePyramid; diff --git a/src/globals.ts b/src/globals.ts new file mode 100644 index 0000000..cac5bf2 --- /dev/null +++ b/src/globals.ts @@ -0,0 +1,5 @@ + +export var gl: WebGL2RenderingContext; +export function setGL(_gl: WebGL2RenderingContext) { + gl = _gl; +} diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..94555d4 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,218 @@ +import {vec3} from 'gl-matrix'; +import {vec4} from 'gl-matrix'; +const Stats = require('stats-js'); +import * as DAT from 'dat.gui'; +import Icosphere from './geometry/Icosphere'; +import Square from './geometry/Square'; +import Cube from './geometry/Cube'; +import SquarePyramid from './geometry/SquarePyramid'; + +import OpenGLRenderer from './rendering/gl/OpenGLRenderer'; +import Camera from './Camera'; +import {setGL} from './globals'; +import ShaderProgram, {Shader} from './rendering/gl/ShaderProgram'; + +// Define an object with application parameters and button callbacks +// This will be referred to by dat.GUI's functions that add GUI elements. +const controls = { + tesselations: 5, + 'Load Scene': loadScene, // A function pointer, essentially + 'Shader': 0, + 'Color': [ 255, 12, 25 ], + 'CameraX': 1, + 'CameraY': 1, + 'CameraZ': 1, + + 'Camera Animation': 'Off', + 'Camera Animation Speed': 1, + + 'Noise Color': [ 255, 255, 0 ], + 'Depth': 0.1, + 'Rows': 4, + 'TriScale': 1.0, + 'LowTriRange': -1.0, + 'HighTriRange': 1.0, + 'HeightT': 'Off', + 'SymbolScaleT': 'Off', + 'SymbolPositionT': 'Off', + 'NumSymbolsPerTri': 0.0, + +}; + +let icosphere: Icosphere; + +let square: Square; +let cube: Cube; +let squarePyramid: SquarePyramid; +let time: number = 0; +let timeCamera: number = 0; +let cameraSpeed: number = 0.002; +let height: number = 0; +let color: vec4; +let noiseColor: vec4; + +let prevTesselations: number = 5; + +function loadScene() { + icosphere = new Icosphere(vec3.fromValues(3, 0, 0), 1, controls.tesselations); + icosphere.create(); + + square = new Square(vec3.fromValues(0, 0, 0), vec3.fromValues(1, 1, 1)); + square.create(); + + cube = new Cube(vec3.fromValues(0, 0, 0)); + cube.create(); + + squarePyramid = new SquarePyramid(vec3.fromValues(0, 0, 0)) + squarePyramid.create(); +} + +function main() { + + // Initial display for framerate + const stats = Stats(); + stats.setMode(0); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.left = '0px'; + stats.domElement.style.top = '0px'; + document.body.appendChild(stats.domElement); + + // Add controls to the gui + const gui = new DAT.GUI(); + // gui.add(controls, 'tesselations', 0, 8).step(1); + // gui.add(controls, 'Load Scene'); + // gui.addColor(controls, 'Color'); + // gui.addColor(controls, 'Noise Color'); + var f1 = gui.addFolder('Greeble Control'); + + f1.add(controls, 'Depth', 0, 0.5).step(0.02); + f1.add(controls, 'Rows', 2, 30).step(1); + f1.add(controls, 'TriScale', 0.01, 1.5).step(0.01); + f1.add(controls, 'LowTriRange', -1.0, 1.0).step(0.01); + f1.add(controls, 'HighTriRange', -1.0, 1.0).step(0.01); + f1.add(controls, 'HeightT', [ 'On', 'Off' ]); + f1.add(controls, 'SymbolScaleT', [ 'On', 'Off' ]); + f1.add(controls, 'SymbolPositionT', [ 'On', 'Off' ]); + f1.add(controls, 'NumSymbolsPerTri', -1.0, 1.0).step(0.01); + + var f2 = gui.addFolder('Animation'); + + f2.add(controls, 'Camera Animation', [ 'On', 'Off' ]); + f2.add(controls, 'Camera Animation Speed', 1, 10).step(1); + f2.add(controls, 'CameraX', -10, 10).step(0.02); + f2.add(controls, 'CameraY', -10, 10).step(0.02); + f2.add(controls, 'CameraZ', -10, 10).step(0.02); + // gui.add(controls, 'Shader', 0, 1).step(1); + // gui.add(controls, 'Shaders', [ 'Lambert', 'Perlin Noise', 'Transform', 'Fireball' ] ); + + // get canvas and webgl context + const canvas = document.getElementById('canvas'); + const gl = canvas.getContext('webgl2'); + if (!gl) { + alert('WebGL 2 not supported!'); + } + // `setGL` is a function imported above which sets the value of `gl` in the `globals.ts` module. + // Later, we can import `gl` from `globals.ts` to access it + setGL(gl); + + // Initial call to load scene + loadScene(); + const camera = new Camera(vec3.fromValues(2, 2, 1.5), vec3.fromValues(0, 0, 0)); + + // const camera = new Camera(vec3.fromValues(2, 3, 0), vec3.fromValues(0, 0, 0)); + + const renderer = new OpenGLRenderer(canvas); + renderer.setClearColor(0.2, 0.2, 0.2, 1); + gl.enable(gl.DEPTH_TEST); + + const sdf = new ShaderProgram([ + new Shader(gl.VERTEX_SHADER, [require('./shaders/sdf1-vert.glsl')], []), + new Shader(gl.FRAGMENT_SHADER, [ + require('./shaders/toolbox.glsl'), + require('./shaders/noise.glsl'), + require('./shaders/sdf-compose.glsl'), + require('./shaders/sdf-objects.glsl'), + require('./shaders/sdf1-frag.glsl') + ], [ + ]), + ]); + sdf.setDimensions(window.innerWidth, window.innerHeight); + + time = 0; + + let SymbolPositionT = 0; + let SymbolScaleT = 0; + let HeightT = 0; + // This function will be called every frame + function tick() { + time +=1; + color = vec4.fromValues(controls.Color[0] /255, controls.Color[1] / 255, controls.Color[2] / 255, 1); + noiseColor = vec4.fromValues(controls['Noise Color'][0] /255, controls['Noise Color'][1] / 255, controls['Noise Color'][2] / 255, 1); + height = controls['Depth']; + + if(controls['SymbolScaleT'] == 'On'){SymbolScaleT += 0.01} + if(controls['SymbolPositionT'] == 'On'){SymbolPositionT += 0.01} + if(controls['HeightT'] == 'On'){HeightT += 0.01} + + if(controls['Camera Animation'] == 'On'){ + // camera.setPosition(vec3.fromValues( + // controls['CameraX'] + Math.sin(timeCamera) * 4, + // controls['CameraY'] + Math.sin(timeCamera) * 2, + // controls['CameraZ'] + Math.sin(timeCamera) * 10)); + camera.setPosition(vec3.fromValues( + 2 + Math.sin(timeCamera) * controls['CameraX'], + 2 + Math.sin(timeCamera) * controls['CameraY'], + 1.5 + Math.sin(timeCamera) * controls['CameraZ'])); + } + // const camera = new Camera(vec3.fromValues(controls.CameraX, 3, 0), vec3.fromValues(0, 0, 0)); + + // camera.update(); + stats.begin(); + gl.viewport(0, 0, window.innerWidth, window.innerHeight); + renderer.clear(); + if(controls.tesselations != prevTesselations) + { + prevTesselations = controls.tesselations; + icosphere = new Icosphere(vec3.fromValues(3, 0, 0), 1, prevTesselations); + icosphere.create(); + } + + + + sdf.setRows(controls['Rows']); + sdf.setTriScale(controls['TriScale']); + sdf.setLowTriRange(controls['LowTriRange']); + sdf.setHighTriRange(controls['HighTriRange']); + sdf.setHightT(HeightT); + sdf.setSymbolScaleT(SymbolScaleT); + sdf.setSymbolPositionT(SymbolPositionT); + sdf.setNumSymbolsPerTri(controls['NumSymbolsPerTri']); + + renderer.render(camera, time, height, color, noiseColor, sdf, [ + square, + ], false); + + stats.end(); + + // Tell the browser to call `tick` again whenever it renders a new frame + requestAnimationFrame(tick); + + + timeCamera+=0.002 * controls['Camera Animation Speed']; + } + + window.addEventListener('resize', function() { + renderer.setSize(window.innerWidth, window.innerHeight); + camera.setAspectRatio(window.innerWidth / window.innerHeight); + camera.updateProjectionMatrix(); + }, false); + + renderer.setSize(window.innerWidth, window.innerHeight); + camera.setAspectRatio(window.innerWidth / window.innerHeight); + camera.updateProjectionMatrix(); + + // Start the render loop + tick(); +} + +main(); diff --git a/src/rendering/gl/Drawable.ts b/src/rendering/gl/Drawable.ts new file mode 100644 index 0000000..3006b5c --- /dev/null +++ b/src/rendering/gl/Drawable.ts @@ -0,0 +1,67 @@ +import {gl} from '../../globals'; + +abstract class Drawable { + count: number = 0; + + bufIdx: WebGLBuffer; + bufPos: WebGLBuffer; + bufNor: WebGLBuffer; + + idxBound: boolean = false; + posBound: boolean = false; + norBound: boolean = false; + + abstract create() : void; + + destory() { + gl.deleteBuffer(this.bufIdx); + gl.deleteBuffer(this.bufPos); + gl.deleteBuffer(this.bufNor); + } + + generateIdx() { + this.idxBound = true; + this.bufIdx = gl.createBuffer(); + } + + generatePos() { + this.posBound = true; + this.bufPos = gl.createBuffer(); + } + + generateNor() { + this.norBound = true; + this.bufNor = gl.createBuffer(); + } + + bindIdx(): boolean { + if (this.idxBound) { + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.bufIdx); + } + return this.idxBound; + } + + bindPos(): boolean { + if (this.posBound) { + gl.bindBuffer(gl.ARRAY_BUFFER, this.bufPos); + } + return this.posBound; + } + + bindNor(): boolean { + if (this.norBound) { + gl.bindBuffer(gl.ARRAY_BUFFER, this.bufNor); + } + return this.norBound; + } + + elemCount(): number { + return this.count; + } + + drawMode(): GLenum { + return gl.TRIANGLES; + } +}; + +export default Drawable; diff --git a/src/rendering/gl/OpenGLRenderer.ts b/src/rendering/gl/OpenGLRenderer.ts new file mode 100644 index 0000000..462b842 --- /dev/null +++ b/src/rendering/gl/OpenGLRenderer.ts @@ -0,0 +1,54 @@ +import {mat4, vec4} from 'gl-matrix'; +import Drawable from './Drawable'; +import Camera from '../../Camera'; +import {gl} from '../../globals'; +import ShaderProgram from './ShaderProgram'; + +// In this file, `gl` is accessible because it is imported above +class OpenGLRenderer { + constructor(public canvas: HTMLCanvasElement) { + } + + setClearColor(r: number, g: number, b: number, a: number) { + gl.clearColor(r, g, b, a); + } + + setSize(width: number, height: number) { + this.canvas.width = width; + this.canvas.height = height; + } + + clear() { + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + } + + render(camera: Camera, time: number, height:number, color: vec4, noiseColor:vec4, prog: ShaderProgram, + drawables: Array, mode: boolean) { + let model = mat4.create(); + let viewProj = mat4.create(); + // color = vec4.fromValues(1,0,0,1); + mat4.identity(model); + mat4.multiply(viewProj, camera.projectionMatrix, camera.viewMatrix); + prog.setModelMatrix(model); + prog.setViewProjMatrix(viewProj); + prog.setGeometryColor(color); + prog.setNoiseColor(noiseColor); + prog.setTime(time); + prog.setNoiseHeight(height); + prog.setEyeRefUp(camera.controls.eye, camera.controls.center, camera.controls.up); + // prog.setColor(color); + // gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT ); + gl.clearColor(0.0, 0.0 / 255.0, 0.0 / 255.0, 0.9); + for (let drawable of drawables) { + if(!mode){ + prog.draw(drawable); + + }else{ + prog.drawLine(drawable); + + } + } + } +}; + +export default OpenGLRenderer; diff --git a/src/rendering/gl/ShaderProgram.ts b/src/rendering/gl/ShaderProgram.ts new file mode 100644 index 0000000..87b18e3 --- /dev/null +++ b/src/rendering/gl/ShaderProgram.ts @@ -0,0 +1,273 @@ +import {vec4, mat4, vec3} from 'gl-matrix'; +import Drawable from './Drawable'; +import {gl} from '../../globals'; +import jsonsdfs from './sdfs.json'; + +var activeProgram: WebGLProgram = null; + + +type flatArr = { + name: string, + data: Float32Array, + x: number, + y: number, + z: number +} + +function toFlatArr(name: string){ + + // @ts-ignore + const arr: number[][][] = jsonsdfs[name]; + const flat2d = arr.reduce((accumulator, value) => accumulator.concat(value), []) + const flat1d = flat2d.reduce((accumulator, value) => accumulator.concat(value), []) + const obj: flatArr = { + name: name, + data: new Float32Array(flat1d), + x: arr.length, y:arr[0].length , z: arr[0][0].length + } + return obj; +} + +export class Shader { + shader: WebGLShader; + fields: Array; + + constructor(type: number, sources: Array, fields: Array) { + this.shader = gl.createShader(type); + this.fields = []; + let fullSource = '#version 300 es\n' + + 'precision highp float;\n'; + for (let field of fields){ + // @ts-ignore + const fieldObj = toFlatArr(field); + console.log('data size', fieldObj.data.length) + fullSource += `uniform float u_${field}Field[${fieldObj.x * fieldObj.y * fieldObj.z}];\n` + + `uniform vec3 u_${field}FieldDims;\n` + // @ts-ignore + this.fields.push(fieldObj); + } + for (let partialSource of sources){ + fullSource += partialSource; + } + //console.log(fullSource); + gl.shaderSource(this.shader, fullSource); + gl.compileShader(this.shader); + + if (!gl.getShaderParameter(this.shader, gl.COMPILE_STATUS)) { + throw gl.getShaderInfoLog(this.shader); + } + } +}; + +class ShaderProgram { + prog: WebGLProgram; + + attrPos: number; + attrNor: number; + attrCol: number; + + unifModel: WebGLUniformLocation; + unifModelInvTr: WebGLUniformLocation; + unifViewProj: WebGLUniformLocation; + unifColor: WebGLUniformLocation; + unifNoiseColor: WebGLUniformLocation; + unifTime: WebGLUniformLocation; + unifNoiseHeight: WebGLUniformLocation; + + unifCenter: WebGLUniformLocation; + + unifRef: WebGLUniformLocation; + unifEye: WebGLUniformLocation; + unifUp: WebGLUniformLocation; + unifDimensions: WebGLUniformLocation; + + unifRows: WebGLUniformLocation; + unifTriScale: WebGLUniformLocation; + unifLowTriRange: WebGLUniformLocation; + unifHighTriRange: WebGLUniformLocation; + unifHightT: WebGLUniformLocation; + unifSymbolScaleT: WebGLUniformLocation; + unifSymbolPositionT: WebGLUniformLocation; + unifNumSymbolsPerTri: WebGLUniformLocation; + + constructor(shaders: Array) { + this.prog = gl.createProgram(); + + + + for (let shader of shaders) { + gl.attachShader(this.prog, shader.shader); + } + gl.linkProgram(this.prog); + if (!gl.getProgramParameter(this.prog, gl.LINK_STATUS)) { + throw gl.getProgramInfoLog(this.prog); + } + + this.attrPos = gl.getAttribLocation(this.prog, "vs_Pos"); + this.attrNor = gl.getAttribLocation(this.prog, "vs_Nor"); + this.attrCol = gl.getAttribLocation(this.prog, "vs_Col"); + this.unifModel = gl.getUniformLocation(this.prog, "u_Model"); + this.unifModelInvTr = gl.getUniformLocation(this.prog, "u_ModelInvTr"); + this.unifViewProj = gl.getUniformLocation(this.prog, "u_ViewProj"); + this.unifColor = gl.getUniformLocation(this.prog, "u_Color"); + this.unifNoiseColor = gl.getUniformLocation(this.prog, "u_NoiseColor"); + this.unifTime = gl.getUniformLocation(this.prog, "u_Time"); + this.unifNoiseHeight = gl.getUniformLocation(this.prog, "u_NoiseHeight"); + this.unifCenter = gl.getUniformLocation(this.prog, "u_Center"); + this.unifEye = gl.getUniformLocation(this.prog, "u_Eye"); + this.unifRef = gl.getUniformLocation(this.prog, "u_Ref"); + this.unifUp = gl.getUniformLocation(this.prog, "u_Up"); + this.unifDimensions = gl.getUniformLocation(this.prog, "u_Dimensions"); + + this.unifRows = gl.getUniformLocation(this.prog, "u_Rows"); + this.unifTriScale = gl.getUniformLocation(this.prog, "u_TriScale"); + this.unifLowTriRange = gl.getUniformLocation(this.prog, "u_LowTriRange"); + this.unifHighTriRange = gl.getUniformLocation(this.prog, "u_HighTriRange"); + this.unifHightT = gl.getUniformLocation(this.prog, "u_HeightT"); + this.unifSymbolScaleT = gl.getUniformLocation(this.prog, "u_SymbolScaleT"); + this.unifSymbolPositionT = gl.getUniformLocation(this.prog, "u_SymbolPositionT"); + this.unifNumSymbolsPerTri = gl.getUniformLocation(this.prog, "u_NumSymbolsPerTri"); + + + + + + this.use(); + for (let shader of shaders) { + console.log(shader); + for(let field of shader.fields){ + + const shaderF = gl.getUniformLocation(this.prog, `u_${field.name}Field`); + const shaderFDims = gl.getUniformLocation(this.prog, `u_${field.name}FieldDims`); + + gl.uniform1fv(shaderF, field.data); + gl.uniform3f(shaderFDims, field.x, field.y, field.z); + } + } + + + + } + + setRows(t: number){this.use();gl.uniform1f(this.unifRows, t)} + setTriScale(t: number){this.use();gl.uniform1f(this.unifTriScale, t)} + setLowTriRange(t: number){this.use();gl.uniform1f(this.unifLowTriRange, t)} + setHighTriRange(t: number){this.use();gl.uniform1f(this.unifHighTriRange, t)} + setHightT(t: number){this.use();gl.uniform1f(this.unifHightT, t)} + setSymbolScaleT(t: number){this.use();gl.uniform1f(this.unifSymbolScaleT, t)} + setSymbolPositionT(t: number){this.use();gl.uniform1f(this.unifSymbolPositionT, t)} + setNumSymbolsPerTri(t: number){this.use();gl.uniform1f(this.unifNumSymbolsPerTri, t)} + + use() { + if (activeProgram !== this.prog) { + gl.useProgram(this.prog); + activeProgram = this.prog; + } + } + setTime(t: number){ + this.use(); + if(this.unifTime !== -1){ + gl.uniform1f(this.unifTime, t); + } + } + setNoiseHeight(h: number){ + this.use(); + if(this.unifNoiseHeight !== -1){ + gl.uniform1f(this.unifNoiseHeight, h); + } + } + setEyeRefUp(eye: vec3, ref: vec3, up: vec3) { + this.use(); + if(this.unifEye !== -1) { + gl.uniform3f(this.unifEye, eye[0], eye[1], eye[2]); + } + if(this.unifRef !== -1) { + gl.uniform3f(this.unifRef, ref[0], ref[1], ref[2]); + } + if(this.unifUp !== -1) { + gl.uniform3f(this.unifUp, up[0], up[1], up[2]); + } + } + + setDimensions(width: number, height: number) { + this.use(); + if(this.unifDimensions !== -1) { + gl.uniform2f(this.unifDimensions, width, height); + } + } + + setModelMatrix(model: mat4) { + this.use(); + if (this.unifModel !== -1) { + gl.uniformMatrix4fv(this.unifModel, false, model); + } + + if (this.unifModelInvTr !== -1) { + let modelinvtr: mat4 = mat4.create(); + mat4.transpose(modelinvtr, model); + mat4.invert(modelinvtr, modelinvtr); + gl.uniformMatrix4fv(this.unifModelInvTr, false, modelinvtr); + } + } + + setViewProjMatrix(vp: mat4) { + this.use(); + if (this.unifViewProj !== -1) { + gl.uniformMatrix4fv(this.unifViewProj, false, vp); + } + } + + setGeometryColor(color: vec4) { + this.use(); + if (this.unifColor !== -1) { + gl.uniform4fv(this.unifColor, color); + } + } + + setNoiseColor(color: vec4) { + this.use(); + if (this.unifNoiseColor !== -1) { + gl.uniform4fv(this.unifNoiseColor, color); + } + } + draw(d: Drawable) { + this.use(); + + if (this.attrPos != -1 && d.bindPos()) { + gl.enableVertexAttribArray(this.attrPos); + gl.vertexAttribPointer(this.attrPos, 4, gl.FLOAT, false, 0, 0); + } + + if (this.attrNor != -1 && d.bindNor()) { + gl.enableVertexAttribArray(this.attrNor); + gl.vertexAttribPointer(this.attrNor, 4, gl.FLOAT, false, 0, 0); + } + + d.bindIdx(); + gl.drawElements(d.drawMode(), d.elemCount(), gl.UNSIGNED_INT, 0); + + if (this.attrPos != -1) gl.disableVertexAttribArray(this.attrPos); + if (this.attrNor != -1) gl.disableVertexAttribArray(this.attrNor); + } + drawLine(d: Drawable) { + this.use(); + + if (this.attrPos != -1 && d.bindPos()) { + gl.enableVertexAttribArray(this.attrPos); + gl.vertexAttribPointer(this.attrPos, 4, gl.FLOAT, false, 0, 0); + } + + if (this.attrNor != -1 && d.bindNor()) { + gl.enableVertexAttribArray(this.attrNor); + gl.vertexAttribPointer(this.attrNor, 4, gl.FLOAT, false, 0, 0); + } + + d.bindIdx(); + gl.drawElements(gl.LINE_LOOP, d.elemCount(), gl.UNSIGNED_INT, 0); + + if (this.attrPos != -1) gl.disableVertexAttribArray(this.attrPos); + if (this.attrNor != -1) gl.disableVertexAttribArray(this.attrNor); + } +}; + +export default ShaderProgram; diff --git a/src/rendering/gl/sdfs.json b/src/rendering/gl/sdfs.json new file mode 100644 index 0000000..e27dac5 --- /dev/null +++ b/src/rendering/gl/sdfs.json @@ -0,0 +1 @@ +{"pyramid": [[[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]], [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 0.0006404371233657002, 0.001013775123283267, -0.0008194190450012684, -0.001357257249765098, -0.0005523401196114719, 0.0009646675898693502, -0.00042024508002214134, 0.0011131975334137678, 1.0], [1.0, 0.1626695990562439, 0.12559188902378082, 0.12618127465248108, 0.12595340609550476, 0.12579657137393951, 0.12580516934394836, 0.1257726103067398, 0.1626695990562439, 1.0], [1.0, 0.32818543910980225, 0.25361067056655884, 0.2537778317928314, 0.25384846329689026, 0.25388872623443604, 0.25390633940696716, 0.2536560297012329, 0.3282470703125, 1.0], [1.0, 0.49355021119117737, 0.3854247033596039, 0.38171854615211487, 0.3819630742073059, 0.3818628191947937, 0.3817989230155945, 0.38533660769462585, 0.49363693594932556, 1.0], [1.0, 0.6584144830703735, 0.5332039594650269, 0.5097784996032715, 0.5098821520805359, 0.5098782777786255, 0.509715735912323, 0.5331319570541382, 0.6586779952049255, 1.0], [1.0, 0.8237737417221069, 0.6888783574104309, 0.6376650333404541, 0.637822687625885, 0.6377705931663513, 0.6376252770423889, 0.6886281371116638, 0.8237027525901794, 1.0], [1.0, 0.9883724451065063, 0.8482103943824768, 0.7725545763969421, 0.7655360102653503, 0.7654853463172913, 0.7724708914756775, 0.8479803204536438, 0.9885831475257874, 1.0], [1.0, 1.1533149480819702, 1.0087388753890991, 0.9171014428138733, 0.8930988311767578, 0.8931118249893188, 0.9171884059906006, 1.008906602859497, 1.1533420085906982, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]], [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 0.0010097573976963758, -0.0008302137721329927, -0.0007914174348115921, -0.0012329904129728675, -0.0006148703396320343, -0.0013791171368211508, -0.0008302137721329927, 0.0003622045333031565, 1.0], [1.0, 0.12576685845851898, -0.1268102377653122, -0.12695631384849548, -0.12709377706050873, -0.12701456248760223, -0.12699124217033386, -0.12683512270450592, 0.1255984902381897, 1.0], [1.0, 0.25366687774658203, -0.0011037244694307446, -0.001164254266768694, 0.000864448316860944, -0.001099669374525547, 0.0013848909875378013, 0.0015998994931578636, 0.2537601590156555, 1.0], [1.0, 0.3851626515388489, 0.1635880172252655, 0.1264498233795166, 0.12651126086711884, 0.12648160755634308, 0.1263996958732605, 0.16384819149971008, 0.3854372799396515, 1.0], [1.0, 0.5329083204269409, 0.3289731740951538, 0.25425371527671814, 0.2544251084327698, 0.25443413853645325, 0.25434610247612, 0.32906854152679443, 0.532935619354248, 1.0], [1.0, 0.6889408826828003, 0.49354538321495056, 0.385984867811203, 0.382230281829834, 0.38228243589401245, 0.3856672942638397, 0.4937182068824768, 0.6887241005897522, 1.0], [1.0, 0.8481928110122681, 0.6584433913230896, 0.533184826374054, 0.509881854057312, 0.5098750591278076, 0.5333124995231628, 0.6584704518318176, 0.847989559173584, 1.0], [1.0, 1.0087432861328125, 0.8235989809036255, 0.6887488961219788, 0.6374470591545105, 0.637518048286438, 0.6887436509132385, 0.8235605359077454, 1.008988380432129, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]], [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 0.0011295118601992726, -0.0012312468606978655, -0.001510994741693139, -0.0005862406105734408, -0.0017501187976449728, -0.0011040003737434745, -0.0008627212373539805, -0.0011758864857256413, 1.0], [1.0, 0.12592966854572296, -0.12695695459842682, -0.28557780385017395, -0.28566858172416687, -0.2856003940105438, -0.2855451703071594, -0.12705743312835693, 0.1259646862745285, 1.0], [1.0, 0.25385910272598267, -0.000897408346645534, -0.25506392121315, -0.2552129924297333, -0.2552545368671417, -0.2550577223300934, 0.0005415224004536867, 0.25373995304107666, 1.0], [1.0, 0.38185203075408936, 0.12641000747680664, -0.12758657336235046, -0.1277392953634262, -0.12770357728004456, -0.12754270434379578, 0.1262977421283722, 0.3818396329879761, 1.0], [1.0, 0.5098083019256592, 0.25423234701156616, -0.0011663972400128841, -0.0008739389013499022, -0.0008065979927778244, -0.000623403349891305, 0.25423571467399597, 0.5097689032554626, 1.0], [1.0, 0.637701690196991, 0.38570621609687805, 0.16357211768627167, 0.12678511440753937, 0.1266631931066513, 0.16359908878803253, 0.3857845664024353, 0.6376041173934937, 1.0], [1.0, 0.772468626499176, 0.5331932902336121, 0.328734815120697, 0.25432756543159485, 0.2542959153652191, 0.3286946415901184, 0.5334672331809998, 0.7725951671600342, 1.0], [1.0, 0.9171755909919739, 0.6887723207473755, 0.4939853250980377, 0.3856949508190155, 0.38564494252204895, 0.49336928129196167, 0.6886992454528809, 0.9173536896705627, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]], [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 0.0006824881420470774, -0.0006947120418772101, -0.0006541340844705701, -0.0012864663731306791, -0.0011640948941931129, -0.0020663775503635406, -0.0009593767463229597, -0.0011552681680768728, 1.0], [1.0, 0.12579673528671265, -0.12711471319198608, -0.2857009470462799, -0.2857173681259155, -0.2857173681259155, -0.2856813073158264, -0.1270427703857422, 0.12607857584953308, 1.0], [1.0, 0.253888875246048, -0.001444671186618507, -0.25527238845825195, -0.5108662843704224, -0.5109004378318787, -0.25525137782096863, -0.00041655535460449755, 0.25391685962677, 1.0], [1.0, 0.38186296820640564, 0.12648175656795502, -0.12771134078502655, -0.38325992226600647, -0.38328754901885986, -0.12771351635456085, 0.1265140026807785, 0.3819524347782135, 1.0], [1.0, 0.509920060634613, 0.25447264313697815, -0.002208929043263197, -0.25555384159088135, -0.2555282711982727, -0.0010503805242478848, 0.25454384088516235, 0.5098822116851807, 1.0], [1.0, 0.6377652883529663, 0.3822682797908783, 0.12694431841373444, -0.12769865989685059, -0.1277094930410385, 0.12659896910190582, 0.3822551369667053, 0.6377846598625183, 1.0], [1.0, 0.765529990196228, 0.5099227428436279, 0.25433826446533203, -0.0008789091370999813, -0.0006142298225313425, 0.2542590796947479, 0.5099121332168579, 0.7654711604118347, 1.0], [1.0, 0.8931118249893188, 0.6375483870506287, 0.38540777564048767, 0.1635458618402481, 0.1633416712284088, 0.38534557819366455, 0.6374965906143188, 0.8931081295013428, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]], [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], [1.0, -0.000599591585341841, -0.0009294410701841116, -0.0013727735495194793, -0.0012864663731306791, -0.0012864663731306791, -0.0010405534412711859, -0.0016957707703113556, -0.0011306926608085632, 1.0], [1.0, 0.12594544887542725, -0.1270475685596466, -0.285618394613266, -0.2857173681259155, -0.2857173681259155, -0.285665363073349, -0.1270182579755783, 0.12579673528671265, 1.0], [1.0, 0.2539599537849426, -0.0016617474611848593, -0.2552013397216797, -0.5108641386032104, -0.5108848214149475, -0.255208283662796, -0.0015989119419828057, 0.2538887560367584, 1.0], [1.0, 0.38190436363220215, 0.12660805881023407, -0.1277005970478058, -0.38326653838157654, -0.3832797110080719, -0.1276606172323227, 0.12642896175384521, 0.38186296820640564, 1.0], [1.0, 0.5098822116851807, 0.2543942928314209, -0.0005073864012956619, -0.25557151436805725, -0.2555442154407501, -0.0009592815185897052, 0.25447264313697815, 0.5099241137504578, 1.0], [1.0, 0.6378100514411926, 0.38233381509780884, 0.12665900588035583, -0.1276712566614151, -0.12764576077461243, 0.126631960272789, 0.3822789192199707, 0.6377964019775391, 1.0], [1.0, 0.7654834389686584, 0.5098315477371216, 0.2542371153831482, -0.0012572050327435136, -0.0007931494037620723, 0.2542271018028259, 0.5099264979362488, 0.7654818296432495, 1.0], [1.0, 0.8930597305297852, 0.6373831033706665, 0.38567689061164856, 0.16384251415729523, 0.1634983867406845, 0.3854624032974243, 0.6374683380126953, 0.893080472946167, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]], [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], [1.0, -0.0010880096815526485, -0.0013870310503989458, -0.0015982170589268208, -0.0017341859638690948, -0.0014519531978294253, -0.0006524159689433873, -0.0007396694854833186, -0.0005450314492918551, 1.0], [1.0, 0.12578564882278442, -0.1269819438457489, -0.2855352759361267, -0.2857148349285126, -0.28572893142700195, -0.2855724096298218, -0.12705951929092407, 0.12600713968276978, 1.0], [1.0, 0.2537890374660492, -0.0005901223048567772, -0.2551180124282837, -0.25522762537002563, -0.2552168369293213, -0.2550913989543915, 0.0009970751125365496, 0.253816157579422, 1.0], [1.0, 0.3817545175552368, 0.12633253633975983, -0.12753379344940186, -0.127704456448555, -0.1277032345533371, -0.12747354805469513, 0.1264723837375641, 0.3818511664867401, 1.0], [1.0, 0.5096901059150696, 0.2543070912361145, -0.0005293629947118461, -0.002220739610493183, -0.0013234867947176099, -0.0005594691610895097, 0.25431403517723083, 0.5096808075904846, 1.0], [1.0, 0.6376391649246216, 0.385623037815094, 0.16391621530056, 0.12667404115200043, 0.12673169374465942, 0.163626030087471, 0.3857404291629791, 0.6375594735145569, 1.0], [1.0, 0.7725631594657898, 0.5332662463188171, 0.32868239283561707, 0.2543559670448303, 0.2542693316936493, 0.32895517349243164, 0.5333052277565002, 0.7724864482879639, 1.0], [1.0, 0.9171220660209656, 0.6888110637664795, 0.4935992956161499, 0.3854934871196747, 0.38553908467292786, 0.4936208724975586, 0.6889470815658569, 0.9172965884208679, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]], [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 0.0006115819560363889, -0.0008302137721329927, -0.0011269926326349378, -0.0014219429576769471, -0.0010457378812134266, -0.000818391446955502, -0.0008302137721329927, 0.0011682227486744523, 1.0], [1.0, 0.12587852776050568, -0.12683160603046417, -0.1270083487033844, -0.12706704437732697, -0.12706762552261353, -0.12707173824310303, -0.1268574744462967, 0.12585969269275665, 1.0], [1.0, 0.25364771485328674, 0.0010111185256391764, -0.0011621526209637523, -0.001288488507270813, -0.0009433922823518515, -0.0014097961829975247, -0.0016429958632215858, 0.2536129355430603, 1.0], [1.0, 0.385254830121994, 0.1637500375509262, 0.1264212429523468, 0.12648175656795502, 0.12660376727581024, 0.12652966380119324, 0.1635880321264267, 0.38556888699531555, 1.0], [1.0, 0.5332929491996765, 0.3287302851676941, 0.2543276250362396, 0.254399836063385, 0.25444284081459045, 0.25420284271240234, 0.32867637276649475, 0.533341646194458, 1.0], [1.0, 0.6888860464096069, 0.4937160015106201, 0.3857542872428894, 0.3822523057460785, 0.3822524845600128, 0.3856302797794342, 0.4935930669307709, 0.6887911558151245, 1.0], [1.0, 0.8479198217391968, 0.6587476134300232, 0.5334057807922363, 0.5098902583122253, 0.5099281072616577, 0.533384382724762, 0.6584924459457397, 0.8478977084159851, 1.0], [1.0, 1.008861780166626, 0.8234742879867554, 0.6888172626495361, 0.6374922394752502, 0.637464702129364, 0.6887773871421814, 0.8237693309783936, 1.0088541507720947, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]], [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], [1.0, -0.000609725306276232, 0.0015690225409343839, -0.0010630121687427163, -0.0013591103488579392, -0.0008301475900225341, -0.0008249222300946712, -0.0009612178546376526, 0.0013091220753267407, 1.0], [1.0, 0.1626695990562439, 0.1255403310060501, 0.1256980150938034, 0.12579673528671265, 0.12595833837985992, 0.12591256201267242, 0.1260053664445877, 0.1626695990562439, 1.0], [1.0, 0.32860928773880005, 0.2537544369697571, 0.2537400722503662, 0.25387364625930786, 0.25392282009124756, 0.2537502348423004, 0.25374844670295715, 0.32851332426071167, 1.0], [1.0, 0.49341335892677307, 0.3856588900089264, 0.38178569078445435, 0.38186296820640564, 0.38192611932754517, 0.38182637095451355, 0.385307639837265, 0.49329349398612976, 1.0], [1.0, 0.6583050489425659, 0.5330289006233215, 0.5097119212150574, 0.5098875164985657, 0.5098729133605957, 0.5096933245658875, 0.5334555506706238, 0.658399760723114, 1.0], [1.0, 0.8235777020454407, 0.6887555718421936, 0.637646496295929, 0.6377848386764526, 0.6377888917922974, 0.6375730633735657, 0.6886337995529175, 0.8235220313072205, 1.0], [1.0, 0.9885818958282471, 0.8480232954025269, 0.7726991772651672, 0.7654982805252075, 0.7654973864555359, 0.7725403308868408, 0.8479831218719482, 0.9884309768676758, 1.0], [1.0, 1.1534879207611084, 1.0089747905731201, 0.9172266721725464, 0.8931127190589905, 0.8931043744087219, 0.9173002243041992, 1.008895993232727, 1.1533633470535278, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]], [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]]]} \ No newline at end of file diff --git a/src/shaders/flat-frag.glsl b/src/shaders/flat-frag.glsl new file mode 100644 index 0000000..fddb9b5 --- /dev/null +++ b/src/shaders/flat-frag.glsl @@ -0,0 +1,12 @@ +precision highp float; + +uniform vec3 u_Eye, u_Ref, u_Up; +uniform vec2 u_Dimensions; +uniform float u_Time; + +in vec2 fs_Pos; +out vec4 out_Col; + +void main() { + out_Col = vec4(0.5 * (fs_Pos + vec2(1.0)), 0.5 * (sin(u_Time * 3.14159 * 0.01) + 1.0), 1.0); +} \ No newline at end of file diff --git a/src/shaders/flat-vert.glsl b/src/shaders/flat-vert.glsl new file mode 100644 index 0000000..1905d27 --- /dev/null +++ b/src/shaders/flat-vert.glsl @@ -0,0 +1,11 @@ +precision highp float; + +// The vertex shader used to render the background of the scene + +in vec4 vs_Pos; +out vec2 fs_Pos; + +void main() { + fs_Pos = vs_Pos.xy; + gl_Position = vs_Pos; +} \ No newline at end of file diff --git a/src/shaders/lambert-frag.glsl b/src/shaders/lambert-frag.glsl new file mode 100644 index 0000000..7c56682 --- /dev/null +++ b/src/shaders/lambert-frag.glsl @@ -0,0 +1,43 @@ + + +// This is a fragment shader. If you've opened this file first, please +// open and read lambert.vert.glsl before reading on. +// Unlike the vertex shader, the fragment shader actually does compute +// the shading of geometry. For every pixel in your program's output +// screen, the fragment shader is run for every bit of geometry that +// particular pixel overlaps. By implicitly interpolating the position +// data passed into the fragment shader by the vertex shader, the fragment shader +// can compute what color to apply to its pixel based on things like vertex +// position, light position, and vertex color. +precision highp float; + +uniform vec4 u_Color; // The color with which to render this instance of geometry. + +// These are the interpolated values out of the rasterizer, so you can't know +// their specific values without knowing the vertices that contributed to them +in vec4 fs_Nor; +in vec4 fs_LightVec; +in vec4 fs_Col; + +out vec4 out_Col; // This is the final output color that you will see on your + // screen for the pixel that is currently being processed. + +void main() +{ + // Material base color (before shading) + vec4 diffuseColor = u_Color; + + // Calculate the diffuse term for Lambert shading + float diffuseTerm = dot(normalize(fs_Nor), normalize(fs_LightVec)); + // Avoid negative lighting values + // diffuseTerm = clamp(diffuseTerm, 0, 1); + + float ambientTerm = 0.2; + + float lightIntensity = diffuseTerm + ambientTerm; //Add a small float value to the color multiplier + //to simulate ambient lighting. This ensures that faces that are not + //lit by our point light are not completely black. + + // Compute final shaded color + out_Col = vec4(diffuseColor.rgb * lightIntensity, diffuseColor.a); +} diff --git a/src/shaders/lambert-vert.glsl b/src/shaders/lambert-vert.glsl new file mode 100644 index 0000000..86411eb --- /dev/null +++ b/src/shaders/lambert-vert.glsl @@ -0,0 +1,53 @@ + + +//This is a vertex shader. While it is called a "shader" due to outdated conventions, this file +//is used to apply matrix transformations to the arrays of vertex data passed to it. +//Since this code is run on your GPU, each vertex is transformed simultaneously. +//If it were run on your CPU, each vertex would have to be processed in a FOR loop, one at a time. +//This simultaneous transformation allows your program to run much faster, especially when rendering +//geometry with millions of vertices. + +uniform mat4 u_Model; // The matrix that defines the transformation of the + // object we're rendering. In this assignment, + // this will be the result of traversing your scene graph. + +uniform mat4 u_ModelInvTr; // The inverse transpose of the model matrix. + // This allows us to transform the object's normals properly + // if the object has been non-uniformly scaled. + +uniform mat4 u_ViewProj; // The matrix that defines the camera's transformation. + // We've written a static matrix for you to use for HW2, + // but in HW3 you'll have to generate one yourself + +in vec4 vs_Pos; // The array of vertex positions passed to the shader + +in vec4 vs_Nor; // The array of vertex normals passed to the shader + +in vec4 vs_Col; // The array of vertex colors passed to the shader. + +out vec4 fs_Nor; // The array of normals that has been transformed by u_ModelInvTr. This is implicitly passed to the fragment shader. +out vec4 fs_LightVec; // The direction in which our virtual light lies, relative to each vertex. This is implicitly passed to the fragment shader. +out vec4 fs_Col; // The color of each vertex. This is implicitly passed to the fragment shader. + +const vec4 lightPos = vec4(5, 5, 3, 1); //The position of our virtual light, which is used to compute the shading of + //the geometry in the fragment shader. + +void main() +{ + fs_Col = vs_Col; // Pass the vertex colors to the fragment shader for interpolation + + mat3 invTranspose = mat3(u_ModelInvTr); + fs_Nor = vec4(invTranspose * vec3(vs_Nor), 0); // Pass the vertex normals to the fragment shader for interpolation. + // Transform the geometry's normals by the inverse transpose of the + // model matrix. This is necessary to ensure the normals remain + // perpendicular to the surface after the surface is transformed by + // the model matrix. + + + vec4 modelposition = u_Model * vs_Pos; // Temporarily store the transformed vertex positions for use below + + fs_LightVec = lightPos - modelposition; // Compute the direction in which the light source lies + + gl_Position = u_ViewProj * modelposition;// gl_Position is a built-in variable of OpenGL which is + // used to render the final positions of the geometry's vertices +} diff --git a/src/shaders/noise.glsl b/src/shaders/noise.glsl new file mode 100644 index 0000000..a81b6db --- /dev/null +++ b/src/shaders/noise.glsl @@ -0,0 +1,275 @@ +// so called "canonical" pseudoranom +float random(vec2 co){ + return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453); +} + +float random1d(float x){ + return random(vec2(x, 1.337)); +} + +float random1d2(float x){ + return (1.0 + random(vec2(x, 1.337)))/2.0; +} + +float random3d(vec3 inp){ + return random1d(random1d(random1d(inp.x) * inp.y) * inp.z); +} + + +int inc(int num){ + num++; + return num; +} + +float grad(int hash, float x, float y, float z) +{ + switch(hash & 0xF) + { + case 0x0: return x + y; + case 0x1: return -x + y; + case 0x2: return x - y; + case 0x3: return -x - y; + case 0x4: return x + z; + case 0x5: return -x + z; + case 0x6: return x - z; + case 0x7: return -x - z; + case 0x8: return y + z; + case 0x9: return -y + z; + case 0xA: return y - z; + case 0xB: return -y - z; + case 0xC: return y + x; + case 0xD: return -y + z; + case 0xE: return y - x; + case 0xF: return -y - z; + default: return 0.0; + } +} + +float fade(float t) { + + return t * t * t * (t * (t * 6.0 - 15.0) + 10.0); +} + +int p[512] = int[512](151,160,137,91,90,15, + 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, + 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, + 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, + 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, + 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, + 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, + 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, + 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, + 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, + 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, + 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, + 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180,151,160,137,91,90,15, + 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, + 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, + 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, + 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, + 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, + 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, + 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, + 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, + 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, + 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, + 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, + 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180); + + +float lerp(float a, float b, float x) { + return a + x * (b - a); +} + +float lerp2(float a, float b, float x){ + return a*(1.0-x) + b*x; +} + + +float perlin(float x, float y, float z) { + // if(repeat > 0) { + // x = x%repeat; + // y = y%repeat; + // z = z%repeat; + // } + + + int xi = int(x) & 255; + int yi = int(y) & 255; + int zi = int(z) & 255; + float xf = x-floor(x); + float yf = y-floor(y); + float zf = z-floor(z); + float u = fade(xf); + float v = fade(yf); + float w = fade(zf); + + int aaa, aba, aab, abb, baa, bba, bab, bbb; + aaa = p[p[p[ xi ]+ yi ]+ zi ]; + aba = p[p[p[ xi ]+inc(yi)]+ zi ]; + aab = p[p[p[ xi ]+ yi ]+inc(zi)]; + abb = p[p[p[ xi ]+inc(yi)]+inc(zi)]; + baa = p[p[p[inc(xi)]+ yi ]+ zi ]; + bba = p[p[p[inc(xi)]+inc(yi)]+ zi ]; + bab = p[p[p[inc(xi)]+ yi ]+inc(zi)]; + bbb = p[p[p[inc(xi)]+inc(yi)]+inc(zi)]; + + float x1, x2, y1, y2; + x1 = lerp( grad (aaa, xf , yf , zf), // The gradient function calculates the dot product between a pseudorandom + grad (baa, xf-1.0, yf , zf), // gradient vector and the vector from the input coordinate to the 8 + u); // surrounding points in its unit cube. + x2 = lerp( grad (aba, xf , yf-1.0, zf), // This is all then lerped together as a sort of weighted average based on the faded (u,v,w) + grad (bba, xf-1.0, yf-1.0, zf), // values we made earlier. + u); + y1 = lerp(x1, x2, v); + + x1 = lerp( grad (aab, xf , yf , zf-1.0), + grad (bab, xf-1.0, yf , zf-1.0), + u); + x2 = lerp( grad (abb, xf , yf-1.0, zf-1.0), + grad (bbb, xf-1.0, yf-1.0, zf-1.0), + u); + y2 = lerp (x1, x2, v); + + return (lerp (y1, y2, w)+1.0)/2.0; // For convenience we bind the result to 0 - 1 (theoretical min/max before is [-1, 1]) +} + + + + +float bilinear_interp(float a, float b, float c, float d, float x, float y){ + + float left = lerp(a, b, x); + float right = lerp(c, d, x); + return lerp(left, right, y); +} + +float trilinear_interp(float a, float b, float c, float d, float e, float f, float g, float h, float x, float y, float z){ + float bottom = bilinear_interp(a, b, c, d, x, y); + float top = bilinear_interp(e, f, g, h, x, y); + return lerp(bottom, top, z); +} + +float cos_interp1(float a, float b, float x){ + float cos_t = (1.0 - cos(x*3.41459)) * 0.5; + return lerp(a, b, cos_t); +} + +float trilinear_interp2(float a, float b, float c, float d, float e, float f, float g, float h, float x, float y, float z){ + // adapted from https://en.wikipedia.org/wiki/Trilinear_interpolation + + float xd = (x - floor(x)); + float yd = (y - floor(y)); + float zd = (z - floor(z)); + + float c00 = cos_interp1(a, d, xd); + float c01 = cos_interp1(b, c, xd); + float c10 = cos_interp1(e, h, xd); + float c11 = cos_interp1(f, g, xd); + + float c0 = cos_interp1(c00, c10, yd); + float c1 = cos_interp1(c01, c11, yd); + + float cf = cos_interp1(c0, c1, zd); + + return cf; +} + +// so called "canonical" pseudoranom +float random_1(vec2 co){ + return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453); +} + +float random1d_1(float x){ + return random_1(vec2(x, 1.337)); +} + +float random3d_1(vec3 inp){ + return random1d_1(random1d_1(random1d_1(inp.x) * inp.y) * inp.z); +} + +// trilinear +// const float lattice_spacing = 0.1; + +// lattice point before +float l_b(float d, float ls){ + return floor(d / ls) * ls; +} + +// lattice point after +float l_a(float d, float ls){ + return ceil(d / ls) * ls; +} + +float interp_noise(float x, float y, float z, float ls){ + // interpolating the surrounding lattice values (for 3D, this means the surrounding eight 'corner' points) + + // start by assigning lattice as whole numbers to start + float a = random3d_1(vec3(l_b(x, ls), l_b(y, ls), l_b(z, ls))); + float b = random3d_1(vec3(l_b(x, ls), l_a(y, ls), l_b(z, ls))); + float c = random3d_1(vec3(l_a(x, ls), l_a(y, ls), l_b(z, ls))); + float d = random3d_1(vec3(l_a(x, ls), l_a(y, ls), l_b(z, ls))); + float e = random3d_1(vec3(l_b(x, ls), l_b(y, ls), l_a(z, ls))); + float f = random3d_1(vec3(l_b(x, ls), l_a(y, ls), l_a(z, ls))); + float g = random3d_1(vec3(l_a(x, ls), l_a(y, ls), l_a(z, ls))); + float h = random3d_1(vec3(l_a(x, ls), l_b(y, ls), l_a(z, ls))); + + return trilinear_interp2(a, b, c, d, e, f, g, h, x, y, z); +} + +const float N_OCTAVES = 2.0; +const float PERSISTANCE = 1.0 / 2.0; +const float lattice_spacing_mod = 0.002; +const float shift_freq = 100.0; + +float fbm3d(float x, float y, float z){ + float total = 0.0; + for (float i = 0.0; i < N_OCTAVES; ++i){ + float frequency = pow(2.0, i); + //float power = pow(2.0, i); + float amplitude = pow(PERSISTANCE, i); + + total += amplitude * interp_noise(x, y, z, (1.0/(frequency * 1000.0)) * lattice_spacing_mod); + } + return total / 1.0; +} + +float mod289(float x){return x - floor(x * (1.0 / 289.0)) * 289.0;} +vec4 mod289(vec4 x){return x - floor(x * (1.0 / 289.0)) * 289.0;} +vec4 perm(vec4 x){return mod289(((x * 34.0) + 1.0) * x);} + +float noise_ref(vec3 p){ + vec3 a = floor(p); + vec3 d = p - a; + d = d * d * (3.0 - 2.0 * d); + + vec4 b = a.xxyy + vec4(0.0, 1.0, 0.0, 1.0); + vec4 k1 = perm(b.xyxy); + vec4 k2 = perm(k1.xyxy + b.zzww); + + vec4 c = k2 + a.zzzz; + vec4 k3 = perm(c); + vec4 k4 = perm(c + 1.0); + + vec4 o1 = fract(k3 * (1.0 / 41.0)); + vec4 o2 = fract(k4 * (1.0 / 41.0)); + + vec4 o3 = o2 * d.z + o1 * (1.0 - d.z); + vec2 o4 = o3.yw * d.x + o3.xz * (1.0 - d.x); + + return o4.y * d.y + o4.x * (1.0 - d.y); +} + + +float fbm3d_2(vec3 x) { + float v = 0.0; + + vec3 shift = vec3(shift_freq); + for (float i = 0.0; i < N_OCTAVES; ++i) { + float amplitude = pow(PERSISTANCE, i); + v += amplitude * noise_ref(x); + x = x * 2.0 + shift; + + } + return v; +} \ No newline at end of file diff --git a/src/shaders/sdf-compose.glsl b/src/shaders/sdf-compose.glsl new file mode 100644 index 0000000..8952393 --- /dev/null +++ b/src/shaders/sdf-compose.glsl @@ -0,0 +1,142 @@ + + + +float smoothUnion( float d1, float d2, float k ) { + float h = clamp( 0.5 + 0.5*(d2-d1)/k, 0.0, 1.0 ); + return mix( d2, d1, h ) - k*h*(1.0-h); } + + +float smoothSubtraction( float d1, float d2, float k ) +{ + float h = clamp( 0.5 - 0.5*(d2+d1)/k, 0.0, 1.0 ); + return mix( d2, -d1, h ) + k*h*(1.0-h); +} + +float smoothIntersection( float d1, float d2, float k ) +{ + float h = clamp( 0.5 - 0.5*(d2-d1)/k, 0.0, 1.0 ); + return mix( d2, d1, h ) + k*h*(1.0-h); +} + +// non smooth combinations https://www.ronja-tutorials.com/post/035-2d-sdf-combination/ + +float flatUnion(float shape1, float shape2){ + return min(shape1, shape2); +} + +float flatIntersection(float shape1, float shape2){ + return max(shape1, shape2); +} + +float flatSubtraction(float base, float subtraction){ + return max(base, -subtraction); +} + +//float flatInterpolatation(float shape1, float shape2, float amount){ +// return lerp(shape1, shape2, amount); +//} + +vec3 rotate(vec3 q, vec3 rot){ + mat4 Rx = mat4( + vec4(1, 0, 0, 0), + vec4(0, cos(rot.x), -sin(rot.x), 0), + vec4(0, sin(rot.x), cos(rot.x), 0), + vec4(0, 0, 0, 1)); + mat4 Ry = mat4( + vec4(cos(rot.y), 0, sin(rot.y), 0), + vec4(0, 1, 0, 0), + vec4(-sin(rot.y), 0, cos(rot.y), 0), + vec4(0, 0, 0, 1)); + mat4 Rz = mat4( + vec4(cos(rot.z), -sin(rot.z), 0, 0), + vec4(sin(rot.z), cos(rot.z), 0, 0), + vec4(0, 0, 1, 0), + vec4(0, 0, 0, 1)); + return (vec4(q, 1) * inverse(Rz * Ry * Rx)).xyz; +} + +vec3 translate(vec3 q, vec3 trans){ + + + // Translate to (3, 3, 3) + mat4 T = mat4( + vec4(1, 0, 0, trans.x), + vec4(0, 1, 0, trans.y), + vec4(0, 0, 1, trans.z), + vec4(0, 0, 0, 1)); + return (vec4(q, 1) * inverse(T)).xyz; +} + +vec3 transform(vec3 q, vec3 trans){ + + + // Translate to (3, 3, 3) + mat4 T = mat4( + vec4(1, 0, 0, trans.x), + vec4(0, 1, 0, trans.y), + vec4(0, 0, 1, trans.z), + vec4(0, 0, 0, 1)); + return (vec4(q, 1) * inverse(T)).xyz; +} + +vec3 transform(vec3 q, vec3 rot, vec3 trans){ + + + // Rotation in XY + mat4 Rx = mat4( + vec4(1, 0, 0, 0), + vec4(0, cos(rot.x), -sin(rot.x), 0), + vec4(0, sin(rot.x), cos(rot.x), 0), + vec4(0, 0, 0, 1)); + mat4 Ry = mat4( + vec4(cos(rot.y), 0, sin(rot.y), 0), + vec4(0, 1, 0, 0), + vec4(-sin(rot.y), 0, cos(rot.y), 0), + vec4(0, 0, 0, 1)); + mat4 Rz = mat4( + vec4(cos(rot.z), -sin(rot.z), 0, 0), + vec4(sin(rot.z), cos(rot.z), 0, 0), + vec4(0, 0, 1, 0), + vec4(0, 0, 0, 1)); + + // Translate to (3, 3, 3) + mat4 T = mat4( + vec4(1, 0, 0, trans.x), + vec4(0, 1, 0, trans.y), + vec4(0, 0, 1, trans.z), + vec4(0, 0, 0, 1)); + return (vec4(q, 1) * inverse(Rz * Ry * Rx * T)).xyz; +} + +vec3 transform(vec3 q, vec3 rot, vec3 trans, vec3 scale){ + mat4 S = mat4( + vec4(1.0*scale.x, 0, 0, 0), + vec4(0, 1.0*scale.y, 0, 0), + vec4(0, 0, 1.0*scale.z, 0), + vec4(0, 0, 0, 1)); + + // Rotation in XY + mat4 Rx = mat4( + vec4(1, 0, 0, 0), + vec4(0, cos(rot.x), -sin(rot.x), 0), + vec4(0, sin(rot.x), cos(rot.x), 0), + vec4(0, 0, 0, 1)); + mat4 Ry = mat4( + vec4(cos(rot.y), 0, sin(rot.y), 0), + vec4(0, 1, 0, 0), + vec4(-sin(rot.y), 0, cos(rot.y), 0), + vec4(0, 0, 0, 1)); + mat4 Rz = mat4( + vec4(cos(rot.z), -sin(rot.z), 0, 0), + vec4(sin(rot.z), cos(rot.z), 0, 0), + vec4(0, 0, 1, 0), + vec4(0, 0, 0, 1)); + + // Translate to (3, 3, 3) + mat4 T = mat4( + vec4(1, 0, 0, trans.x), + vec4(0, 1, 0, trans.y), + vec4(0, 0, 1, trans.z), + vec4(0, 0, 0, 1)); + return (vec4(q, 1) * inverse(S * Rz * Ry * Rx * T)).xyz; +} \ No newline at end of file diff --git a/src/shaders/sdf-objects.glsl b/src/shaders/sdf-objects.glsl new file mode 100644 index 0000000..49d54e7 --- /dev/null +++ b/src/shaders/sdf-objects.glsl @@ -0,0 +1,345 @@ + + +float sphereSDF(vec3 query_position, vec3 position, float radius) +{ + return length(query_position - position) - radius; +} + +float planeSDF(vec3 queryPos, float height) +{ + return queryPos.y - height; +} + +float bumpyPlaneSDF(vec3 queryPos, float height, float u_Time) +{ + return queryPos.y - height + (0.3*(sin(queryPos.x + 5.4) * cos(queryPos.z))); +} + +float rand_3(vec2 p) +{ + return fract(sin(dot(p.xy ,vec2(12.9898,78.233))) * 43758.5453); +} + +float boxSDF( vec3 p, vec3 b) +{ + vec3 q = abs(p) - b; + return length(max(q,0.0)) + min(max(q.x,max(q.y,q.z)),0.0); + +} + +float symbol1SDF( vec3 p){ + // cross thing + return flatUnion( + boxSDF(p, vec3(0.1, 0.1, 1.0)), + boxSDF(p, vec3(1.0, 0.1, 0.1)) + ); +} + +float symbol2SDF( vec3 p){ + // star thing + float final; + final = boxSDF(p, vec3(0.1, 0.1, 1.0)); + final = flatUnion(final, boxSDF(p, vec3(1.0, 0.1, 0.1))); + final = flatUnion(final, boxSDF(rotate(p, vec3(0, PI/4.0, 0)), vec3(1.0, 0.1, 0.1))); + final = flatUnion(final, boxSDF(rotate(p, vec3(0, -PI/4.0, 0)), vec3(1.0, 0.1, 0.1))); + + return final; +} + +float symbol3SDF( vec3 p){ + // flat twist thing + float final; + final = boxSDF(p, vec3(0.1, 0.1, 1.0)); + final = flatUnion(final, boxSDF(translate(p, vec3(-1.0, 0, 0)), vec3(0.1, 0.1, 1.0))); + final = flatUnion(final, boxSDF(translate(p, vec3(1.0, 0, 0)), vec3(0.1, 0.1, 1.0))); + final = flatUnion(final, boxSDF(translate(p, vec3(0.5, 0, 0.9)), vec3(0.5, 0.1, 0.1))); + final = flatUnion(final, boxSDF(translate(p, vec3(-0.5, 0, -0.9)), vec3(0.5, 0.1, 0.1))); + + return final; +} + + +float value_noise(vec2 p) +{ + vec2 i = floor(p); + vec2 f = fract(p); + + vec2 s = smoothstep(0.0, 1.0, f); + float nx0 = mix(rand_3(i + vec2(0.0, 0.0)), rand_3(i + vec2(1.0, 0.0)), s.x); + float nx1 = mix(rand_3(i + vec2(0.0, 1.0)), rand_3(i + vec2(1.0, 1.0)), s.x); + return mix(nx0, nx1, s.y); +} + + +float bumpyPlaneSDF2(vec3 p) +{ + const int no = 3; + float tot = 0.0; + vec2 q = p.xz * 0.35; + float a = 0.5; + float f = 1.0; + for (int i = 0; i < no; ++i) + { + tot += value_noise(q * f) * a; + a *= 0.5; + f *= 2.5; + q = q * mat2(0.5, -0.866, 0.866, 0.5) * 0.65; + q += vec2(2.5, 4.8); + } + + float d1 = p.y - tot * 2.0; + + return d1; +} + +float cubeSDF(vec3 query_position, vec3 dims ) +{ + vec3 d = abs(query_position) - dims; + return min(max(d.x,max(d.y,d.z)),0.0) + length(max(d,0.0)); +} + +float capsuleSDF( vec3 queryPos, vec3 a, vec3 b, float r ) +{ + vec3 pa = queryPos - a, ba = b - a; + float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 ); + return length( pa - ba*h ) - r; +} + +// based on https://www.shadertoy.com/view/Ntd3DX +float pyramidSDF(vec3 q_position, vec3 position, float halfWidth, float halfDepth, float halfHeight) { + q_position -= position; + q_position.xz = abs(q_position.xz); + + // bottom + float s1 = abs(q_position.y) - halfHeight; + vec3 base = vec3(max(q_position.x - halfWidth, 0.0), abs(q_position.y + halfHeight), max(q_position.z - halfDepth, 0.0)); + float d1 = dot(base, base); + + vec3 q = q_position - vec3(halfWidth, -halfHeight, halfDepth); + vec3 end = vec3(-halfWidth, 2.0 * halfHeight, -halfDepth); + vec3 segment = q - end * clamp(dot(q, end) / dot(end, end), 0.0, 1.0); + float d = dot(segment, segment); + + // side + vec3 normal1 = vec3(end.y, -end.x, 0.0); + float s2 = dot(q.xy, normal1.xy); + float d2 = d; + if (dot(q.xy, -end.xy) < 0.0 && dot(q, cross(normal1, end)) < 0.0) { + d2 = s2 * s2 / dot(normal1.xy, normal1.xy); + } + // front/back + vec3 normal2 = vec3(0.0, -end.z, end.y); + float s3 = dot(q.yz, normal2.yz); + float d3 = d; + if (dot(q.yz, -end.yz) < 0.0 && dot(q, cross(normal2, -end)) < 0.0) { + d3 = s3 * s3 / dot(normal2.yz, normal2.yz); + } + return sqrt(min(min(d1, d2), d3)) * sign(max(max(s1, s2), s3)); +} + +float triprism(vec3 q_position, float halfWidth, float halfHeight, float halfDepth) { + + q_position.x = abs(q_position.x); + q_position.xy -= vec2(halfWidth, -halfHeight); + vec2 end = vec2(-halfWidth, halfHeight * 2.0); + vec2 segment = q_position.xy - end * clamp(dot(q_position.xy, end) / dot(end, end), 0.0, 1.0); + float d1 = length(segment); + if (max(segment.x, segment.y) < 0.0) { + d1 = -min(d1, q_position.y); + } + float d2 = abs(q_position.z) - halfDepth; + return length(max(vec2(d1, d2), 0.0)) + min(max(d1, d2), 0.0); +} + +// https://math.stackexchange.com/questions/1641859/distance-function-for-n-prism +float nGon(in int n, in vec2 p, in float r) { + // these 2 lines can be precomputed + float an = 6.2831853 / float(n); + float he = r * tan(0.5 * an); + + // rotate to first sector + p = -p.yx; // if you want the corner to be up + float bn = an * floor((atan(p.y, p.x) + 0.5 * an) / an); + vec2 cs = vec2(cos(bn), sin(bn)); + p = mat2(cs.x, -cs.y, cs.y, cs.x) * p; + + // side of polygon + return length(p - vec2(r, clamp(p.y, -he, he))) * sign(p.x-r); +} + +float toPrism(in float d2d, in float v, in float size) { + vec2 d = vec2(d2d, abs(v) - 0.5 * size); + return length(max(d, 0.0)) + min(max(d.x, d.y), 0.0); +} + +float nPrism(in vec3 p, in int n, in float r, in float depth) { + float d = nGon(n, p.xy, r); + return toPrism(d, p.z, depth); +} + +float sdTorus( vec3 p, vec2 t ) +{ + vec2 q = vec2(length(p.xz)-t.x,p.y); + return length(q)-t.y; +} + +float sdCappedTorus(in vec3 p, in vec2 sc, in float ra, in float rb) +{ + p.x = abs(p.x); + float k = (sc.y*p.x>sc.x*p.y) ? dot(p.xy,sc) : length(p.xy); + return sqrt( dot(p,p) + ra*ra - 2.0*ra*k ) - rb; +} + +float hourglass(vec3 p){ + return sdTorus(p, vec2(0.15, 0.03)); +} + +float randomSymbol(vec3 p, float r){ + float tot = 4.0; + if(r < 1.0/tot){ + return symbol1SDF(p); + }else if(r < 2.0/tot){ + return symbol2SDF(p); + }else if(r < 3.0/tot){ + return symbol3SDF(p); + }else{ + return sdTorus(p, vec2(0.40, 0.10)); + } +} + +float pyramidNormalSDF(vec3 p, float h, float depth, float depth_scale, float num_splits, float split_height_scale) { + //q_position -= position; + vec3 q_position = p; + + float m2 = h*h + 0.25; + + p.xz = abs(p.xz); + p.xz = (p.z>p.x) ? p.zx : p.xz; + p.xz -= 0.5; + + vec3 q = vec3( p.z, h*p.y - 0.5*p.x, h*p.x + 0.5*p.y); + + float s = max(-q.x,0.0); + float t = clamp( (q.y-0.5*p.z)/(m2+0.25), 0.0, 1.0 ); + + float a = m2*(q.x+s)*(q.x+s) + q.y*q.y; + float b = m2*(q.x+0.5*t)*(q.x+0.5*t) + (q.y-m2*t)*(q.y-m2*t); + + float d2 = min(q.y,-q.x*m2-q.y*0.5) > 0.0 ? 0.0 : min(a,b); + + float mainPyramid = sqrt( (d2+q.z*q.z)/m2 ) * sign(max(q.z,-p.y)); + + float slant = atan(0.5/h); // 1/2 base , height + float prisim1 = nPrism(transform(q_position, vec3(slant, 0, 0), vec3(0, 0, 0)), 3, 0.1, 1.0); + + float final = mainPyramid; + + //float num_splits = 15.0; + + float slant_height = sqrt(h*h + 0.25); + float greeble_height = (slant_height / num_splits) * split_height_scale * 0.5; + float greeble_width = (1.0/slant_height) * greeble_height; + + + + + for(float g_i=0.0; g_i<4.0; g_i++){ + float g_rot = g_i * (PI/2.0); +// +// for(float b_i=0.0; b_i<10.0; b_i++){ +// //bars +// +// float y_min = 0.0; +// float y_max = h; +// float _y1 = y_min + random(vec2(b_i+1.0, b_i)) * (y_max - y_min); +// +// float z_min = -0.5 * (h - _y1); +// float z_max = 0.5 * (h - _y1); +// float _z1 = z_min + random(vec2(b_i+1.0, b_i+1.0)) * (z_max - z_min); +//// _z = 0.05; +//// _y = u_NumSymbolsPerTri; +// float _x1 = 0.5 - (tan(slant) * _y1); +// vec3 prisim_transform = transform(q_position, vec3(0, g_rot, 0), vec3(0, 0, 0)); // rotate to a different pyramid face (of four) +// prisim_transform = transform(prisim_transform, vec3(0, PI/2.0, 0), vec3(_x1, _y1, _z1)); // translate to the position on the face and rotate so prism "points outward +// prisim_transform = transform(prisim_transform, vec3(-slant, 0, 0), vec3(0, 0, 0)); +// prisim_transform = transform(prisim_transform, vec3(0, random(vec2(b_i+1.0, b_i+1.0))*PI/16.0, 0), vec3(0, 0, 0)); +// float prisim = triprism(prisim_transform, 0.01, 0.01, 0.1); +// final = flatUnion(final, prisim); +// +// } + + // the main triangles that get shifted in/out + for(float i=0.0; i 0.0){ + final = flatUnion(final, prisim); + }else{ + final = flatSubtraction(final, prisim); + } + + } + + } + + // spread symbols randomly +// for(float i=0.0; i<5.0; i++){ +// float _y = random1d(i+g_i) * h; +// float _x = 0.5 - (tan(slant) * _y); +// float _z = -0.5 * (1.0-_y) + random1d(_y); +// //_z = 0.0; +// +// +// vec3 shape_transform = transform(q_position, vec3(0, g_rot, 0), vec3(0, 0, 0)); +// shape_transform = transform(shape_transform, vec3(0, PI/2.0, 0), vec3(_x, _y, _z)); +// shape_transform = transform(shape_transform, vec3(-slant+PI/2.0, 0, 0), vec3(0, 0, 0)); +// float scale = 0.05; +// shape_transform = transform(shape_transform, vec3(0, 0, 0), vec3(0, 0.02, 0), vec3(1.0 * scale, 7.0 * scale, 1.0 * scale)); +// +// float shape = randomSymbol(shape_transform, random1d(_x)); +// final = flatSubtraction(final, shape); +// +// } + + break; + } + + + + + return final; +} \ No newline at end of file diff --git a/src/shaders/sdf1-frag.glsl b/src/shaders/sdf1-frag.glsl new file mode 100644 index 0000000..f350b8a --- /dev/null +++ b/src/shaders/sdf1-frag.glsl @@ -0,0 +1,376 @@ + +precision highp float; + +uniform vec3 u_Eye, u_Ref, u_Up; +uniform vec2 u_Dimensions; + +uniform float u_NoiseHeight; + +in vec2 fs_Pos; +out vec4 out_Col; + +const int MAX_RAY_STEPS = 200; +const float DIST_MAX = 30.0; +const float FOV = 45.0; +const float EPSILON = 1E-2; +const float EPSILON_N = 1E-2; + +// const vec3 EYE = vec3(2.0, 1.5, 5.0); +// const vec3 REF = vec3(1.2, 1.0, 0.0); +const vec3 WORLD_UP = vec3(0.0, 1.0, 0.0); +const vec3 WORLD_RIGHT = vec3(-1.0, 0.0, 0.0); +const vec3 WORLD_FORWARD = vec3(0.0, 0.0, 1.0); +const vec3 LIGHT_DIR = vec3(0.6, 1.0, 0.4) * 1.5; + +const vec3 BACKGROUND_COLOR = vec3(0.5, 0.7, 0.9); + + + +struct Ray +{ + vec3 origin; + vec3 direction; +}; +struct DirectionalLight +{ + vec3 dir; + vec3 color; +}; +Ray getRay(vec2 uv) { + Ray ray; + + float len = tan(3.14159 * 0.125) * distance(u_Eye, u_Ref); + vec3 H = normalize(cross(vec3(0.0, 1.0, 0.0), u_Ref - u_Eye)); + vec3 V = normalize(cross(H, u_Eye - u_Ref)); + V *= len; + H *= len * u_Dimensions.x / u_Dimensions.y; + vec3 p = u_Ref + uv.x * H + uv.y * V; + vec3 dir = normalize(p - u_Eye); + + ray.origin = u_Eye; + ray.direction = dir; + return ray; +} + +const float NUM_HILLS = 10.0; +const float HILL_X_WIDTH = 20.0; +const float HILL_Z_WIDTH = 14.0; + +float bumpyPlane(vec3 queryPos){ + float plane = planeSDF(queryPos, -0.6); + + for(float i = 0.0; i < NUM_HILLS; i++){ + plane = smoothUnion(plane, sphereSDF(queryPos, vec3(-HILL_X_WIDTH + (random1d_1(i-0.1) * HILL_X_WIDTH * 2.0), -1.2, - (random1d_1(i+0.1) * HILL_Z_WIDTH * 2.0)), 0.5 + (2.0*random1d_1(i+0.2))), 1.0 + (0.5*random1d_1(i+0.3))); + } + return plane; + +} + +float skyPyramids(vec3 queryPos){ + return 0.0; +} + +//float weirdPyramid(vec3 queryPos){ +// float final; +// float mainPart = pyramidSDF(queryPos, vec3(0.0, -0.5, -5.0), 4.0, 4.0, 2.4); +// mainPart = flatSubtraction(mainPart, cubeSDF(queryPos, vec3(0.0, 1.8, -5.0), vec3(0.5, 0.5, 0.5))); +// float pyramideon = pyramidSDF(queryPos, vec3(0.0, 1.7, -5.0), 0.4, 0.4, 0.25); +// pyramideon = flatSubtraction(pyramideon, flatSubtraction(pyramidSDF(queryPos, vec3(0.0, 1.71, -5.0), 0.4*0.9, 0.4*1.1, 0.25*0.88), cubeSDF(queryPos, vec3(0.0, 2.2, -5.0), vec3(0.5, 0.5, 0.5)))); +// pyramideon = flatSubtraction(pyramideon, flatSubtraction(pyramidSDF(queryPos, vec3(0.0, 1.71, -5.0), 0.4*1.1, 0.4*0.9, 0.25*0.88), cubeSDF(queryPos, vec3(0.0, 2.2, -5.0), vec3(0.5, 0.5, 0.5)))); +// float skyPyramid = pyramidSDF(queryPos, vec3(0.0, 4.5, -5.0), 4.0, 4.0, -2.4); +// final = flatUnion(flatUnion(mainPart, pyramideon), skyPyramid); +// return final; +//} + + +//float sceneSDField(vec3 queryPos) +//{ +// vec3 t = transform(queryPos, vec3(0, 0, 0), vec3(-20.0, -20.0, -20.0), vec3(2, 2, 2)); +// float final; +// +// if(t.x < 0.0 || t.x > u_pyramidFieldDims.x - 1.0 || t.y < 0.0 || t.y > u_pyramidFieldDims.y - 1.0 || t.z < 0.0 || t.z > u_pyramidFieldDims.z - 1.0){ +// return 1.0; +// } +// +// float qp_idx = round(t.x) + round(t.y) * u_pyramidFieldDims.x + round(t.z) * u_pyramidFieldDims.x * u_pyramidFieldDims.y; +// return u_pyramidField[int(qp_idx)]; +// +//} + +//float sceneSDFunction(vec3 queryPos) +//{ +// return 1000000000.0; +//} +// +//float sceneSDF(vec3 queryPos){ +// return min(sceneSDFunction(queryPos), sceneSDField(queryPos)); +//} + +float culledSceneSDF(vec3 queryPos) +{ + return planeSDF(queryPos, -1.6); +} + +float sceneSDF(vec3 queryPos) +{ + + float final; + vec3 main_t = transform(queryPos, vec3(0, 0, 0), vec3(0.0, -1.5, 0), vec3(4.0, 4.0, 4.0)); + + final = pyramidNormalSDF(main_t, 0.5, + u_NoiseHeight, + 0.5, + u_Rows, + u_TriScale); + + //final = symbol3SDF(queryPos); + + + final = flatUnion(final, planeSDF(queryPos, -1.6)); + + return final; +} + +struct Intersection +{ + vec3 position; + vec3 normal; + float distance; + int material_id; +}; + +vec3 estimateNormal2(vec3 p) { + return normalize(vec3( + sceneSDF(vec3(p.x + EPSILON_N, p.y, p.z)) - sceneSDF(vec3(p.x - EPSILON_N, p.y, p.z)), + sceneSDF(vec3(p.x, p.y + EPSILON_N, p.z)) - sceneSDF(vec3(p.x, p.y - EPSILON_N, p.z)), + sceneSDF(vec3(p.x, p.y, p.z + EPSILON_N)) - sceneSDF(vec3(p.x, p.y, p.z - EPSILON_N)) + )); +} + +// https://iquilezles.org/articles/normalsSDF/ +vec3 estimateNormal( in vec3 p ) // for function f(p) +{ + const float h = EPSILON_N; // replace by an appropriate value + const vec2 k = vec2(1,-1); + return normalize( k.xyy*sceneSDF( p + k.xyy*h ) + + k.yyx*sceneSDF( p + k.yyx*h ) + + k.yxy*sceneSDF( p + k.yxy*h ) + + k.xxx*sceneSDF( p + k.xxx*h ) ); +} + +vec3 lambertColor(Intersection intersection, float daycycle){ + vec3 albedo = vec3(0.99, 0.91, 0.72); + // vec4 diffuseColor = u_Color; + + DirectionalLight lights[3]; + lights[0] = DirectionalLight(normalize(vec3(0.0, 3.0, 0.0)), + normalize(vec3(1, 1, 1))); + lights[1] = DirectionalLight(normalize(vec3(0., 1., 0.)), + normalize(vec3(124, 104, 95))); + lights[2] = DirectionalLight(normalize(-vec3(15.0, 0.0, 10.0)), + normalize(vec3(72, 53, 39))); + + vec3 norm = estimateNormal(intersection.position); + + float dayProgression = abs(sin(daycycle * 3.14159)); + vec3 color; + for(int i = 1; i < 3; ++i) { + color += albedo * + lights[i].color * + max(0.0, dot(norm, lights[i].dir)); + } + + // vec3 color = albedo * 0.1 * vec3(1.0, 1.0, 1.0) * max(0.0, dot(norm, normalize(vec3(4.0, 15.0, -10.0)))); + + // color += vec3(0.96, 0.28, 0.74) * 0.1 * max(0.0, dot(norm, normalize(vec3(0.0, 10.0, 0.0)))); + // //color = max(color, albedo*0.2); + // color += vec3(0.96, 0.88, 0.74) * dayProgression * max(0.0, dot(norm, normalize(vec3((dayProgression-0.5) * 60.0, 10.0, (dayProgression-0.5) * 40.0)))); + + return color; +} + +bool sphereIntersect(Ray r, vec3 center, float radius) +{ +//solve for tc +vec3 L = r.origin - center; +float p = dot(r.direction, L); +float q = dot(L, L) - (radius * radius); + +float discriminant = (p * p) - q; +if (discriminant < 0.0f) +{ + return true; +} +return false; +} + +Intersection getRaymarchedIntersection(vec2 uv) +{ + Ray ray = getRay(uv); + Intersection intersection; + float dist = 0.0; + vec3 queryPoint = ray.origin; + + bool culled = sphereIntersect(ray, vec3(0, -0.5, 0), 15.0); + + for (int i=0; i < MAX_RAY_STEPS; ++i) + { + float distanceToSurface; + if(culled) { + distanceToSurface = culledSceneSDF(queryPoint); + }else { + distanceToSurface = sceneSDF(queryPoint); + } + + if (distanceToSurface < EPSILON) + { + + intersection.position = queryPoint; + intersection.normal = vec3(0.0, 0.0, 1.0); + intersection.distance = length(queryPoint - ray.origin); + + return intersection; + } + dist += distanceToSurface * 0.5; + if (dist > DIST_MAX){ + intersection.distance = -1.0; + return intersection; + } + + // sphere distance + queryPoint = queryPoint + ray.direction * distanceToSurface; + } + + + intersection.distance = -1.0; + return intersection; +} + +struct skyGradient{ + vec3 midColLit; + vec3 midColUnlit; + vec3 upperCol; + vec3 lowerCol1; + vec3 lowerCol2; +}; + +const skyGradient sunMid = skyGradient( + vec3(1., 0.341 * 2., 0.09 * 2.2), + vec3(1., 0.341, 0.09), + vec3(0.5, 0.156, 0.225), + vec3(1., 0.6, 0.1), + vec3(1., 0.7, 0.1) +); + +const skyGradient sunDusk = skyGradient( + vec3(0.21, 0.2, 0.2), + vec3(0.02, 0.01, 0.01), + vec3(0.13, 0.1, 0.1), + vec3(0.05, 0.05, 0.05), + vec3(0.09, 0.05, 0.05) +); + +const skyGradient sunDay = skyGradient( + vec3(0.2, 0.69, 1.0), + vec3(0.2, 0.69, 0.96), + vec3(0.2, 0.69, 0.96), + vec3(0.92, 0.79, 0.45), + vec3(0.92, 0.82, 0.45) +); + +vec3 getSkyBackground(in vec2 uv, skyGradient colorScheme) +{ + float mid = smoothstep(0.1, 0.2, uv.y/2.0); + vec3 midCol = mix(colorScheme.midColUnlit, colorScheme.midColLit, 1. - clamp(distance(uv.x, 0.5) * 1.5, 0., 1.)); + vec3 skyColorTop = mix(midCol, colorScheme.upperCol, uv.y/2.0); + vec3 skyColorBottom = mix(colorScheme.lowerCol1, colorScheme.lowerCol2, 1. - clamp(distance(uv.x, 0.5) * 3., 0., 1.)); + vec3 skyColor = mix(skyColorBottom, skyColorTop, mid); + + return skyColor; +} + + +vec3 skyColorAtTime(vec2 uv, float daycycle){ + vec3 midColor = getSkyBackground(uv, sunMid); + vec3 duskColor = getSkyBackground(uv, sunDusk); + vec3 dayColor = getSkyBackground(uv, sunDay); + + // day night cycle should progress with peak at 0.0 / 1.0 for dusk, 0.3 and 0.7 for mid, and 0.5 for day + vec3 finalColor; + + finalColor = mix(duskColor, midColor, smoothstep(0.0, 0.2, daycycle)); + finalColor = mix(finalColor, dayColor, smoothstep(0.2, 0.5, daycycle)); + finalColor = mix(finalColor, midColor, smoothstep(0.5, 0.8, daycycle)); + finalColor = mix(finalColor, duskColor, smoothstep(0.8, 1.0, daycycle)); + //finalColor = vec3(daycycle); + + return finalColor; +} + +vec3 getSun(in vec2 uv, float opacity, float dayCycle) +{ + // float dayProgression = abs(cos(dayCycle * 3.14159)); + // vec2 st = uv; + // uv -= .5; + // uv.x *= u_Dimensions.x / u_Dimensions.y; + + // uv.y += 0.05; + // uv.y += bias(dayProgression, 0.1); + + // float radius = 0.1; + // float uvLength = 1. - length(uv); + // vec3 sun; + // float sunOpacity = 1.; + // float time = u_Time * 0.1; + + // for(int i = 0; i < 10; i++) + // { + // sunOpacity *= 0.6; + // sun += vec3(smoothstep(0.95 - radius, 0.953 - radius, uvLength) * sunOpacity) * vec3(1., 0.6, 0.); + // sun = clamp(sun, 0., 1.); + // radius *= 1.3 + sin(time) / 100.; + // } + + // sun *= opacity; + // sun.g *= 0.9; + + // vec3 sunGlow = clamp(1. - vec3(length(uv * 2.)), 0., 1.) * opacity; + // sunGlow *= smoothstep(0.1 - sin(time) / 10., 1. - sin(time) / 10., sunGlow); + + // vec3 flare = 1. - vec3(distance(vec2(st.x * 1.5 - 0.25, st.y * 2. - 0.5), vec2(0.5))) * 2. + sin(time) / 40.; + // flare = clamp(flare * vec3(1., 0.8, 0.), 0., 1.); + + // return sun + (sunGlow + flare) / 4.; + + + Ray ray = getRay(uv); + + // sun + float sunn = clamp( dot(normalize(vec3(0.0, 2.0, 10.0)), ray.direction), 0.0, 1.0 ); + + vec3 color = vec3(1.0,0.6,0.3) * pow( sunn, 256.0 ); // sun + color += 0.5 * vec3(1.0,0.6,0.3) * pow( sunn, 32.0 ); + + return color; +} + + +void main() { + //out_Col = vec4(0.5 * (fs_Pos + vec2(1.0)), 0.5 * (sin(u_Time * 3.14159 * 0.01) + 1.0), 1.0); + Intersection intersection = getRaymarchedIntersection(fs_Pos); + + vec3 albedo = vec3(0.5); + vec3 color; + float dayCycle = (1.0+cos(u_Time / 90.0))/2.0; + if (intersection.distance > 0.0){ + color = lambertColor(intersection, dayCycle); + }else{ + color = skyColorAtTime(fs_Pos, dayCycle); + color += getSun(fs_Pos, 0.5, dayCycle); + // color += skyColorAtTime(fs_Pos, 0.9); + // color = BACKGROUND_COLOR * rnd; + } + + + out_Col = vec4(color, 1.0); +} diff --git a/src/shaders/sdf1-vert.glsl b/src/shaders/sdf1-vert.glsl new file mode 100644 index 0000000..5fa2d7a --- /dev/null +++ b/src/shaders/sdf1-vert.glsl @@ -0,0 +1,16 @@ + +// The vertex shader used to render the background of the scene + +in vec4 vs_Pos; +out vec2 fs_Pos; + + + + + +void main() { + fs_Pos = vs_Pos.xy; + gl_Position = vs_Pos; + + +} diff --git a/src/shaders/toolbox.glsl b/src/shaders/toolbox.glsl new file mode 100644 index 0000000..ad489d1 --- /dev/null +++ b/src/shaders/toolbox.glsl @@ -0,0 +1,25 @@ +const float PI=3.14159265; +uniform float u_Time; +uniform float u_Rows; +uniform float u_TriScale; +uniform float u_LowTriRange; +uniform float u_HighTriRange; +uniform float u_NumSymbolsPerTri; +uniform float u_HeightT; +uniform float u_SymbolScaleT; +uniform float u_SymbolPositionT; + + + +float bias(float t, float b) { + return (t / ((((1.0/b) - 2.0)*(1.0 - t))+1.0)); +} + +float gain(float t, float g) { + if(t < 0.5){ + return bias(1.0-g, 2.0*t) / 2.0; + }else{ + return 1.0 - bias(1.0-g, 2.0 - 2.0*t) / 2.0; + } + +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..b7b680a --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "outDir": "./dist", + "sourceMap": true, + "noImplicitAny": true, + "module": "es6", + "target": "es6", + "allowJs": true, + "moduleResolution": "node", + "resolveJsonModule": true, + "allowSyntheticDefaultImports": true + } +} diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 0000000..2cce33b --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,37 @@ +const path = require('path'); + +module.exports = { + mode: process.env.NODE_ENV === 'production' ? 'production' : 'development', + entry: path.resolve(__dirname, "src/main"), + output: { + path: path.resolve(__dirname, "dist"), + filename: "bundle.js", + publicPath: '/', + }, + module: { + rules: [ + { + test: /\.ts$/, + use: 'ts-loader', + exclude: /node_modules/ + }, + { + test: /\.glsl$/, + loader: 'webpack-glsl-loader' + }, + ] + }, + resolve: { + extensions: ['.ts', '.js' ], + }, + devtool: 'source-map', + devServer: { + port: 5660, + static: { + directory: path.join(__dirname, 'dist'), + }, + client: { + overlay: true, + } + }, +};