├── .babelrc
├── .eslintignore
├── .eslintrc
├── .gitignore
├── .prettierrc
├── .travis.yml
├── LICENSE
├── README.md
├── docs
├── controls_src_index.js.html
├── core_src_index.js.html
├── fonts
│ ├── OpenSans-Bold-webfont.eot
│ ├── OpenSans-Bold-webfont.svg
│ ├── OpenSans-Bold-webfont.woff
│ ├── OpenSans-BoldItalic-webfont.eot
│ ├── OpenSans-BoldItalic-webfont.svg
│ ├── OpenSans-BoldItalic-webfont.woff
│ ├── OpenSans-Italic-webfont.eot
│ ├── OpenSans-Italic-webfont.svg
│ ├── OpenSans-Italic-webfont.woff
│ ├── OpenSans-Light-webfont.eot
│ ├── OpenSans-Light-webfont.svg
│ ├── OpenSans-Light-webfont.woff
│ ├── OpenSans-LightItalic-webfont.eot
│ ├── OpenSans-LightItalic-webfont.svg
│ ├── OpenSans-LightItalic-webfont.woff
│ ├── OpenSans-Regular-webfont.eot
│ ├── OpenSans-Regular-webfont.svg
│ └── OpenSans-Regular-webfont.woff
├── geometries_src_index.js.html
├── index.html
├── module-controls.html
├── module-core.html
├── module-geometries.html
├── scripts
│ ├── linenumber.js
│ └── prettify
│ │ ├── Apache-License-2.0.txt
│ │ ├── lang-css.js
│ │ └── prettify.js
└── styles
│ ├── jsdoc-default.css
│ ├── prettify-jsdoc.css
│ └── prettify-tomorrow.css
├── jsdoc.config.json
├── package-lock.json
├── package.json
├── packages
├── controls
│ ├── README.md
│ ├── build
│ │ ├── controls.js
│ │ ├── controls.min.js
│ │ └── controls.module.js
│ ├── package.json
│ └── src
│ │ ├── index.js
│ │ ├── orbit
│ │ └── index.js
│ │ └── utils
│ │ └── math.js
├── core
│ ├── README.md
│ ├── build
│ │ ├── core.js
│ │ ├── core.min.js
│ │ └── core.module.js
│ ├── package.json
│ └── src
│ │ ├── cameras
│ │ ├── index.js
│ │ ├── orthographic.js
│ │ └── perspective.js
│ │ ├── constants.js
│ │ ├── core
│ │ ├── composer.js
│ │ ├── lights.js
│ │ ├── mesh.js
│ │ ├── model.js
│ │ ├── object3.js
│ │ ├── pass.js
│ │ ├── performance.js
│ │ ├── renderer.js
│ │ ├── rt.js
│ │ ├── scene.js
│ │ ├── shadow-map-renderer.js
│ │ ├── texture.js
│ │ └── vector3.js
│ │ ├── gl
│ │ ├── attributes.js
│ │ ├── index.js
│ │ ├── program.js
│ │ ├── types.js
│ │ ├── ubo.js
│ │ ├── uniforms.js
│ │ └── vao.js
│ │ ├── helpers
│ │ ├── axis.js
│ │ ├── index.js
│ │ └── normal.js
│ │ ├── index.js
│ │ ├── passes
│ │ ├── basic.js
│ │ └── index.js
│ │ ├── session.js
│ │ ├── shaders
│ │ ├── basic.js
│ │ ├── billboard.js
│ │ ├── chunks
│ │ │ ├── clipping.js
│ │ │ ├── extensions.js
│ │ │ ├── fog.js
│ │ │ ├── index.js
│ │ │ ├── light.js
│ │ │ ├── noise.js
│ │ │ ├── shadow.js
│ │ │ └── ubo.js
│ │ ├── default.js
│ │ ├── index.js
│ │ └── sem.js
│ │ └── utils
│ │ ├── color.js
│ │ ├── dom.js
│ │ ├── glsl-parser.js
│ │ ├── index.js
│ │ └── math.js
├── geometries
│ ├── README.md
│ ├── build
│ │ ├── geometries.js
│ │ ├── geometries.min.js
│ │ └── geometries.module.js
│ ├── package.json
│ └── src
│ │ ├── box
│ │ └── index.js
│ │ ├── dodecahedron
│ │ └── index.js
│ │ ├── hexahedron
│ │ └── index.js
│ │ ├── icosahedron
│ │ └── index.js
│ │ ├── index.js
│ │ ├── octahedron
│ │ └── index.js
│ │ ├── plane
│ │ └── index.js
│ │ ├── polyhedra.js
│ │ ├── prism
│ │ └── index.js
│ │ ├── sphere
│ │ └── index.js
│ │ ├── tetrahedron
│ │ └── index.js
│ │ ├── torus
│ │ └── index.js
│ │ ├── torusknot
│ │ └── index.js
│ │ └── utils
│ │ ├── index.js
│ │ ├── merge.js
│ │ └── modify.js
├── physics
│ ├── README.md
│ ├── build
│ │ ├── physics.js
│ │ ├── physics.min.js
│ │ └── physics.module.js
│ ├── package.json
│ └── src
│ │ ├── colliders
│ │ ├── aabb-collider.js
│ │ └── sphere-collider.js
│ │ ├── constants.js
│ │ ├── core
│ │ ├── contacts.js
│ │ ├── force.js
│ │ ├── rigid-body.js
│ │ └── world.js
│ │ ├── index.js
│ │ └── workers
│ │ └── todo.js
└── postprocessing
│ ├── README.md
│ ├── build
│ ├── postprocessing.js
│ ├── postprocessing.min.js
│ └── postprocessing.module.js
│ ├── package.json
│ └── src
│ ├── bleach
│ └── index.js
│ ├── blur
│ ├── horizontal.js
│ ├── index.js
│ └── vertical.js
│ ├── brightness
│ └── index.js
│ ├── dot-screen
│ └── index.js
│ ├── glitch
│ └── index.js
│ ├── hue-saturation
│ └── index.js
│ ├── index.js
│ ├── noise
│ └── index.js
│ └── tilt-shift
│ ├── horizontal.js
│ ├── index.js
│ └── vertical.js
├── scripts
├── node
│ ├── generate-packages.js
│ └── minify-options.js
└── rollup
│ ├── examples.development.js
│ ├── examples.production.js
│ ├── rollup-plugins
│ ├── copy.js
│ └── html.js
│ ├── rollup.es5.js
│ └── rollup.es6.js
├── site
├── basic.html
├── clipping-planes.html
├── css
│ └── style.css
├── favicon.ico
├── geometries.html
├── img
│ ├── facebook.png
│ ├── logo.svg
│ ├── matcap
│ │ ├── black-gloss.jpg
│ │ ├── skin.jpg
│ │ └── world.jpg
│ ├── thumbnails
│ │ ├── basic.jpg
│ │ ├── clipping-planes.jpg
│ │ ├── geometries.jpg
│ │ ├── instancing.jpg
│ │ ├── materials.jpg
│ │ ├── modify.jpg
│ │ ├── postprocessing.jpg
│ │ └── render-to-texture.jpg
│ ├── twitter.png
│ └── uv.png
├── index.html
├── instancing.html
├── js
│ ├── basic.js
│ ├── clipping-planes.js
│ ├── geometries.js
│ ├── instancing.js
│ ├── materials.js
│ ├── modify.js
│ ├── physics.js
│ ├── postprocessing.js
│ └── render-to-texture.js
├── materials.html
├── modify.html
├── physics.html
├── postprocessing.html
└── render-to-texture.html
└── src
├── _physics
└── index.js
├── _prism
├── index.js
└── letters.js
├── basic
└── index.js
├── clipping-planes
└── index.js
├── geometries
└── index.js
├── instancing
└── index.js
├── materials
└── index.js
├── modify
└── index.js
├── postprocessing
└── index.js
├── render-to-texture
└── index.js
├── static
├── css
│ └── style.css
├── favicon.ico
└── img
│ ├── facebook.png
│ ├── logo.svg
│ ├── matcap
│ ├── black-gloss.jpg
│ ├── skin.jpg
│ └── world.jpg
│ ├── thumbnails
│ ├── 2d-pattern3.jpg
│ ├── 2d-pattern3.png
│ ├── basic.jpg
│ ├── clipping-planes.jpg
│ ├── geometries.jpg
│ ├── instancing.jpg
│ ├── materials.jpg
│ ├── modify.jpg
│ ├── postprocessing.jpg
│ └── render-to-texture.jpg
│ ├── twitter.png
│ └── uv.png
└── template.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | ["env", {
4 | "modules": false
5 | }]
6 | ],
7 | "plugins": [
8 | "external-helpers",
9 | "transform-class-properties"
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | packages/controls/build
3 | packages/core/build
4 | packages/geometries/build
5 | packages/postprocessing/build
6 | packages/physics/build
7 | site/
8 | dev/
9 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "babel-eslint",
3 | "extends": ["airbnb", "prettier"],
4 | "globals": {
5 | "__LIBRARY__": true,
6 | "__VERSION__": true,
7 | "cancelAnimationFrame": true,
8 | "document": true,
9 | "Image": true,
10 | "lowww": true,
11 | "requestAnimationFrame": true,
12 | "window": true
13 | },
14 | "rules": {
15 | "arrow-body-style": [0],
16 | "class-methods-use-this": [0],
17 | "global-require": [0],
18 | "guard-for-in": [0],
19 | "import/prefer-default-export": [0],
20 | "indent": [2, 4],
21 | "no-bitwise": [0],
22 | "no-console": [0],
23 | "no-param-reassign": [0],
24 | "no-plusplus": [0],
25 | "no-restricted-syntax": [2, 'DebuggerStatement'],
26 | "no-return-assign": [0],
27 | "no-underscore-dangle": [0],
28 | "prefer-destructuring": ["error", { "array": false, "object": true }, { "enforceForRenamedProperties": false }]
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/*
2 | scripts/minify-options.json
3 | dev/*
4 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "trailingComma": "es5",
3 | "tabWidth": 4,
4 | "semi": true,
5 | "singleQuote": true
6 | }
7 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "8.9.4"
4 | script:
5 | - npm run lint:all
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017-2018 André Venâncio (info@andrevenancio.com)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | lowww `WebGL2.0` engine
5 |
6 | lowww
7 | ===
8 |
9 |
10 |
11 |
12 |
13 | lowww is a `WebGL 2.0` Javascript 3D engine. This is an experimental project focused in the advantages of `WebGL 2.0` and `GLSL ES 3.0`. It falls back to `WebGL` for devices that don't yet support `WebGL 2.0`.
14 |
15 |
16 | ## About this repository
17 | This is a monorepo where all packages are separated in the `packages/` folder and they can be imported independently as a npm module. There are several [npm scripts](https://github.com/andrevenancio/lowww/blob/master/package.json#L13) to allow you to build each module independently.
18 |
19 | A brief explanation of the content within this monorepo can be seen below:
20 | * `packages/` - contains all the packages part of the engine. Each package is a separate npm module.
21 | * `scripts/` - contains all the build scripts necessary to compile the website, examples, documentation and each individual package.
22 | * `site/` - contains the source code of the website.
23 | * `src/` - contains the source code for the website which include the examples. This is where you should add any specific example you might want to contribute.
24 |
25 |
26 | ## Development
27 | `npm start`
28 |
29 |
30 | ## Production
31 | `npm build:all`
32 |
--------------------------------------------------------------------------------
/docs/controls_src_index.js.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | JSDoc: Source: controls/src/index.js
6 |
7 |
8 |
9 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
Source: controls/src/index.js
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | /**
30 | * Controls
31 | * @module controls
32 | */
33 |
34 | import Orbit from './orbit';
35 |
36 | export { Orbit };
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | Modules
48 |
49 |
50 |
51 |
52 |
53 | Documentation generated by JSDoc 3.5.5 on Fri May 18 2018 14:19:50 GMT+0100 (BST)
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/docs/core_src_index.js.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | JSDoc: Source: core/src/index.js
6 |
7 |
8 |
9 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
Source: core/src/index.js
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | /**
30 | * Core
31 | * @module core
32 | */
33 | import * as chunks from './shaders/chunks';
34 | import * as utils from './utils';
35 | import * as cameras from './cameras';
36 | import * as shaders from './shaders';
37 | import * as helpers from './helpers';
38 | import * as constants from './constants';
39 |
40 | import Renderer from './core/renderer';
41 | import Object3 from './core/object3';
42 | import Scene from './core/scene';
43 | import Model from './core/model';
44 | import Mesh from './core/mesh';
45 | import Texture from './core/texture';
46 | import RenderTarget from './core/rt';
47 | import Composer from './core/composer';
48 | import Pass from './core/pass';
49 | import Performance from './core/performance';
50 |
51 | export {
52 | chunks,
53 | utils,
54 | cameras,
55 | shaders,
56 | helpers,
57 | constants,
58 | Renderer,
59 | Object3,
60 | Scene,
61 | Model,
62 | Mesh,
63 | Texture,
64 | RenderTarget,
65 | Composer,
66 | Pass,
67 | Performance,
68 | };
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 | Modules
80 |
81 |
82 |
83 |
84 |
85 | Documentation generated by JSDoc 3.5.5 on Fri May 18 2018 14:19:50 GMT+0100 (BST)
86 |
87 |
88 |
89 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/docs/fonts/OpenSans-Bold-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/docs/fonts/OpenSans-Bold-webfont.eot
--------------------------------------------------------------------------------
/docs/fonts/OpenSans-Bold-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/docs/fonts/OpenSans-Bold-webfont.woff
--------------------------------------------------------------------------------
/docs/fonts/OpenSans-BoldItalic-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/docs/fonts/OpenSans-BoldItalic-webfont.eot
--------------------------------------------------------------------------------
/docs/fonts/OpenSans-BoldItalic-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/docs/fonts/OpenSans-BoldItalic-webfont.woff
--------------------------------------------------------------------------------
/docs/fonts/OpenSans-Italic-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/docs/fonts/OpenSans-Italic-webfont.eot
--------------------------------------------------------------------------------
/docs/fonts/OpenSans-Italic-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/docs/fonts/OpenSans-Italic-webfont.woff
--------------------------------------------------------------------------------
/docs/fonts/OpenSans-Light-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/docs/fonts/OpenSans-Light-webfont.eot
--------------------------------------------------------------------------------
/docs/fonts/OpenSans-Light-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/docs/fonts/OpenSans-Light-webfont.woff
--------------------------------------------------------------------------------
/docs/fonts/OpenSans-LightItalic-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/docs/fonts/OpenSans-LightItalic-webfont.eot
--------------------------------------------------------------------------------
/docs/fonts/OpenSans-LightItalic-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/docs/fonts/OpenSans-LightItalic-webfont.woff
--------------------------------------------------------------------------------
/docs/fonts/OpenSans-Regular-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/docs/fonts/OpenSans-Regular-webfont.eot
--------------------------------------------------------------------------------
/docs/fonts/OpenSans-Regular-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/docs/fonts/OpenSans-Regular-webfont.woff
--------------------------------------------------------------------------------
/docs/geometries_src_index.js.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | JSDoc: Source: geometries/src/index.js
6 |
7 |
8 |
9 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
Source: geometries/src/index.js
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | /**
30 | * Geometries
31 | * @module geometries
32 | */
33 | import * as utils from './utils';
34 |
35 | import Tetrahedron from './tetrahedron';
36 | import Hexahedron from './hexahedron';
37 | import Octahedron from './octahedron';
38 | import Dodecahedron from './dodecahedron';
39 | import Icosahedron from './icosahedron';
40 |
41 | import Plane from './plane';
42 | import Box from './box';
43 | import Sphere from './sphere';
44 | import Torus from './torus';
45 | import TorusKnot from './torusknot';
46 |
47 | export {
48 | utils,
49 |
50 | /* PLATONIC SOLIDS */
51 | Tetrahedron,
52 | Hexahedron,
53 | Octahedron,
54 | Dodecahedron,
55 | Icosahedron,
56 |
57 | /* OTHER */
58 | Plane,
59 | Box,
60 | Sphere,
61 | Torus,
62 | TorusKnot,
63 | };
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | Modules
75 |
76 |
77 |
78 |
79 |
80 | Documentation generated by JSDoc 3.5.5 on Fri May 18 2018 00:26:31 GMT+0100 (BST)
81 |
82 |
83 |
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | JSDoc: Home
6 |
7 |
8 |
9 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
Home
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | Modules
54 |
55 |
56 |
57 |
58 |
59 | Documentation generated by JSDoc 3.5.5 on Fri May 18 2018 14:19:50 GMT+0100 (BST)
60 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/docs/module-controls.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | JSDoc: Module: controls
6 |
7 |
8 |
9 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
Module: controls
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
Controls
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 | Source:
89 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 | Modules
152 |
153 |
154 |
155 |
156 |
157 | Documentation generated by JSDoc 3.5.5 on Fri May 18 2018 14:19:50 GMT+0100 (BST)
158 |
159 |
160 |
161 |
162 |
163 |
--------------------------------------------------------------------------------
/docs/module-core.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | JSDoc: Module: core
6 |
7 |
8 |
9 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
Module: core
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
Core
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 | Source:
89 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 | Modules
152 |
153 |
154 |
155 |
156 |
157 | Documentation generated by JSDoc 3.5.5 on Fri May 18 2018 14:19:50 GMT+0100 (BST)
158 |
159 |
160 |
161 |
162 |
163 |
--------------------------------------------------------------------------------
/docs/module-geometries.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | JSDoc: Module: geometries
6 |
7 |
8 |
9 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
Module: geometries
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
Geometries
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 | Source:
89 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 | Modules
152 |
153 |
154 |
155 |
156 |
157 | Documentation generated by JSDoc 3.5.5 on Fri May 18 2018 00:26:31 GMT+0100 (BST)
158 |
159 |
160 |
161 |
162 |
163 |
--------------------------------------------------------------------------------
/docs/scripts/linenumber.js:
--------------------------------------------------------------------------------
1 | /*global document */
2 | (function() {
3 | var source = document.getElementsByClassName('prettyprint source linenums');
4 | var i = 0;
5 | var lineNumber = 0;
6 | var lineId;
7 | var lines;
8 | var totalLines;
9 | var anchorHash;
10 |
11 | if (source && source[0]) {
12 | anchorHash = document.location.hash.substring(1);
13 | lines = source[0].getElementsByTagName('li');
14 | totalLines = lines.length;
15 |
16 | for (; i < totalLines; i++) {
17 | lineNumber++;
18 | lineId = 'line' + lineNumber;
19 | lines[i].id = lineId;
20 | if (lineId === anchorHash) {
21 | lines[i].className += ' selected';
22 | }
23 | }
24 | }
25 | })();
26 |
--------------------------------------------------------------------------------
/docs/scripts/prettify/lang-css.js:
--------------------------------------------------------------------------------
1 | PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n"]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com",
2 | /^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]);
3 |
--------------------------------------------------------------------------------
/docs/styles/prettify-jsdoc.css:
--------------------------------------------------------------------------------
1 | /* JSDoc prettify.js theme */
2 |
3 | /* plain text */
4 | .pln {
5 | color: #000000;
6 | font-weight: normal;
7 | font-style: normal;
8 | }
9 |
10 | /* string content */
11 | .str {
12 | color: #006400;
13 | font-weight: normal;
14 | font-style: normal;
15 | }
16 |
17 | /* a keyword */
18 | .kwd {
19 | color: #000000;
20 | font-weight: bold;
21 | font-style: normal;
22 | }
23 |
24 | /* a comment */
25 | .com {
26 | font-weight: normal;
27 | font-style: italic;
28 | }
29 |
30 | /* a type name */
31 | .typ {
32 | color: #000000;
33 | font-weight: normal;
34 | font-style: normal;
35 | }
36 |
37 | /* a literal value */
38 | .lit {
39 | color: #006400;
40 | font-weight: normal;
41 | font-style: normal;
42 | }
43 |
44 | /* punctuation */
45 | .pun {
46 | color: #000000;
47 | font-weight: bold;
48 | font-style: normal;
49 | }
50 |
51 | /* lisp open bracket */
52 | .opn {
53 | color: #000000;
54 | font-weight: bold;
55 | font-style: normal;
56 | }
57 |
58 | /* lisp close bracket */
59 | .clo {
60 | color: #000000;
61 | font-weight: bold;
62 | font-style: normal;
63 | }
64 |
65 | /* a markup tag name */
66 | .tag {
67 | color: #006400;
68 | font-weight: normal;
69 | font-style: normal;
70 | }
71 |
72 | /* a markup attribute name */
73 | .atn {
74 | color: #006400;
75 | font-weight: normal;
76 | font-style: normal;
77 | }
78 |
79 | /* a markup attribute value */
80 | .atv {
81 | color: #006400;
82 | font-weight: normal;
83 | font-style: normal;
84 | }
85 |
86 | /* a declaration */
87 | .dec {
88 | color: #000000;
89 | font-weight: bold;
90 | font-style: normal;
91 | }
92 |
93 | /* a variable name */
94 | .var {
95 | color: #000000;
96 | font-weight: normal;
97 | font-style: normal;
98 | }
99 |
100 | /* a function name */
101 | .fun {
102 | color: #000000;
103 | font-weight: bold;
104 | font-style: normal;
105 | }
106 |
107 | /* Specify class=linenums on a pre to get line numbering */
108 | ol.linenums {
109 | margin-top: 0;
110 | margin-bottom: 0;
111 | }
112 |
--------------------------------------------------------------------------------
/docs/styles/prettify-tomorrow.css:
--------------------------------------------------------------------------------
1 | /* Tomorrow Theme */
2 | /* Original theme - https://github.com/chriskempson/tomorrow-theme */
3 | /* Pretty printing styles. Used with prettify.js. */
4 | /* SPAN elements with the classes below are added by prettyprint. */
5 | /* plain text */
6 | .pln {
7 | color: #4d4d4c; }
8 |
9 | @media screen {
10 | /* string content */
11 | .str {
12 | color: #718c00; }
13 |
14 | /* a keyword */
15 | .kwd {
16 | color: #8959a8; }
17 |
18 | /* a comment */
19 | .com {
20 | color: #8e908c; }
21 |
22 | /* a type name */
23 | .typ {
24 | color: #4271ae; }
25 |
26 | /* a literal value */
27 | .lit {
28 | color: #f5871f; }
29 |
30 | /* punctuation */
31 | .pun {
32 | color: #4d4d4c; }
33 |
34 | /* lisp open bracket */
35 | .opn {
36 | color: #4d4d4c; }
37 |
38 | /* lisp close bracket */
39 | .clo {
40 | color: #4d4d4c; }
41 |
42 | /* a markup tag name */
43 | .tag {
44 | color: #c82829; }
45 |
46 | /* a markup attribute name */
47 | .atn {
48 | color: #f5871f; }
49 |
50 | /* a markup attribute value */
51 | .atv {
52 | color: #3e999f; }
53 |
54 | /* a declaration */
55 | .dec {
56 | color: #f5871f; }
57 |
58 | /* a variable name */
59 | .var {
60 | color: #c82829; }
61 |
62 | /* a function name */
63 | .fun {
64 | color: #4271ae; } }
65 | /* Use higher contrast and text-weight for printable form. */
66 | @media print, projection {
67 | .str {
68 | color: #060; }
69 |
70 | .kwd {
71 | color: #006;
72 | font-weight: bold; }
73 |
74 | .com {
75 | color: #600;
76 | font-style: italic; }
77 |
78 | .typ {
79 | color: #404;
80 | font-weight: bold; }
81 |
82 | .lit {
83 | color: #044; }
84 |
85 | .pun, .opn, .clo {
86 | color: #440; }
87 |
88 | .tag {
89 | color: #006;
90 | font-weight: bold; }
91 |
92 | .atn {
93 | color: #404; }
94 |
95 | .atv {
96 | color: #060; } }
97 | /* Style */
98 | /*
99 | pre.prettyprint {
100 | background: white;
101 | font-family: Consolas, Monaco, 'Andale Mono', monospace;
102 | font-size: 12px;
103 | line-height: 1.5;
104 | border: 1px solid #ccc;
105 | padding: 10px; }
106 | */
107 |
108 | /* Specify class=linenums on a pre to get line numbering */
109 | ol.linenums {
110 | margin-top: 0;
111 | margin-bottom: 0; }
112 |
113 | /* IE indents via margin-left */
114 | li.L0,
115 | li.L1,
116 | li.L2,
117 | li.L3,
118 | li.L4,
119 | li.L5,
120 | li.L6,
121 | li.L7,
122 | li.L8,
123 | li.L9 {
124 | /* */ }
125 |
126 | /* Alternate shading for lines */
127 | li.L1,
128 | li.L3,
129 | li.L5,
130 | li.L7,
131 | li.L9 {
132 | /* */ }
133 |
--------------------------------------------------------------------------------
/jsdoc.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "source": {
3 | "include": [
4 | "packages/controls/src/index.js",
5 | "packages/core/src/index.js",
6 | "packages/geometries/src/index.js",
7 | "packages/postprocessing/src/index.js"
8 | ]
9 | },
10 | "opts": {
11 | "recurse": true,
12 | "destination": "./docs/"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/packages/controls/README.md:
--------------------------------------------------------------------------------
1 | # lowww-controls
2 | Adds camera control utilities for the [lowww](https://github.com/andrevenancio/lowww) engine.
3 |
4 | ## Installation
5 | `npm install --save lowww-controls`
6 |
7 |
8 | ## Usage
9 | ```javascript
10 | import { Renderer, Scene, cameras, Mesh } from 'lowww-core';
11 | import { Box } from 'lowww-geometries';
12 | import { Orbit } from 'lowww-controls';
13 |
14 | let renderer;
15 | let camera;
16 | let scene;
17 | let controls;
18 | let mesh;
19 |
20 | init();
21 | update();
22 |
23 | const init = () => {
24 | renderer = new Renderer();
25 | renderer.setSize(400, 300);
26 | document.body.appendChild(renderer.domElement);
27 |
28 | camera = new cameras.Perspective();
29 | camera.position.set(0, 0, 500);
30 |
31 | scene = new Scene();
32 |
33 | controls = new Orbit(camera, renderer.domElement);
34 |
35 | const geometry = new Box({ width: 10, height: 10, depth: 10 });
36 | mesh = new Mesh({ geometry });
37 | scene.add(mesh);
38 | };
39 |
40 | const update = () => {
41 | controls.update();
42 | renderer.render(scene, camera);
43 | requestAnimationFrame(update.bind(this));
44 | };
45 | ```
46 |
47 |
48 | ## License
49 | MIT
50 |
--------------------------------------------------------------------------------
/packages/controls/build/controls.min.js:
--------------------------------------------------------------------------------
1 | /*
2 | lowww-controls - version: 1.1.5
3 | Copyright © 2018 Andre Venancio (info@andrevenancio.com)
4 | */
5 | var t,e;t=this,e=function(t){"use strict";var o="undefined"!=typeof Float32Array?Float32Array:Array;function e(){var t=new o(3);return t[0]=0,t[1]=0,t[2]=0,t}function n(t,e,n){var i=new o(3);return i[0]=t,i[1]=e,i[2]=n,i}Math.PI;var i;function s(){var t=new o(4);return t[0]=0,t[1]=0,t[2]=0,t[3]=1,t}e(),(i=new o(4))[0]=0,i[1]=0,i[2]=0,i[3]=0;var r,h;function a(t,e,n){return Math.max(Math.min(t,n),e)}e(),n(1,0,0),n(0,1,0),s(),s(),(r=new o(9))[0]=1,r[1]=0,r[2]=0,r[3]=0,r[4]=1,r[5]=0,r[6]=0,r[7]=0,r[8]=1,(h=new o(2))[0]=0,h[1]=0;var d=function(){function i(t,e){for(var n=0;nr.oldDiff?-100:100,r.zoom(s),r.oldDiff=r.curDiff}}},this.onEnd=function(){r.isDown=!1,r.oldDiff=-1},this.onWheel=function(t){t.preventDefault(),r.zoom(-t.deltaY)},this.camera=t,this.domElement=e,this.radius=Math.max(t.position.x,t.position.z),this.rx=Math.atan2(t.position.y,this.radius),this.ry=Math.atan2(t.position.z,t.position.x)+u,this.ox=0,this.oy=0,this.width=window.innerWidth,this.height=window.innerHeight,this.rotationSpeed=5*window.devicePixelRatio,this.zoomMin=.1,this.zoomMax=1/0,this.zoomSpeed=100,this.isDown=!1,this.curDiff=0,this.oldDiff=-1,this.enable()}return d(n,[{key:"enable",value:function(){this.domElement.addEventListener("mousedown",this.onStart,!1),this.domElement.addEventListener("mousemove",this.onMove,!1),this.domElement.addEventListener("mouseup",this.onEnd,!1),this.domElement.addEventListener("touchstart",this.onStart,!1),this.domElement.addEventListener("touchmove",this.onMove,!1),this.domElement.addEventListener("touchend",this.onEnd,!1),this.domElement.addEventListener("wheel",this.onWheel,!1)}},{key:"disable",value:function(){this.domElement.removeEventListener("mousedown",this.onStart,!1),this.domElement.removeEventListener("mousemove",this.onMove,!1),this.domElement.removeEventListener("mouseup",this.onEnd,!1),this.domElement.removeEventListener("touchstart",this.onStart,!1),this.domElement.removeEventListener("touchmove",this.onMove,!1),this.domElement.removeEventListener("touchend",this.onEnd,!1),this.domElement.removeEventListener("wheel",this.onWheel,!1)}},{key:"pinchMode",value:function(t,e,n,i){return Math.sqrt((t-n)*(t-n)+(e-i)*(e-i))}},{key:"zoom",value:function(t){this.radius+=t/1e3*this.zoomSpeed,this.radius=a(this.radius,this.zoomMin,this.zoomMax)}},{key:"update",value:function(){var t,e,n,i,o=this.radius*Math.sin(this.rx),s=this.radius*Math.cos(this.rx);e=Math.sin(this.ry)*s,n=o,i=Math.cos(this.ry)*s,(t=this.camera.position.data)[0]=e,t[1]=n,t[2]=i}}]),n}();t.Orbit=m,Object.defineProperty(t,"__esModule",{value:!0})},"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t.lowww=t.lowww||{},t.lowww.controls={}));
6 |
--------------------------------------------------------------------------------
/packages/controls/package.json:
--------------------------------------------------------------------------------
1 | {"name":"lowww-controls","description":"WebGL 2 Engine extension","author":"Andre Venancio (info@andrevenancio.com)","version":"1.1.5","main":"src/index.js","module":"build/controls.module.js","repository":"git@github.com:andrevenancio/lowww.git","scripts":{"test":"echo 'Error: no test specified' && exit 0"},"devDependencies":{},"dependencies":{"gl-matrix":"^2.5.1"}}
--------------------------------------------------------------------------------
/packages/controls/src/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Controls
3 | * @module controls
4 | */
5 |
6 | import Orbit from './orbit';
7 |
8 | export { Orbit };
9 |
--------------------------------------------------------------------------------
/packages/controls/src/utils/math.js:
--------------------------------------------------------------------------------
1 | export function clamp(value, min, max) {
2 | return Math.max(Math.min(value, max), min);
3 | }
4 |
--------------------------------------------------------------------------------
/packages/core/README.md:
--------------------------------------------------------------------------------
1 | # lowww-core
2 | core functionality for the [lowww](https://github.com/andrevenancio/lowww) engine.
3 |
4 | ## Installation
5 | `npm install --save lowww-core`
6 |
7 |
8 | ## Usage
9 | ```javascript
10 | import { Renderer, Scene, cameras, Mesh } from 'lowww-core';
11 | import { Box } from 'lowww-geometries';
12 |
13 | let renderer;
14 | let camera;
15 | let scene;
16 | let mesh;
17 |
18 | init();
19 | update();
20 |
21 | const init = () => {
22 | renderer = new Renderer();
23 | renderer.setSize(400, 300);
24 | document.body.appendChild(renderer.domElement);
25 |
26 | camera = new cameras.Perspective();
27 | camera.position.set(0, 0, 500);
28 |
29 | scene = new Scene();
30 |
31 | const geometry = new Box({ width: 10, height: 10, depth: 10 });
32 | mesh = new Mesh({ geometry });
33 | scene.add(mesh);
34 | };
35 |
36 | const update = () => {
37 | mesh.rotation.x += 0.01;
38 | mesh.rotation.y += 0.01;
39 |
40 | renderer.render(scene, camera);
41 | requestAnimationFrame(update.bind(this));
42 | };
43 | ```
44 |
45 | ## Hello World
46 | check out this [JSFiddle](https://jsfiddle.net/andrevenancio/Lq1wgvjp/).
47 |
48 | ## License
49 | MIT
50 |
--------------------------------------------------------------------------------
/packages/core/package.json:
--------------------------------------------------------------------------------
1 | {"name":"lowww-core","description":"WebGL 2 Engine extension","author":"Andre Venancio (info@andrevenancio.com)","version":"1.1.5","main":"src/index.js","module":"build/core.module.js","repository":"git@github.com:andrevenancio/lowww.git","scripts":{"test":"echo 'Error: no test specified' && exit 0"},"devDependencies":{},"dependencies":{"gl-matrix":"^2.5.1"}}
--------------------------------------------------------------------------------
/packages/core/src/cameras/index.js:
--------------------------------------------------------------------------------
1 | import Orthographic from './orthographic';
2 | import Perspective from './perspective';
3 |
4 | export { Orthographic, Perspective };
5 |
--------------------------------------------------------------------------------
/packages/core/src/cameras/orthographic.js:
--------------------------------------------------------------------------------
1 | import { vec3, mat4 } from 'gl-matrix';
2 | import Object3 from '../core/object3';
3 |
4 | class OrthographicCamera extends Object3 {
5 | constructor(params = {}) {
6 | super();
7 |
8 | Object.assign(
9 | this,
10 | {
11 | left: -1,
12 | right: 1,
13 | top: 1,
14 | bottom: -1,
15 | near: -1000,
16 | far: 1000,
17 | },
18 | params
19 | );
20 |
21 | this.matrices.projection = mat4.create();
22 | }
23 |
24 | lookAt(v) {
25 | vec3.copy(this.target, v);
26 | }
27 |
28 | /**
29 | * updates projection matrix
30 | *
31 | * @param {Number} a The first number to test.
32 | * @param {Number} b The second number to test.
33 | * @returns {Boolean} True if the numbers are approximately equal, false otherwise.
34 | */
35 | updateCameraMatrix() {
36 | // left, right, bottom, top, near, far
37 | mat4.ortho(
38 | this.matrices.projection,
39 | this.left,
40 | this.right,
41 | this.bottom,
42 | this.top,
43 | this.near,
44 | this.far
45 | );
46 | }
47 | }
48 |
49 | export default OrthographicCamera;
50 |
--------------------------------------------------------------------------------
/packages/core/src/cameras/perspective.js:
--------------------------------------------------------------------------------
1 | import { vec3, mat4 } from 'gl-matrix';
2 | import Object3 from '../core/object3';
3 |
4 | class PerspectiveCamera extends Object3 {
5 | constructor(params = {}) {
6 | super();
7 |
8 | Object.assign(
9 | this,
10 | {
11 | near: 1,
12 | far: 1000,
13 | fov: 35,
14 | },
15 | params
16 | );
17 |
18 | this.matrices.projection = mat4.create();
19 | }
20 |
21 | lookAt(v) {
22 | vec3.copy(this.target, v);
23 | }
24 |
25 | updateCameraMatrix(width, height) {
26 | mat4.perspective(
27 | this.matrices.projection,
28 | this.fov * (Math.PI / 180),
29 | width / height,
30 | this.near,
31 | this.far
32 | );
33 | }
34 | }
35 |
36 | export default PerspectiveCamera;
37 |
--------------------------------------------------------------------------------
/packages/core/src/constants.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Max directional light allowed
3 | *
4 | * @static
5 | * @constant
6 | * @name MAX_DIRECTIONAL
7 | * @type {string}
8 | */
9 | export const MAX_DIRECTIONAL = 1;
10 |
11 | /**
12 | * directional light id
13 | *
14 | * @static
15 | * @constant
16 | * @name DIRECTIONAL_LIGHT
17 | * @type {string}
18 | */
19 | export const DIRECTIONAL_LIGHT = 1000;
20 |
21 | /**
22 | * basic shader id
23 | *
24 | * @static
25 | * @constant
26 | * @name SHADER_BASIC
27 | * @type {string}
28 | */
29 | export const SHADER_BASIC = 2000;
30 |
31 | /**
32 | * default shader id
33 | *
34 | * @static
35 | * @constant
36 | * @name SHADER_DEFAULT
37 | * @type {string}
38 | */
39 | export const SHADER_DEFAULT = 2001;
40 |
41 | /**
42 | * billboard shader id
43 | *
44 | * @static
45 | * @constant
46 | * @name SHADER_BILLBOARD
47 | * @type {string}
48 | */
49 | export const SHADER_BILLBOARD = 2002;
50 |
51 | /**
52 | * shadow shader id
53 | *
54 | * @static
55 | * @constant
56 | * @name SHADER_SHADOW
57 | * @type {string}
58 | */
59 | export const SHADER_SHADOW = 2003;
60 |
61 | /**
62 | * sem shader id
63 | *
64 | * @static
65 | * @constant
66 | * @name SHADER_SEM
67 | * @type {string}
68 | */
69 | export const SHADER_SEM = 2004;
70 |
71 | /**
72 | * custom shader id
73 | *
74 | * @static
75 | * @constant
76 | * @name SHADER_CUSTOM
77 | * @type {string}
78 | */
79 | export const SHADER_CUSTOM = 2500;
80 |
81 | /**
82 | * shader draw modes
83 | *
84 | * @static
85 | * @constant
86 | * @name DRAW
87 | * @type {object}
88 | * @property {number} POINTS
89 | * @property {number} LINES
90 | * @property {number} TRIANGLES
91 | */
92 | export const DRAW = {
93 | POINTS: 0,
94 | LINES: 1,
95 | TRIANGLES: 4,
96 | };
97 |
98 | /**
99 | * triangle side
100 | *
101 | * @static
102 | * @constant
103 | * @name SIDE
104 | * @type {object}
105 | * @property {number} FRONT
106 | * @property {number} BACK
107 | * @property {number} BOTH
108 | */
109 | export const SIDE = {
110 | FRONT: 0,
111 | BACK: 1,
112 | BOTH: 2,
113 | };
114 |
115 | /**
116 | * context types
117 | *
118 | * @static
119 | * @constant
120 | * @name CONTEXT
121 | * @type {object}
122 | * @property {number} WEBGL
123 | * @property {number} WEBGL2
124 | */
125 | export const CONTEXT = {
126 | WEBGL: 'webgl',
127 | WEBGL2: 'webgl2',
128 | };
129 |
--------------------------------------------------------------------------------
/packages/core/src/core/composer.js:
--------------------------------------------------------------------------------
1 | import { vec4 } from 'gl-matrix';
2 | import { Orthographic } from '../cameras';
3 | import Renderer from './renderer';
4 | import RenderTarget from './rt';
5 | import Pass from './pass';
6 | import { Basic } from '../passes';
7 |
8 | class Composer {
9 | constructor(props) {
10 | this.renderer = new Renderer(props);
11 | this.domElement = this.renderer.domElement;
12 |
13 | this.camera = new Orthographic();
14 | this.camera.position.z = 100;
15 |
16 | this.passes = [];
17 |
18 | this.clearColor = vec4.fromValues(0, 0, 0, 1);
19 |
20 | this.screen = new Pass(Basic);
21 | this.screen.compile();
22 |
23 | this.buffers = [new RenderTarget(), new RenderTarget()];
24 |
25 | this.read = this.buffers[1];
26 | this.write = this.buffers[0];
27 | }
28 |
29 | setSize(width, height) {
30 | this.renderer.setSize(width, height);
31 | this.read.setSize(width, height);
32 | this.write.setSize(width, height);
33 | }
34 |
35 | setRatio(ratio) {
36 | this.renderer.setRatio(ratio);
37 | }
38 |
39 | pass(pass) {
40 | this.passes.push(pass);
41 | }
42 |
43 | compile() {
44 | for (let i = 0; i < this.passes.length; i++) {
45 | this.passes[i].compile();
46 | }
47 | }
48 |
49 | renderToTexture(renderTarget, scene, camera) {
50 | this.renderer.rtt({
51 | renderTarget,
52 | scene,
53 | camera,
54 | clearColor: this.clearColor,
55 | });
56 | }
57 |
58 | resetBuffers() {
59 | this.read = this.buffers[1];
60 | this.write = this.buffers[0];
61 | }
62 |
63 | swapBuffers() {
64 | this.temp = this.read;
65 | this.read = this.write;
66 | this.write = this.temp;
67 | }
68 |
69 | render(scene, camera) {
70 | this.resetBuffers();
71 | this.renderToTexture(this.write, scene, camera);
72 |
73 | // ping pong textures through passes
74 | const total = this.passes.length;
75 | for (let i = 0; i < total; i++) {
76 | if (this.passes[i].enable) {
77 | this.swapBuffers();
78 | this.passes[i].setUniform('u_input', this.read.texture);
79 | this.renderToTexture(
80 | this.write,
81 | this.passes[i].scene,
82 | this.camera
83 | );
84 | }
85 | }
86 |
87 | // render last pass to screen
88 | this.screen.setUniform('u_input', this.write.texture);
89 | this.renderer.render(this.screen.scene, this.camera);
90 | }
91 | }
92 |
93 | export default Composer;
94 |
--------------------------------------------------------------------------------
/packages/core/src/core/lights.js:
--------------------------------------------------------------------------------
1 | import { vec3 } from 'gl-matrix';
2 | // import Vector3 from '../core/vector3';
3 | import { DIRECTIONAL_LIGHT } from '../constants';
4 |
5 | class Light {
6 | constructor() {
7 | this.position = vec3.create();
8 | }
9 |
10 | destroy() {
11 | // TODO
12 | }
13 | }
14 |
15 | class Directional extends Light {
16 | constructor(props = {}) {
17 | super();
18 |
19 | this.type = DIRECTIONAL_LIGHT;
20 |
21 | this.color = props.color || vec3.fromValues(1, 1, 1);
22 | this.intensity = props.intensity || 0.989;
23 | }
24 | }
25 |
26 | export { Directional };
27 |
--------------------------------------------------------------------------------
/packages/core/src/core/mesh.js:
--------------------------------------------------------------------------------
1 | import Model from './model';
2 | import { Default } from '../shaders';
3 | import { SHADER_CUSTOM } from '../constants';
4 |
5 | let shaderID = 0;
6 | class Mesh extends Model {
7 | constructor(params = {}) {
8 | super();
9 |
10 | this._shader = null;
11 |
12 | const { positions, indices, normals, uvs } = params.geometry || {};
13 |
14 | const { vertex, fragment, uniforms, type, mode } =
15 | params.shader ||
16 | new Default({ color: params.color, map: params.map });
17 |
18 | // if there's a type, assign it, so we can sort by type in the renderer.
19 | if (type !== undefined) {
20 | this.type = type;
21 | } else {
22 | this.type = `${SHADER_CUSTOM}-${shaderID++}`;
23 | }
24 |
25 | if (mode !== undefined) {
26 | this.mode = mode;
27 | }
28 |
29 | this.setAttribute('a_position', 'vec3', new Float32Array(positions));
30 | if (indices) {
31 | this.setIndex(new Uint16Array(indices));
32 | }
33 | if (normals) {
34 | this.setAttribute('a_normal', 'vec3', new Float32Array(normals));
35 | }
36 | if (uvs) {
37 | this.setAttribute('a_uv', 'vec2', new Float32Array(uvs));
38 | }
39 |
40 | Object.keys(uniforms).forEach(key => {
41 | this.setUniform(key, uniforms[key].type, uniforms[key].value);
42 | });
43 |
44 | this.setShader(vertex, fragment);
45 | }
46 |
47 | set shader(shader) {
48 | this.dirty.shader = true;
49 | this._shader = shader;
50 | if (shader.type !== undefined) {
51 | this.type = shader.type;
52 | } else {
53 | this.type = SHADER_CUSTOM;
54 | }
55 | this.setShader(shader.vertex, shader.fragment);
56 | }
57 |
58 | get shader() {
59 | return this._shader;
60 | }
61 | }
62 |
63 | export default Mesh;
64 |
--------------------------------------------------------------------------------
/packages/core/src/core/pass.js:
--------------------------------------------------------------------------------
1 | import Scene from './scene';
2 | import Mesh from './mesh';
3 | import { UBO } from '../shaders/chunks';
4 |
5 | class Pass {
6 | constructor(props) {
7 | this.scene = new Scene();
8 |
9 | const { vertex, fragment, uniforms } = props;
10 |
11 | this.vertex = vertex;
12 | this.fragment = fragment;
13 | this.uniforms = uniforms;
14 |
15 | this.enable = true;
16 | }
17 |
18 | compile() {
19 | const shader = {
20 | vertex: `#version 300 es
21 | in vec3 a_position;
22 | in vec3 a_normal;
23 | in vec2 a_uv;
24 |
25 | ${UBO.scene()}
26 | ${UBO.model()}
27 |
28 | ${this.vertex}`,
29 |
30 | fragment: `#version 300 es
31 | precision highp float;
32 | precision highp int;
33 |
34 | ${UBO.scene()}
35 | ${UBO.model()}
36 |
37 | out vec4 outColor;
38 | ${this.fragment}`,
39 | uniforms: this.uniforms,
40 | };
41 |
42 | const geometry = {
43 | positions: [-1, -1, 0, 1, -1, 0, 1, 1, 0, -1, 1, 0],
44 | indices: [0, 1, 2, 0, 2, 3],
45 | uvs: [0, 0, 1, 0, 1, 1, 0, 1],
46 | };
47 | this.quad = new Mesh({ geometry, shader });
48 | this.scene.add(this.quad);
49 | }
50 |
51 | setUniform(key, value) {
52 | this.quad.uniforms[key].value = value;
53 | }
54 | }
55 |
56 | export default Pass;
57 |
--------------------------------------------------------------------------------
/packages/core/src/core/performance.js:
--------------------------------------------------------------------------------
1 | class Performance {
2 | constructor(params = {}) {
3 | this.theme = params.theme || {
4 | font:
5 | 'font-family:sans-serif;font-size:xx-small;font-weight:bold;line-height:15px;-moz-osx-font-smoothing: grayscale;-webkit-font-smoothing: antialiased;',
6 | color1: '#242424',
7 | color2: '#2a2a2a',
8 | color3: '#666',
9 | color4: '#999',
10 | };
11 |
12 | const container = document.createElement('div');
13 | container.style.cssText =
14 | 'position:fixed;bottom:0;left:0;min-width:80px;opacity:0.9;z-index:10000;';
15 |
16 | this.holder = document.createElement('div');
17 | this.holder.style.cssText = `padding:3px;background-color:${this.theme.color1};`;
18 | container.appendChild(this.holder);
19 |
20 | const title = document.createElement('div');
21 | title.style.cssText = `${this.theme.font};color:${this.theme.color3};`;
22 | title.innerHTML = 'Performance';
23 | this.holder.appendChild(title);
24 |
25 | this.msTexts = [];
26 |
27 | this.domElement = container;
28 | }
29 |
30 | rebuild(params) {
31 | this.msTexts = [];
32 | Object.keys(params).forEach(key => {
33 | const element = document.createElement('div');
34 | element.style.cssText = `${this.theme.font};color:${this.theme.color4};background-color:${this.theme.color2};`;
35 | this.holder.appendChild(element);
36 | this.msTexts[key] = element;
37 | });
38 | }
39 |
40 | update(renderer) {
41 | if (
42 | Object.keys(this.msTexts).length !==
43 | Object.keys(renderer.performance).length
44 | ) {
45 | this.rebuild(renderer.performance);
46 | }
47 |
48 | Object.keys(renderer.performance).forEach(key => {
49 | this.msTexts[
50 | key
51 | ].textContent = `${key}: ${renderer.performance[key]}`;
52 | });
53 | }
54 | }
55 |
56 | export default Performance;
57 |
--------------------------------------------------------------------------------
/packages/core/src/core/scene.js:
--------------------------------------------------------------------------------
1 | import { vec4 } from 'gl-matrix';
2 | import Object3 from './object3';
3 | import { Directional } from './lights';
4 | import { DIRECTIONAL_LIGHT } from '../constants';
5 |
6 | class Scene extends Object3 {
7 | constructor() {
8 | super();
9 |
10 | this.lights = {
11 | directional: [],
12 | };
13 |
14 | this.fog = {
15 | enable: false,
16 | color: vec4.fromValues(0, 0, 0, 1),
17 | start: 500,
18 | end: 1000,
19 | density: 0.00025,
20 | };
21 |
22 | this.clipping = {
23 | enable: false,
24 | planes: [vec4.create(), vec4.create(), vec4.create()],
25 | };
26 |
27 | // add sun
28 | const directional = new Directional({
29 | near: 1,
30 | far: 1000,
31 | });
32 | directional.position[0] = 125;
33 | directional.position[1] = 250;
34 | directional.position[2] = 500;
35 | this.addLight(directional);
36 | }
37 |
38 | addLight(light) {
39 | switch (light.type) {
40 | case DIRECTIONAL_LIGHT:
41 | this.lights.directional.push(light);
42 | break;
43 | default:
44 | // unsupported light
45 | }
46 | }
47 |
48 | removeLight(light) {
49 | const index = this.lights.directional.indexOf(light);
50 | if (index !== -1) {
51 | light.destroy();
52 | this.lights.directional.splice(index, 1);
53 | }
54 | }
55 | }
56 |
57 | export default Scene;
58 |
--------------------------------------------------------------------------------
/packages/core/src/core/shadow-map-renderer.js:
--------------------------------------------------------------------------------
1 | import { vec3, mat4 } from 'gl-matrix';
2 | import RenderTarget from './rt';
3 | import Perspective from '../cameras/perspective';
4 | import Orthographic from '../cameras/orthographic';
5 |
6 | class ShadowMapRenderer {
7 | constructor(props = {}) {
8 | // size of texture
9 | this.width = props.width || 1024;
10 | this.height = props.height || 1024;
11 |
12 | // create render target
13 | const { width, height } = this;
14 | this.rt = new RenderTarget({ width, height });
15 |
16 | // matrices
17 | this.matrices = {
18 | view: mat4.create(),
19 | shadow: mat4.create(),
20 | bias: mat4.fromValues(
21 | 0.5,
22 | 0.0,
23 | 0.0,
24 | 0.0,
25 | 0.0,
26 | 0.5,
27 | 0.0,
28 | 0.0,
29 | 0.0,
30 | 0.0,
31 | 0.5,
32 | 0.0,
33 | 0.5,
34 | 0.5,
35 | 0.5,
36 | 1.0
37 | ),
38 | };
39 |
40 | // origin of directional light
41 | this.camera = new Perspective({
42 | fov: 60,
43 | near: 1,
44 | far: 1000,
45 | });
46 |
47 | this.camera = new Orthographic();
48 | this.camera.position.z = 1; // TODO: remove this when fix lookAt bug on gl-matrix
49 | this.setLightOrigin(props.light || vec3.fromValues(100, 250, 500));
50 | }
51 |
52 | // move the camera to the light position
53 | setLightOrigin(vec) {
54 | // CAMERA
55 |
56 | // update camera position
57 | vec3.copy(this.camera.position.data, vec);
58 |
59 | // update view matrix
60 | mat4.identity(this.matrices.view);
61 | mat4.lookAt(
62 | this.matrices.view,
63 | this.camera.position.data,
64 | this.camera.target,
65 | this.camera.up
66 | );
67 |
68 | // SHADOW
69 | mat4.identity(this.matrices.shadow);
70 | mat4.multiply(
71 | this.matrices.shadow,
72 | this.camera.matrices.projection,
73 | this.matrices.view
74 | );
75 | mat4.multiply(
76 | this.matrices.shadow,
77 | this.matrices.bias,
78 | this.matrices.shadow
79 | );
80 | }
81 |
82 | /*
83 | TODO:
84 | maybe create a program just for shadows. this avoids having to change program
85 | in complex scenes just to write for the depth buffer.
86 | find a way to bypass the changeProgram on the renderer to accomodate this.
87 | */
88 | }
89 |
90 | export default ShadowMapRenderer;
91 |
--------------------------------------------------------------------------------
/packages/core/src/core/texture.js:
--------------------------------------------------------------------------------
1 | import { getContext } from '../session';
2 |
3 | class Texture {
4 | constructor(props = {}) {
5 | const gl = getContext();
6 |
7 | Object.assign(
8 | this,
9 | {
10 | magFilter: gl.NEAREST,
11 | minFilter: gl.NEAREST,
12 | wrapS: gl.CLAMP_TO_EDGE,
13 | wrapT: gl.CLAMP_TO_EDGE,
14 | transparent: false,
15 | },
16 | props
17 | );
18 |
19 | const data = new Uint8Array([255, 255, 255, 255]);
20 | this.texture = gl.createTexture();
21 | gl.bindTexture(gl.TEXTURE_2D, this.texture);
22 | gl.texImage2D(
23 | gl.TEXTURE_2D,
24 | 0,
25 | gl.RGBA,
26 | 1,
27 | 1,
28 | 0,
29 | gl.RGBA,
30 | gl.UNSIGNED_BYTE,
31 | data
32 | );
33 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, this.magFilter);
34 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, this.minFilter);
35 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, this.wrapS);
36 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, this.wrapT);
37 | if (this.transparent) {
38 | gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
39 | }
40 |
41 | gl.bindTexture(gl.TEXTURE_2D, null);
42 | }
43 |
44 | fromImage(url) {
45 | const img = new Image();
46 | img.crossOrigin = '';
47 | img.onload = () => {
48 | this.update(img);
49 | };
50 | img.src = url;
51 | }
52 |
53 | update(image) {
54 | const gl = getContext();
55 | gl.bindTexture(gl.TEXTURE_2D, this.texture);
56 | gl.generateMipmap(gl.TEXTURE_2D);
57 | gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
58 | gl.texImage2D(
59 | gl.TEXTURE_2D,
60 | 0,
61 | gl.RGBA,
62 | gl.RGBA,
63 | gl.UNSIGNED_BYTE,
64 | image
65 | );
66 | gl.bindTexture(gl.TEXTURE_2D, null);
67 | }
68 | }
69 |
70 | export default Texture;
71 |
--------------------------------------------------------------------------------
/packages/core/src/core/vector3.js:
--------------------------------------------------------------------------------
1 | import { vec3 } from 'gl-matrix';
2 |
3 | class Vector3 {
4 | constructor(x = 0, y = 0, z = 0) {
5 | this.data = vec3.fromValues(x, y, z);
6 | }
7 |
8 | set(x, y, z) {
9 | this.x = x;
10 | this.y = y;
11 | this.z = z;
12 | }
13 |
14 | set x(value) {
15 | this.data[0] = value;
16 | }
17 |
18 | get x() {
19 | return this.data[0];
20 | }
21 |
22 | set y(value) {
23 | this.data[1] = value;
24 | }
25 |
26 | get y() {
27 | return this.data[1];
28 | }
29 |
30 | set z(value) {
31 | this.data[2] = value;
32 | }
33 |
34 | get z() {
35 | return this.data[2];
36 | }
37 | }
38 |
39 | export default Vector3;
40 |
--------------------------------------------------------------------------------
/packages/core/src/gl/attributes.js:
--------------------------------------------------------------------------------
1 | import { getContext, getContextType, supports } from '../session';
2 | import { CONTEXT } from '../constants';
3 |
4 | export const initAttributes = (attributes, program) => {
5 | const gl = getContext();
6 |
7 | for (const prop in attributes) {
8 | const current = attributes[prop];
9 | const location = gl.getAttribLocation(program, prop);
10 |
11 | let b = current.buffer;
12 | if (!current.buffer) {
13 | b = gl.createBuffer();
14 | }
15 |
16 | gl.bindBuffer(gl.ARRAY_BUFFER, b);
17 | gl.bufferData(gl.ARRAY_BUFFER, current.value, gl.STATIC_DRAW); // or DYNAMIC_DRAW
18 | gl.bindBuffer(gl.ARRAY_BUFFER, null);
19 |
20 | Object.assign(current, {
21 | location,
22 | buffer: b,
23 | });
24 | }
25 | };
26 |
27 | export const bindAttributes = attributes => {
28 | const gl = getContext();
29 |
30 | Object.keys(attributes).forEach(key => {
31 | const { location, buffer, size, instanced } = attributes[key];
32 |
33 | if (location !== -1) {
34 | gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
35 | gl.vertexAttribPointer(location, size, gl.FLOAT, false, 0, 0);
36 | gl.enableVertexAttribArray(location);
37 |
38 | const divisor = instanced ? 1 : 0;
39 | if (getContextType() === CONTEXT.WEBGL2) {
40 | gl.vertexAttribDivisor(location, divisor);
41 | } else {
42 | supports().instancedArrays.vertexAttribDivisorANGLE(
43 | location,
44 | divisor
45 | );
46 | }
47 |
48 | gl.bindBuffer(gl.ARRAY_BUFFER, null);
49 | }
50 | });
51 | };
52 |
53 | export const updateAttributes = attributes => {
54 | const gl = getContext();
55 | Object.keys(attributes).forEach(key => {
56 | const { location, buffer, value } = attributes[key];
57 |
58 | if (location !== -1) {
59 | gl.enableVertexAttribArray(location);
60 | gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
61 | gl.bufferData(gl.ARRAY_BUFFER, value, gl.DYNAMIC_DRAW);
62 | gl.bindBuffer(gl.ARRAY_BUFFER, null);
63 | }
64 | });
65 | };
66 |
--------------------------------------------------------------------------------
/packages/core/src/gl/index.js:
--------------------------------------------------------------------------------
1 | import Ubo from './ubo';
2 | import Vao from './vao';
3 | import { getTypeSize } from './types';
4 | import { createProgram } from './program';
5 | import { initAttributes, bindAttributes, updateAttributes } from './attributes';
6 | import { initUniforms, updateUniforms } from './uniforms';
7 |
8 | export {
9 | Ubo,
10 | Vao,
11 | getTypeSize,
12 | createProgram,
13 | initAttributes,
14 | bindAttributes,
15 | updateAttributes,
16 | initUniforms,
17 | updateUniforms,
18 | };
19 |
--------------------------------------------------------------------------------
/packages/core/src/gl/program.js:
--------------------------------------------------------------------------------
1 | const PROGRAM_POOL = {};
2 |
3 | function createShader(gl, str, type) {
4 | const shader = gl.createShader(type);
5 |
6 | gl.shaderSource(shader, str);
7 | gl.compileShader(shader);
8 |
9 | const compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
10 |
11 | if (!compiled) {
12 | const error = gl.getShaderInfoLog(shader);
13 |
14 | gl.deleteShader(shader);
15 | console.error(error, str);
16 | throw new Error(error);
17 | }
18 |
19 | return shader;
20 | }
21 |
22 | export const createProgram = (gl, vertex, fragment, programID) => {
23 | const pool = PROGRAM_POOL[`pool_${programID}`];
24 | if (!pool) {
25 | const vs = createShader(gl, vertex, gl.VERTEX_SHADER);
26 | const fs = createShader(gl, fragment, gl.FRAGMENT_SHADER);
27 |
28 | const program = gl.createProgram();
29 |
30 | gl.attachShader(program, vs);
31 | gl.attachShader(program, fs);
32 | gl.linkProgram(program);
33 |
34 | PROGRAM_POOL[`pool_${programID}`] = program;
35 |
36 | return program;
37 | }
38 |
39 | return pool;
40 | };
41 |
--------------------------------------------------------------------------------
/packages/core/src/gl/types.js:
--------------------------------------------------------------------------------
1 | export const getTypeSize = type => {
2 | switch (type) {
3 | case 'float':
4 | return 1;
5 | case 'vec2':
6 | return 2;
7 | case 'vec3':
8 | return 3;
9 | case 'vec4':
10 | case 'mat2':
11 | return 4;
12 | case 'mat3':
13 | return 9;
14 | case 'mat4':
15 | return 16;
16 | default:
17 | throw new Error(`"${type}" is an unknown type`);
18 | }
19 | };
20 |
--------------------------------------------------------------------------------
/packages/core/src/gl/ubo.js:
--------------------------------------------------------------------------------
1 | import { getContext } from '../session';
2 |
3 | class Ubo {
4 | constructor(data, boundLocation) {
5 | const gl = getContext();
6 | this.boundLocation = boundLocation;
7 |
8 | this.data = new Float32Array(data);
9 |
10 | this.buffer = gl.createBuffer();
11 | gl.bindBuffer(gl.UNIFORM_BUFFER, this.buffer);
12 | gl.bufferData(gl.UNIFORM_BUFFER, this.data, gl.STATIC_DRAW); // DYNAMIC_DRAW
13 | gl.bindBuffer(gl.UNIFORM_BUFFER, null);
14 | }
15 |
16 | bind() {
17 | const gl = getContext();
18 | gl.bindBufferBase(gl.UNIFORM_BUFFER, this.boundLocation, this.buffer);
19 | // gl.bindBufferBase(gl.UNIFORM_BUFFER, null); // MAYBE?
20 | }
21 |
22 | update(data, offset = 0) {
23 | const gl = getContext();
24 |
25 | this.data.set(data, offset);
26 |
27 | gl.bindBuffer(gl.UNIFORM_BUFFER, this.buffer);
28 | gl.bufferSubData(gl.UNIFORM_BUFFER, 0, this.data, 0, null);
29 | gl.bindBuffer(gl.UNIFORM_BUFFER, null);
30 | }
31 | }
32 |
33 | export default Ubo;
34 |
--------------------------------------------------------------------------------
/packages/core/src/gl/uniforms.js:
--------------------------------------------------------------------------------
1 | import { getContext } from '../session';
2 |
3 | export const initUniforms = (uniforms, program) => {
4 | const gl = getContext();
5 |
6 | const textureIndices = [
7 | gl.TEXTURE0,
8 | gl.TEXTURE1,
9 | gl.TEXTURE2,
10 | gl.TEXTURE3,
11 | gl.TEXTURE4,
12 | gl.TEXTURE5,
13 | ];
14 |
15 | let i = 0;
16 |
17 | Object.keys(uniforms).forEach(prop => {
18 | const current = uniforms[prop];
19 | const location = gl.getUniformLocation(program, prop);
20 |
21 | Object.assign(current, {
22 | location,
23 | });
24 |
25 | if (current.type === 'sampler2D') {
26 | current.textureIndex = i;
27 | current.activeTexture = textureIndices[i];
28 | i++;
29 | }
30 | });
31 | };
32 |
33 | export const updateUniforms = uniforms => {
34 | const gl = getContext();
35 | Object.keys(uniforms).forEach(key => {
36 | const uniform = uniforms[key];
37 |
38 | switch (uniform.type) {
39 | case 'mat4':
40 | gl.uniformMatrix4fv(uniform.location, false, uniform.value);
41 | break;
42 | case 'mat3':
43 | gl.uniformMatrix3fv(uniform.location, false, uniform.value);
44 | break;
45 | case 'vec4':
46 | gl.uniform4fv(uniform.location, uniform.value);
47 | break;
48 | case 'vec3':
49 | gl.uniform3fv(uniform.location, uniform.value);
50 | break;
51 | case 'vec2':
52 | gl.uniform2fv(uniform.location, uniform.value);
53 | break;
54 | case 'float':
55 | gl.uniform1f(uniform.location, uniform.value);
56 | break;
57 | case 'sampler2D':
58 | gl.activeTexture(uniform.activeTexture);
59 | gl.bindTexture(gl.TEXTURE_2D, uniform.value);
60 | gl.uniform1i(uniform.location, uniform.textureIndex);
61 | break;
62 | default:
63 | throw new Error(`"${uniform.type}" is an unknown uniform type`);
64 | }
65 | });
66 | };
67 |
--------------------------------------------------------------------------------
/packages/core/src/gl/vao.js:
--------------------------------------------------------------------------------
1 | import { getContext, getContextType, supports } from '../session';
2 | import { CONTEXT } from '../constants';
3 |
4 | class Vao {
5 | constructor() {
6 | const gl = getContext();
7 | const { vertexArrayObject } = supports();
8 |
9 | if (getContextType() === CONTEXT.WEBGL2) {
10 | this.vao = gl.createVertexArray();
11 | gl.bindVertexArray(this.vao);
12 | } else if (vertexArrayObject) {
13 | this.vao = supports().vertexArrayObject.createVertexArrayOES();
14 | vertexArrayObject.bindVertexArrayOES(this.vao);
15 | }
16 | }
17 |
18 | bind() {
19 | const gl = getContext();
20 | const { vertexArrayObject } = supports();
21 |
22 | if (getContextType() === CONTEXT.WEBGL2) {
23 | gl.bindVertexArray(this.vao);
24 | } else if (vertexArrayObject) {
25 | vertexArrayObject.bindVertexArrayOES(this.vao);
26 | }
27 | }
28 |
29 | unbind() {
30 | const gl = getContext();
31 | const { vertexArrayObject } = supports();
32 |
33 | if (getContextType() === CONTEXT.WEBGL2) {
34 | gl.bindVertexArray(null);
35 | } else if (vertexArrayObject) {
36 | vertexArrayObject.bindVertexArrayOES(null);
37 | }
38 | }
39 |
40 | destroy() {
41 | const gl = getContext();
42 | const { vertexArrayObject } = supports();
43 |
44 | if (getContextType() === CONTEXT.WEBGL2) {
45 | gl.deleteVertexArray(this.vao);
46 | } else if (vertexArrayObject) {
47 | vertexArrayObject.deleteVertexArrayOES(this.vao);
48 | }
49 | this.vao = null;
50 | }
51 | }
52 |
53 | export default Vao;
54 |
--------------------------------------------------------------------------------
/packages/core/src/helpers/axis.js:
--------------------------------------------------------------------------------
1 | import { vec3 } from 'gl-matrix';
2 | import Mesh from '../core/mesh';
3 | import Model from '../core/model';
4 | import { Basic } from '../shaders';
5 |
6 | class AxisHelper extends Model {
7 | constructor(props = {}) {
8 | super();
9 |
10 | const size = (props && props.size) || 10;
11 | const g1 = {
12 | positions: [
13 | ...vec3.fromValues(0, 0, 0),
14 | ...vec3.fromValues(size, 0, 0),
15 | ],
16 | };
17 | const g2 = {
18 | positions: [
19 | ...vec3.fromValues(0, 0, 0),
20 | ...vec3.fromValues(0, size, 0),
21 | ],
22 | };
23 | const g3 = {
24 | positions: [
25 | ...vec3.fromValues(0, 0, 0),
26 | ...vec3.fromValues(0, 0, size),
27 | ],
28 | };
29 |
30 | const m1 = new Basic({
31 | color: vec3.fromValues(1, 0, 0),
32 | wireframe: true,
33 | });
34 | const m2 = new Basic({
35 | color: vec3.fromValues(0, 1, 0),
36 | wireframe: true,
37 | });
38 | const m3 = new Basic({
39 | color: vec3.fromValues(0, 0, 1),
40 | wireframe: true,
41 | });
42 |
43 | const x = new Mesh({ geometry: g1, shader: m1 });
44 | this.add(x);
45 |
46 | const y = new Mesh({ geometry: g2, shader: m2 });
47 | this.add(y);
48 |
49 | const z = new Mesh({ geometry: g3, shader: m3 });
50 | this.add(z);
51 | }
52 | }
53 | export default AxisHelper;
54 |
--------------------------------------------------------------------------------
/packages/core/src/helpers/index.js:
--------------------------------------------------------------------------------
1 | import Axis from './axis';
2 | import Normals from './normal';
3 |
4 | export { Axis, Normals };
5 |
--------------------------------------------------------------------------------
/packages/core/src/helpers/normal.js:
--------------------------------------------------------------------------------
1 | import { vec3 } from 'gl-matrix';
2 | import Mesh from '../core/mesh';
3 | import Model from '../core/model';
4 | import { Basic } from '../shaders';
5 | // import { DRAW } from '../constants';
6 |
7 | class AxisHelper extends Model {
8 | constructor(props = {}) {
9 | super();
10 |
11 | const size = (props && props.size) || 1;
12 | const geometry = {
13 | positions: [],
14 | };
15 |
16 | // extract geometry
17 | const sx = props.model.scale.x;
18 | const sy = props.model.scale.y;
19 | const sz = props.model.scale.z;
20 |
21 | const length = props.model.attributes.a_normal.value.length / 3;
22 | for (let i = 0; i < length; i++) {
23 | const i3 = i * 3;
24 | const v0x = sx * props.model.attributes.a_position.value[i3 + 0];
25 | const v0y = sy * props.model.attributes.a_position.value[i3 + 1];
26 | const v0z = sz * props.model.attributes.a_position.value[i3 + 2];
27 | const nx = props.model.attributes.a_normal.value[i3 + 0];
28 | const ny = props.model.attributes.a_normal.value[i3 + 1];
29 | const nz = props.model.attributes.a_normal.value[i3 + 2];
30 | const v1x = v0x + size * nx;
31 | const v1y = v0y + size * ny;
32 | const v1z = v0z + size * nz;
33 | geometry.positions = geometry.positions.concat([
34 | v0x,
35 | v0y,
36 | v0z,
37 | v1x,
38 | v1y,
39 | v1z,
40 | ]);
41 | }
42 |
43 | const shader = new Basic({
44 | color: vec3.fromValues(0, 1, 1),
45 | wireframe: true,
46 | });
47 | const n = new Mesh({ geometry, shader });
48 | this.add(n);
49 |
50 | this.reference = props.model;
51 | // mode = DRAW.LINES
52 | }
53 |
54 | update() {
55 | super.update();
56 |
57 | vec3.copy(this.position.data, this.reference.position.data);
58 | vec3.copy(this.rotation.data, this.reference.rotation.data);
59 | this.lookToTarget = this.reference.lookToTarget;
60 | }
61 | }
62 | export default AxisHelper;
63 |
--------------------------------------------------------------------------------
/packages/core/src/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Core
3 | * @module core
4 | */
5 | import * as chunks from './shaders/chunks';
6 | import * as utils from './utils';
7 | import * as cameras from './cameras';
8 | import * as shaders from './shaders';
9 | import * as helpers from './helpers';
10 | import * as constants from './constants';
11 |
12 | import Renderer from './core/renderer';
13 | import Object3 from './core/object3';
14 | import Scene from './core/scene';
15 | import Model from './core/model';
16 | import Mesh from './core/mesh';
17 | import Texture from './core/texture';
18 | import RenderTarget from './core/rt';
19 | import Composer from './core/composer';
20 | import Pass from './core/pass';
21 | import Performance from './core/performance';
22 |
23 | export {
24 | chunks,
25 | utils,
26 | cameras,
27 | shaders,
28 | helpers,
29 | constants,
30 | Renderer,
31 | Object3,
32 | Scene,
33 | Model,
34 | Mesh,
35 | Texture,
36 | RenderTarget,
37 | Composer,
38 | Pass,
39 | Performance,
40 | };
41 |
--------------------------------------------------------------------------------
/packages/core/src/passes/basic.js:
--------------------------------------------------------------------------------
1 | const Basic = {
2 | uniforms: {
3 | u_input: { type: 'sampler2D', value: null },
4 | },
5 |
6 | vertex: `
7 | out vec2 v_uv;
8 | void main() {
9 | gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(a_position, 1.0);
10 | v_uv = a_uv;
11 | }`,
12 |
13 | fragment: `
14 | in vec2 v_uv;
15 |
16 | uniform sampler2D u_input;
17 |
18 | void main() {
19 | outColor = texture(u_input, v_uv);
20 | }`,
21 | };
22 |
23 | export default Basic;
24 |
--------------------------------------------------------------------------------
/packages/core/src/passes/index.js:
--------------------------------------------------------------------------------
1 | import Basic from './basic';
2 |
3 | export { Basic };
4 |
--------------------------------------------------------------------------------
/packages/core/src/session.js:
--------------------------------------------------------------------------------
1 | import { CONTEXT } from './constants';
2 |
3 | const library = `lowww-${__LIBRARY__}`;
4 | const version = __VERSION__;
5 |
6 | // per session
7 | let gl = null;
8 | let contextType = null;
9 |
10 | // test context webgl and webgl2
11 | const testContext1 = document.createElement('canvas').getContext(CONTEXT.WEBGL);
12 | const testContext2 = document
13 | .createElement('canvas')
14 | .getContext(CONTEXT.WEBGL2);
15 |
16 | const extensions = {
17 | // used globally
18 | vertexArrayObject: testContext1.getExtension('OES_vertex_array_object'),
19 |
20 | // used for instancing
21 | instancedArrays: testContext1.getExtension('ANGLE_instanced_arrays'),
22 |
23 | // used for flat shading
24 | standardDerivatives: testContext1.getExtension('OES_standard_derivatives'),
25 |
26 | // depth texture
27 | depthTextures: testContext1.getExtension('WEBGL_depth_texture'),
28 | };
29 |
30 | const setContextType = preferred => {
31 | const gl2 = testContext2 && CONTEXT.WEBGL2;
32 | const gl1 = testContext1 && CONTEXT.WEBGL;
33 | contextType = preferred || gl2 || gl1;
34 |
35 | if (contextType === CONTEXT.WEBGL2) {
36 | extensions.vertexArrayObject = true;
37 | extensions.instancedArrays = true;
38 | extensions.standardDerivatives = true;
39 | extensions.depthTexture = true;
40 | }
41 |
42 | return contextType;
43 | };
44 |
45 | const getContextType = () => contextType;
46 |
47 | const setContext = context => {
48 | gl = context;
49 | if (getContextType() === CONTEXT.WEBGL) {
50 | extensions.vertexArrayObject = gl.getExtension(
51 | 'OES_vertex_array_object'
52 | );
53 | extensions.instancedArrays = gl.getExtension('ANGLE_instanced_arrays');
54 | extensions.standardDerivatives = gl.getExtension(
55 | 'OES_standard_derivatives'
56 | );
57 | extensions.depthTextures = gl.getExtension('WEBGL_depth_texture');
58 | }
59 | };
60 |
61 | const getContext = () => gl;
62 |
63 | const supports = () => extensions;
64 |
65 | export {
66 | library,
67 | version,
68 | setContext,
69 | getContext,
70 | setContextType,
71 | getContextType,
72 | supports,
73 | };
74 |
--------------------------------------------------------------------------------
/packages/core/src/shaders/basic.js:
--------------------------------------------------------------------------------
1 | import { vec3 } from 'gl-matrix';
2 | import { UBO, FOG, EXTENSIONS } from './chunks';
3 | import { SHADER_BASIC, DRAW } from '../constants';
4 |
5 | class Basic {
6 | constructor(props = {}) {
7 | const color = props.color || vec3.fromValues(1, 1, 1);
8 |
9 | const vertex = `#version 300 es
10 | ${EXTENSIONS.vertex()}
11 |
12 | in vec3 a_position;
13 |
14 | ${UBO.scene()}
15 | ${UBO.model()}
16 |
17 | void main() {
18 | gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(a_position, 1.0);
19 | }
20 | `;
21 |
22 | const fragment = `#version 300 es
23 | ${EXTENSIONS.fragment()}
24 |
25 | precision highp float;
26 | precision highp int;
27 |
28 | ${UBO.scene()}
29 |
30 | uniform vec3 u_color;
31 |
32 | out vec4 outColor;
33 |
34 | void main() {
35 | vec4 base = vec4(u_color, 1.0);
36 |
37 | ${FOG.linear()}
38 |
39 | outColor = base;
40 | }
41 | `;
42 |
43 | return Object.assign(
44 | {
45 | type: SHADER_BASIC,
46 | mode: props.wireframe === true ? DRAW.LINES : DRAW.TRIANGLES,
47 | },
48 | {
49 | vertex,
50 | fragment,
51 | uniforms: {
52 | u_color: {
53 | type: 'vec3',
54 | value: color,
55 | },
56 | },
57 | }
58 | );
59 | }
60 | }
61 |
62 | export default Basic;
63 |
--------------------------------------------------------------------------------
/packages/core/src/shaders/billboard.js:
--------------------------------------------------------------------------------
1 | import { UBO, LIGHT, FOG, CLIPPING, EXTENSIONS, SHADOW } from './chunks';
2 | import { SHADER_BILLBOARD, DRAW } from '../constants';
3 |
4 | class Billboard {
5 | constructor(props = {}) {
6 | const vertex = `#version 300 es
7 | ${EXTENSIONS.vertex()}
8 |
9 | in vec3 a_position;
10 | in vec3 a_normal;
11 | in vec2 a_uv;
12 |
13 | ${UBO.scene()}
14 | ${UBO.model()}
15 | ${CLIPPING.vertex_pre()}
16 | ${SHADOW.vertex_pre()}
17 |
18 | out vec3 fragVertexEc;
19 | out vec2 v_uv;
20 | out vec3 v_normal;
21 |
22 | void main() {
23 | vec4 worldPosition = modelMatrix * vec4(a_position, 1.0);
24 | vec4 position = projectionMatrix * viewMatrix * worldPosition;
25 | gl_Position = position;
26 |
27 | fragVertexEc = position.xyz; // worldPosition.xyz;
28 | v_uv = a_uv;
29 | v_normal = (normalMatrix * vec4(a_normal, 1.0)).xyz;
30 |
31 | ${SHADOW.vertex()}
32 | ${CLIPPING.vertex()}
33 | }
34 | `;
35 |
36 | const fragment = `#version 300 es
37 | ${EXTENSIONS.fragment()}
38 |
39 | precision highp float;
40 | precision highp int;
41 |
42 | in vec3 fragVertexEc;
43 | in vec2 v_uv;
44 | in vec3 v_normal;
45 |
46 | ${CLIPPING.fragment_pre()}
47 |
48 | ${UBO.scene()}
49 | ${UBO.model()}
50 | ${UBO.lights()}
51 |
52 | ${SHADOW.fragment_pre()}
53 |
54 | out vec4 outColor;
55 |
56 | ${props.fragment ||
57 | 'void mainImage( out vec4 fragColor, in vec2 fragCoord ) { fragColor = vec4(0.0, 1.0, 1.0, 1.0); }'}
58 |
59 | void main() {
60 | vec4 base = vec4(0.0, 0.0, 0.0, 1.0);
61 | mainImage(base, gl_FragCoord.xy);
62 |
63 | ${SHADOW.fragment()}
64 | ${LIGHT.factory()}
65 | ${FOG.linear()}
66 | ${CLIPPING.fragment()}
67 |
68 | outColor = base;
69 | }
70 | `;
71 |
72 | return Object.assign(
73 | {
74 | type: SHADER_BILLBOARD,
75 | mode: props.wireframe === true ? DRAW.LINES : DRAW.TRIANGLES,
76 | },
77 | {
78 | vertex,
79 | fragment,
80 | uniforms: {},
81 | }
82 | );
83 | }
84 | }
85 |
86 | export default Billboard;
87 |
--------------------------------------------------------------------------------
/packages/core/src/shaders/chunks/clipping.js:
--------------------------------------------------------------------------------
1 | const CLIPPING = {
2 | vertex_pre: () => {
3 | return `
4 | out vec4 local_eyespace;
5 | out vec4 global_eyespace;`;
6 | },
7 |
8 | vertex: () => {
9 | return `
10 | local_eyespace = modelMatrix * vec4(a_position, 1.0);
11 | global_eyespace = viewMatrix * modelMatrix * vec4(a_position, 1.0);`;
12 | },
13 |
14 | fragment_pre: () => {
15 | return `
16 | in vec4 local_eyespace;
17 | in vec4 global_eyespace;`;
18 | },
19 |
20 | fragment: () => {
21 | return `
22 | if (localClipSettings.x > 0.0) {
23 | if(dot(local_eyespace, localClipPlane0) < 0.0) discard;
24 | if(dot(local_eyespace, localClipPlane1) < 0.0) discard;
25 | if(dot(local_eyespace, localClipPlane2) < 0.0) discard;
26 | }
27 |
28 | if (globalClipSettings.x > 0.0) {
29 | if(dot(global_eyespace, globalClipPlane0) < 0.0) discard;
30 | if(dot(global_eyespace, globalClipPlane1) < 0.0) discard;
31 | if(dot(global_eyespace, globalClipPlane2) < 0.0) discard;
32 | }`;
33 | },
34 | };
35 |
36 | export { CLIPPING };
37 |
--------------------------------------------------------------------------------
/packages/core/src/shaders/chunks/extensions.js:
--------------------------------------------------------------------------------
1 | import { getContextType } from '../../session';
2 | import { CONTEXT } from '../../constants';
3 |
4 | const EXTENSIONS = {
5 | vertex: () => {
6 | if (getContextType() === CONTEXT.WEBGL2) {
7 | return '';
8 | }
9 | return '';
10 | },
11 |
12 | fragment: () => {
13 | if (getContextType() === CONTEXT.WEBGL2) {
14 | return '';
15 | }
16 | return `
17 | #extension GL_OES_standard_derivatives : enable`;
18 | },
19 | };
20 |
21 | export { EXTENSIONS };
22 |
--------------------------------------------------------------------------------
/packages/core/src/shaders/chunks/fog.js:
--------------------------------------------------------------------------------
1 | function base() {
2 | return `
3 | float fogStart = fogSettings.y;
4 | float fogEnd = fogSettings.z;
5 | float fogDensity = fogSettings.a;
6 |
7 | float dist = 0.0;
8 | float fogFactor = 0.0;
9 | dist = gl_FragCoord.z / gl_FragCoord.w;`;
10 | }
11 |
12 | const FOG = {
13 | linear: () => {
14 | return `
15 | if (fogSettings.x > 0.0) {
16 | ${base()}
17 | fogFactor = (fogEnd - dist) / (fogEnd - fogStart);
18 | fogFactor = clamp(fogFactor, 0.0, 1.0);
19 | base = mix(fogColor, base, fogFactor);
20 | }`;
21 | },
22 | exponential: () => {
23 | return `
24 | if (fogSettings.x > 0.0) {
25 | ${base()}
26 | fogFactor = 1.0 / exp(dist * fogDensity);
27 | fogFactor = clamp(fogFactor, 0.0, 1.0);
28 | base = mix(fogColor, base, fogFactor);
29 | }`;
30 | },
31 | exponential2: () => {
32 | return `
33 | if (fogSettings.x > 0.0) {
34 | ${base()}
35 | fogFactor = 1.0 / exp((dist * fogDensity) * (dist * fogDensity));
36 | fogFactor = clamp(fogFactor, 0.0, 1.0);
37 | base = mix(fogColor, base, fogFactor);
38 | }`;
39 | },
40 | };
41 |
42 | export { FOG };
43 |
--------------------------------------------------------------------------------
/packages/core/src/shaders/chunks/index.js:
--------------------------------------------------------------------------------
1 | import { LIGHT } from './light';
2 | import { FOG } from './fog';
3 | import { UBO } from './ubo';
4 | import { NOISE } from './noise';
5 | import { CLIPPING } from './clipping';
6 | import { EXTENSIONS } from './extensions';
7 | import { SHADOW } from './shadow';
8 |
9 | export { UBO, LIGHT, FOG, NOISE, CLIPPING, EXTENSIONS, SHADOW };
10 |
--------------------------------------------------------------------------------
/packages/core/src/shaders/chunks/light.js:
--------------------------------------------------------------------------------
1 | const LIGHT = {
2 | factory: () => {
3 | return `
4 | // factory light
5 | vec3 inverseLightDirection = normalize(vec3(-0.25, -0.25, 1.0));
6 | vec3 directionalColor = vec3(max(dot(v_normal, inverseLightDirection), 0.0));
7 | vec3 factory = mix(vec3(0.0), directionalColor, 0.989); // light intensity
8 | base.rgb *= factory;
9 |
10 | ${LIGHT.directional()}`;
11 | },
12 |
13 | directional: () => {
14 | return `
15 | // vec3 dcolor = vec3(0.01);
16 | //
17 | // for (int i = 0; i < MAX_DIRECTIONAL; i++) {
18 | // vec3 inverseLightDirection = normalize(directionalLights[i].dlPosition.xyz);
19 | // vec3 light = vec3(max(dot(v_normal, inverseLightDirection), 0.0));
20 | // vec3 directionalColor = directionalLights[i].dlColor.rgb * light;
21 | // dcolor += mix(dcolor, directionalColor, directionalLights[i].flIntensity);
22 | // }
23 | // dcolor /= float(MAX_DIRECTIONAL);
24 | //
25 | // base.rgb *= dcolor;
26 | `;
27 | },
28 | };
29 |
30 | export { LIGHT };
31 |
--------------------------------------------------------------------------------
/packages/core/src/shaders/chunks/noise.js:
--------------------------------------------------------------------------------
1 | const NOISE = () => {
2 | return `
3 | vec3 mod289(vec3 x){return x-floor(x*(1./289.))*289.;}vec4 mod289(vec4 x){return x-floor(x*(1./289.))*289.;}vec4 permute(vec4 x){return mod289((x*34.+1.)*x);}vec4 taylorInvSqrt(vec4 r){return 1.79284-.853735*r;}vec3 fade(vec3 t){return t*t*t*(t*(t*6.-15.)+10.);}float cnoise(vec3 P){vec3 Pi0=floor(P),Pi1=Pi0+vec3(1.);Pi0=mod289(Pi0);Pi1=mod289(Pi1);vec3 Pf0=fract(P),Pf1=Pf0-vec3(1.);vec4 ix=vec4(Pi0.r,Pi1.r,Pi0.r,Pi1.r),iy=vec4(Pi0.gg,Pi1.gg),iz0=Pi0.bbbb,iz1=Pi1.bbbb,ixy=permute(permute(ix)+iy),ixy0=permute(ixy+iz0),ixy1=permute(ixy+iz1),gx0=ixy0*(1./7.),gy0=fract(floor(gx0)*(1./7.))-.5;gx0=fract(gx0);vec4 gz0=vec4(.5)-abs(gx0)-abs(gy0),sz0=step(gz0,vec4(0.));gx0-=sz0*(step(0.,gx0)-.5);gy0-=sz0*(step(0.,gy0)-.5);vec4 gx1=ixy1*(1./7.),gy1=fract(floor(gx1)*(1./7.))-.5;gx1=fract(gx1);vec4 gz1=vec4(.5)-abs(gx1)-abs(gy1),sz1=step(gz1,vec4(0.));gx1-=sz1*(step(0.,gx1)-.5);gy1-=sz1*(step(0.,gy1)-.5);vec3 g000=vec3(gx0.r,gy0.r,gz0.r),g100=vec3(gx0.g,gy0.g,gz0.g),g010=vec3(gx0.b,gy0.b,gz0.b),g110=vec3(gx0.a,gy0.a,gz0.a),g001=vec3(gx1.r,gy1.r,gz1.r),g101=vec3(gx1.g,gy1.g,gz1.g),g011=vec3(gx1.b,gy1.b,gz1.b),g111=vec3(gx1.a,gy1.a,gz1.a);vec4 norm0=taylorInvSqrt(vec4(dot(g000,g000),dot(g010,g010),dot(g100,g100),dot(g110,g110)));g000*=norm0.r;g010*=norm0.g;g100*=norm0.b;g110*=norm0.a;vec4 norm1=taylorInvSqrt(vec4(dot(g001,g001),dot(g011,g011),dot(g101,g101),dot(g111,g111)));g001*=norm1.r;g011*=norm1.g;g101*=norm1.b;g111*=norm1.a;float n000=dot(g000,Pf0),n100=dot(g100,vec3(Pf1.r,Pf0.gb)),n010=dot(g010,vec3(Pf0.r,Pf1.g,Pf0.b)),n110=dot(g110,vec3(Pf1.rg,Pf0.b)),n001=dot(g001,vec3(Pf0.rg,Pf1.b)),n101=dot(g101,vec3(Pf1.r,Pf0.g,Pf1.b)),n011=dot(g011,vec3(Pf0.r,Pf1.gb)),n111=dot(g111,Pf1);vec3 fade_xyz=fade(Pf0);vec4 n_z=mix(vec4(n000,n100,n010,n110),vec4(n001,n101,n011,n111),fade_xyz.b);vec2 n_yz=mix(n_z.rg,n_z.ba,fade_xyz.g);float n_xyz=mix(n_yz.r,n_yz.g,fade_xyz.r);return 2.2*n_xyz;}float pnoise(vec3 P,vec3 rep){vec3 Pi0=mod(floor(P),rep),Pi1=mod(Pi0+vec3(1.),rep);Pi0=mod289(Pi0);Pi1=mod289(Pi1);vec3 Pf0=fract(P),Pf1=Pf0-vec3(1.);vec4 ix=vec4(Pi0.r,Pi1.r,Pi0.r,Pi1.r),iy=vec4(Pi0.gg,Pi1.gg),iz0=Pi0.bbbb,iz1=Pi1.bbbb,ixy=permute(permute(ix)+iy),ixy0=permute(ixy+iz0),ixy1=permute(ixy+iz1),gx0=ixy0*(1./7.),gy0=fract(floor(gx0)*(1./7.))-.5;gx0=fract(gx0);vec4 gz0=vec4(.5)-abs(gx0)-abs(gy0),sz0=step(gz0,vec4(0.));gx0-=sz0*(step(0.,gx0)-.5);gy0-=sz0*(step(0.,gy0)-.5);vec4 gx1=ixy1*(1./7.),gy1=fract(floor(gx1)*(1./7.))-.5;gx1=fract(gx1);vec4 gz1=vec4(.5)-abs(gx1)-abs(gy1),sz1=step(gz1,vec4(0.));gx1-=sz1*(step(0.,gx1)-.5);gy1-=sz1*(step(0.,gy1)-.5);vec3 g000=vec3(gx0.r,gy0.r,gz0.r),g100=vec3(gx0.g,gy0.g,gz0.g),g010=vec3(gx0.b,gy0.b,gz0.b),g110=vec3(gx0.a,gy0.a,gz0.a),g001=vec3(gx1.r,gy1.r,gz1.r),g101=vec3(gx1.g,gy1.g,gz1.g),g011=vec3(gx1.b,gy1.b,gz1.b),g111=vec3(gx1.a,gy1.a,gz1.a);vec4 norm0=taylorInvSqrt(vec4(dot(g000,g000),dot(g010,g010),dot(g100,g100),dot(g110,g110)));g000*=norm0.r;g010*=norm0.g;g100*=norm0.b;g110*=norm0.a;vec4 norm1=taylorInvSqrt(vec4(dot(g001,g001),dot(g011,g011),dot(g101,g101),dot(g111,g111)));g001*=norm1.r;g011*=norm1.g;g101*=norm1.b;g111*=norm1.a;float n000=dot(g000,Pf0),n100=dot(g100,vec3(Pf1.r,Pf0.gb)),n010=dot(g010,vec3(Pf0.r,Pf1.g,Pf0.b)),n110=dot(g110,vec3(Pf1.rg,Pf0.b)),n001=dot(g001,vec3(Pf0.rg,Pf1.b)),n101=dot(g101,vec3(Pf1.r,Pf0.g,Pf1.b)),n011=dot(g011,vec3(Pf0.r,Pf1.gb)),n111=dot(g111,Pf1);vec3 fade_xyz=fade(Pf0);vec4 n_z=mix(vec4(n000,n100,n010,n110),vec4(n001,n101,n011,n111),fade_xyz.b);vec2 n_yz=mix(n_z.rg,n_z.ba,fade_xyz.g);float n_xyz=mix(n_yz.r,n_yz.g,fade_xyz.r);return 2.2*n_xyz;}
4 | `;
5 | };
6 |
7 | export { NOISE };
8 |
--------------------------------------------------------------------------------
/packages/core/src/shaders/chunks/shadow.js:
--------------------------------------------------------------------------------
1 | function hard() {
2 | return `
3 | float hardShadow1(sampler2D shadowMap) {
4 | vec4 shadowCoord = vShadowCoord / vShadowCoord.w;
5 | vec2 uv = shadowCoord.xy;
6 | float shadow = texture(shadowMap, uv).r;
7 |
8 | float visibility = 1.0;
9 | float shadowAmount = 0.5;
10 |
11 | float cosTheta = clamp(dot(v_normal, vShadowCoord.xyz), 0.0, 1.0);
12 | float bias = 0.00005 * tan(acos(cosTheta)); // cosTheta is dot( n,l ), clamped between 0 and 1
13 | bias = clamp(bias, 0.0, 0.001);
14 |
15 | if (shadow < shadowCoord.z - bias){
16 | visibility = shadowAmount;
17 | }
18 | return visibility;
19 | }
20 |
21 | float hardShadow2(sampler2D shadowMap) {
22 | vec4 shadowCoord = vShadowCoord / vShadowCoord.w;
23 | vec2 uv = shadowCoord.xy;
24 |
25 | float lightDepth1 = texture(shadowMap, uv).r;
26 | float lightDepth2 = clamp(shadowCoord.z, 0.0, 1.0);
27 | float bias = 0.0001;
28 |
29 | return step(lightDepth2, lightDepth1+bias);
30 | }
31 |
32 | float hardShadow3(sampler2D shadowMap) {
33 | vec4 shadowCoord = vShadowCoord / vShadowCoord.w;
34 | vec2 uv = shadowCoord.xy;
35 |
36 | float visibility = 1.0;
37 | float shadowAmount = 0.5;
38 | float bias = 0.00005;
39 |
40 | vec2 poissonDisk[16];
41 | poissonDisk[0] = vec2(-0.94201624, -0.39906216);
42 | poissonDisk[1] = vec2(0.94558609, -0.76890725);
43 | poissonDisk[2] = vec2(-0.094184101, -0.92938870);
44 | poissonDisk[3] = vec2(0.34495938, 0.29387760);
45 | poissonDisk[4] = vec2(-0.91588581, 0.45771432);
46 | poissonDisk[5] = vec2(-0.81544232, -0.87912464);
47 | poissonDisk[6] = vec2(-0.38277543, 0.27676845);
48 | poissonDisk[7] = vec2(0.97484398, 0.75648379);
49 | poissonDisk[8] = vec2(0.44323325, -0.97511554);
50 | poissonDisk[9] = vec2(0.53742981, -0.47373420);
51 | poissonDisk[10] = vec2(-0.26496911, -0.41893023);
52 | poissonDisk[11] = vec2(0.79197514, 0.19090188);
53 | poissonDisk[12] = vec2(-0.24188840, 0.99706507);
54 | poissonDisk[13] = vec2(-0.81409955, 0.91437590);
55 | poissonDisk[14] = vec2(0.19984126, 0.78641367);
56 | poissonDisk[15] = vec2(0.14383161, -0.14100790);
57 |
58 | for (int i=0;i<16;i++) {
59 | if ( texture(shadowMap, uv + poissonDisk[i]/700.0).r < shadowCoord.z-bias ){
60 | visibility -= 0.02;
61 | }
62 | }
63 |
64 | return visibility;
65 | }
66 |
67 | `;
68 | }
69 |
70 | const SHADOW = {
71 | vertex_pre: () => {
72 | return `
73 | uniform mat4 shadowMatrix;
74 | out vec4 vShadowCoord;`;
75 | },
76 |
77 | vertex: () => {
78 | return `
79 | vShadowCoord = shadowMatrix * modelMatrix * vec4(a_position, 1.0);`;
80 | },
81 |
82 | fragment_pre: () => {
83 | return `
84 | uniform sampler2D shadowMap;
85 | in vec4 vShadowCoord;
86 |
87 | ${hard()}`;
88 | },
89 |
90 | fragment: () => {
91 | return `
92 | // shadows
93 | float shadow = 1.0;
94 |
95 | // OPTION 1
96 | shadow = hardShadow1(shadowMap);
97 |
98 | base *= shadow;
99 | `;
100 | },
101 | };
102 |
103 | export { SHADOW };
104 |
--------------------------------------------------------------------------------
/packages/core/src/shaders/chunks/ubo.js:
--------------------------------------------------------------------------------
1 | import { CONTEXT, MAX_DIRECTIONAL } from '../../constants';
2 | import { getContextType } from '../../session';
3 |
4 | const UBO = {
5 | scene: () => {
6 | if (getContextType() === CONTEXT.WEBGL2) {
7 | return `
8 | uniform perScene {
9 | mat4 projectionMatrix;
10 | mat4 viewMatrix;
11 | vec4 fogSettings;
12 | vec4 fogColor;
13 | float iGlobalTime;
14 | vec4 globalClipSettings;
15 | vec4 globalClipPlane0;
16 | vec4 globalClipPlane1;
17 | vec4 globalClipPlane2;
18 | };`;
19 | }
20 |
21 | return `
22 | uniform mat4 projectionMatrix;
23 | uniform mat4 viewMatrix;
24 | uniform vec4 fogSettings;
25 | uniform vec4 fogColor;
26 | uniform float iGlobalTime;
27 | uniform vec4 globalClipSettings;
28 | uniform vec4 globalClipPlane0;
29 | uniform vec4 globalClipPlane1;
30 | uniform vec4 globalClipPlane2;`;
31 | },
32 |
33 | model: () => {
34 | if (getContextType() === CONTEXT.WEBGL2) {
35 | return `
36 | uniform perModel {
37 | mat4 modelMatrix;
38 | mat4 normalMatrix;
39 | vec4 localClipSettings;
40 | vec4 localClipPlane0;
41 | vec4 localClipPlane1;
42 | vec4 localClipPlane2;
43 | };`;
44 | }
45 | return `
46 | uniform mat4 modelMatrix;
47 | uniform mat4 normalMatrix;
48 | uniform vec4 localClipSettings;
49 | uniform vec4 localClipPlane0;
50 | uniform vec4 localClipPlane1;
51 | uniform vec4 localClipPlane2;`;
52 | },
53 |
54 | lights: () => {
55 | if (getContextType() === CONTEXT.WEBGL2) {
56 | return `
57 | #define MAX_DIRECTIONAL ${MAX_DIRECTIONAL}
58 |
59 | struct Directional {
60 | vec4 dlPosition;
61 | vec4 dlColor;
62 | float flIntensity;
63 | };
64 |
65 | uniform directional {
66 | Directional directionalLights[MAX_DIRECTIONAL];
67 | };`;
68 | }
69 |
70 | return `
71 | #define MAX_DIRECTIONAL ${MAX_DIRECTIONAL}
72 |
73 | struct Directional {
74 | vec4 dlPosition;
75 | vec4 dlColor;
76 | float flIntensity;
77 | };
78 |
79 | uniform Directional directionalLights[MAX_DIRECTIONAL];`;
80 | },
81 | };
82 |
83 | export { UBO };
84 |
--------------------------------------------------------------------------------
/packages/core/src/shaders/default.js:
--------------------------------------------------------------------------------
1 | import { vec3 } from 'gl-matrix';
2 | import Texture from '../core/texture';
3 | import { UBO, LIGHT, FOG, CLIPPING, EXTENSIONS, SHADOW } from './chunks';
4 | import { SHADER_DEFAULT, DRAW } from '../constants';
5 |
6 | class Default {
7 | constructor(props = {}) {
8 | const color = props.color || vec3.fromValues(1, 1, 1);
9 | this.map = new Texture({ transparent: true });
10 |
11 | // map: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/620678/red.jpg'.
12 | if (props.map) {
13 | this.map.fromImage(props.map);
14 | }
15 |
16 | // texture: new Texture()
17 | if (props.texture) {
18 | this.map = props.texture;
19 | }
20 |
21 | const vertex = `#version 300 es
22 | ${EXTENSIONS.vertex()}
23 |
24 | in vec3 a_position;
25 | in vec3 a_normal;
26 | in vec2 a_uv;
27 |
28 | ${UBO.scene()}
29 | ${UBO.model()}
30 | ${CLIPPING.vertex_pre()}
31 | ${SHADOW.vertex_pre()}
32 |
33 | out vec3 fragVertexEc;
34 | out vec2 v_uv;
35 | out vec3 v_normal;
36 |
37 | void main() {
38 | vec4 worldPosition = modelMatrix * vec4(a_position, 1.0);
39 | vec4 position = projectionMatrix * viewMatrix * worldPosition;
40 | gl_Position = position;
41 |
42 | fragVertexEc = position.xyz; // worldPosition.xyz;
43 | v_uv = a_uv;
44 | v_normal = (normalMatrix * vec4(a_normal, 1.0)).xyz;
45 |
46 | ${SHADOW.vertex()}
47 | ${CLIPPING.vertex()}
48 | }
49 | `;
50 |
51 | const fragment = `#version 300 es
52 | ${EXTENSIONS.fragment()}
53 |
54 | precision highp float;
55 | precision highp int;
56 |
57 | in vec3 fragVertexEc;
58 | in vec2 v_uv;
59 | in vec3 v_normal;
60 |
61 | ${CLIPPING.fragment_pre()}
62 |
63 | ${UBO.scene()}
64 | ${UBO.model()}
65 | ${UBO.lights()}
66 |
67 | uniform sampler2D u_map;
68 | uniform vec3 u_color;
69 |
70 | ${SHADOW.fragment_pre()}
71 |
72 | out vec4 outColor;
73 |
74 | void main() {
75 | vec3 v_normal = normalize(cross(dFdx(fragVertexEc), dFdy(fragVertexEc)));
76 |
77 | vec4 base = vec4(0.0, 0.0, 0.0, 1.0);
78 | base += vec4(u_color, 1.0);
79 | base *= texture(u_map, v_uv);
80 |
81 | ${SHADOW.fragment()}
82 | ${LIGHT.factory()}
83 | ${FOG.linear()}
84 | ${CLIPPING.fragment()}
85 |
86 | outColor = base;
87 | }
88 | `;
89 |
90 | return Object.assign(
91 | {
92 | type: SHADER_DEFAULT,
93 | mode: props.wireframe === true ? DRAW.LINES : DRAW.TRIANGLES,
94 | },
95 | {
96 | vertex,
97 | fragment,
98 | uniforms: {
99 | u_map: {
100 | type: 'sampler2D',
101 | value: this.map.texture,
102 | },
103 |
104 | u_color: {
105 | type: 'vec3',
106 | value: color,
107 | },
108 | },
109 | }
110 | );
111 | }
112 | }
113 |
114 | export default Default;
115 |
--------------------------------------------------------------------------------
/packages/core/src/shaders/index.js:
--------------------------------------------------------------------------------
1 | import Basic from './basic';
2 | import Default from './default';
3 | import Billboard from './billboard';
4 | import Sem from './sem';
5 |
6 | export { Basic, Default, Billboard, Sem };
7 |
--------------------------------------------------------------------------------
/packages/core/src/shaders/sem.js:
--------------------------------------------------------------------------------
1 | import Texture from '../core/texture';
2 | import { UBO, FOG, CLIPPING, EXTENSIONS } from './chunks';
3 | import { SHADER_SEM } from '../constants';
4 |
5 | class Sem {
6 | constructor(props = {}) {
7 | this.map = new Texture({ transparent: true });
8 |
9 | if (props.map) {
10 | this.map.fromImage(props.map);
11 | }
12 |
13 | // texture: new Texture()
14 | if (props.texture) {
15 | this.map = props.texture;
16 | }
17 |
18 | const vertex = `#version 300 es
19 | ${EXTENSIONS.vertex()}
20 |
21 | in vec3 a_position;
22 | in vec3 a_normal;
23 | in vec2 a_uv;
24 |
25 | ${UBO.scene()}
26 | ${UBO.model()}
27 | ${CLIPPING.vertex_pre()}
28 |
29 | out vec2 v_uv;
30 |
31 | void main() {
32 | vec4 position = viewMatrix * modelMatrix * vec4(a_position, 1.0);
33 | gl_Position = projectionMatrix * position;
34 |
35 | vec3 v_e = vec3(position);
36 | vec3 v_n = mat3(viewMatrix * modelMatrix) * a_normal;
37 | vec3 r = reflect(normalize(v_e), normalize(v_n));
38 | float m = 2.0 * sqrt(pow(r.x, 2.0) + pow(r.y, 2.0) + pow(r.z + 1.0, 2.0));
39 | v_uv = r.xy / m + 0.5;
40 |
41 | ${CLIPPING.vertex()}
42 | }
43 | `;
44 |
45 | const fragment = `#version 300 es
46 | ${EXTENSIONS.fragment()}
47 |
48 | precision highp float;
49 | precision highp int;
50 |
51 | in vec2 v_uv;
52 |
53 | ${CLIPPING.fragment_pre()}
54 |
55 | ${UBO.scene()}
56 | ${UBO.model()}
57 | ${UBO.lights()}
58 |
59 | uniform sampler2D u_map;
60 |
61 | out vec4 outColor;
62 |
63 | void main() {
64 | vec4 base = vec4(0.0, 0.0, 0.0, 1.0);
65 |
66 | base += texture(u_map, v_uv);
67 |
68 | ${FOG.linear()}
69 | ${CLIPPING.fragment()}
70 |
71 | outColor = base;
72 | }
73 | `;
74 |
75 | return Object.assign(
76 | {
77 | type: SHADER_SEM,
78 | },
79 | {
80 | vertex,
81 | fragment,
82 | uniforms: {
83 | u_map: {
84 | type: 'sampler2D',
85 | value: this.map.texture,
86 | },
87 | },
88 | }
89 | );
90 | }
91 | }
92 |
93 | export default Sem;
94 |
--------------------------------------------------------------------------------
/packages/core/src/utils/color.js:
--------------------------------------------------------------------------------
1 | import { vec3 } from 'gl-matrix';
2 |
3 | // pvt
4 | function normalize(array) {
5 | return vec3.fromValues(array[0] / 255, array[1] / 255, array[2] / 255);
6 | }
7 |
8 | export function hexIntToRgb(hex) {
9 | const r = hex >> 16;
10 | const g = (hex >> 8) & 0xff; // eslint-disable-line
11 | const b = hex & 0xff;
12 | return vec3.fromValues(r, g, b);
13 | }
14 |
15 | export function hexStringToRgb(hex) {
16 | const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
17 | return result
18 | ? vec3.fromValues(
19 | parseInt(result[1], 16),
20 | parseInt(result[2], 16),
21 | parseInt(result[3], 16)
22 | )
23 | : null;
24 | }
25 |
26 | export function componentToHex(c) {
27 | const hex = c.toString(16);
28 | return hex.length === 1 ? `0${hex}` : hex;
29 | }
30 |
31 | export function rgbToHex(r, g, b) {
32 | const hexR = componentToHex(r);
33 | const hexG = componentToHex(g);
34 | const hexB = componentToHex(b);
35 | return `#${hexR}${hexG}${hexB}`;
36 | }
37 |
38 | export function convert(hex) {
39 | const color = vec3.create();
40 | const rgb =
41 | typeof hex === 'number' ? hexIntToRgb(hex) : hexStringToRgb(hex);
42 | vec3.copy(color, normalize(rgb));
43 | return color;
44 | }
45 |
--------------------------------------------------------------------------------
/packages/core/src/utils/dom.js:
--------------------------------------------------------------------------------
1 | export function resize(domElement, width, height, ratio) {
2 | domElement.width = width * ratio;
3 | domElement.height = height * ratio;
4 | domElement.style.width = `${width}px`;
5 | domElement.style.height = `${height}px`;
6 | }
7 |
8 | export function unsupported() {
9 | const div = document.createElement('div');
10 | div.innerHTML =
11 | 'Your browser doesn\'t support WebGL.Get WebGL ';
12 | div.style.display = 'table';
13 | div.style.margin = '20px auto 0 auto';
14 | div.style.border = '1px solid #333';
15 | div.style.backgroundColor = 'rgba(255, 255, 255, 0.1)';
16 | div.style.borderRadius = '4px';
17 | div.style.padding = '10px';
18 | div.style.fontFamily = 'monospace';
19 | div.style.fontSize = '12px';
20 | div.style.textAlign = 'center';
21 | return div;
22 | }
23 |
--------------------------------------------------------------------------------
/packages/core/src/utils/index.js:
--------------------------------------------------------------------------------
1 | import * as color from './color';
2 | import * as math from './math';
3 | import glsl3to1 from './glsl-parser';
4 |
5 | export { color, math, glsl3to1 };
6 |
--------------------------------------------------------------------------------
/packages/core/src/utils/math.js:
--------------------------------------------------------------------------------
1 | export function randomRange(min, max) {
2 | return Math.random() * (max - min) + min;
3 | }
4 |
5 | export function mod(m, n) {
6 | return ((m % n) + n) % n;
7 | }
8 |
--------------------------------------------------------------------------------
/packages/geometries/README.md:
--------------------------------------------------------------------------------
1 | # lowww-geometries
2 | Adds geometries for the [lowww](https://github.com/andrevenancio/lowww) engine.
3 |
4 | ## Installation
5 | `npm install --save lowww-geometries`
6 |
7 |
8 | ## Usage
9 | ```javascript
10 | import { Renderer, Scene, cameras, Mesh } from 'lowww-core';
11 | import { Icosahedron } from 'lowww-geometries';
12 |
13 | let renderer;
14 | let camera;
15 | let scene;
16 | let mesh;
17 |
18 | init();
19 | update();
20 |
21 | const init = () => {
22 | renderer = new Renderer();
23 | renderer.setSize(400, 300);
24 | document.body.appendChild(renderer.domElement);
25 |
26 | camera = new cameras.Perspective();
27 | camera.position.set(0, 0, 500);
28 |
29 | scene = new Scene();
30 |
31 | const geometry = new Icosahedron({ radius: 10, detail: 1 });
32 | mesh = new Mesh({ geometry });
33 | scene.add(mesh);
34 | };
35 |
36 | const update = () => {
37 | renderer.render(scene, camera);
38 | requestAnimationFrame(update.bind(this));
39 | };
40 | ```
41 |
42 |
43 | ## License
44 | MIT
45 |
--------------------------------------------------------------------------------
/packages/geometries/package.json:
--------------------------------------------------------------------------------
1 | {"name":"lowww-geometries","description":"WebGL 2 Engine extension","author":"Andre Venancio (info@andrevenancio.com)","version":"1.1.5","main":"src/index.js","module":"build/geometries.module.js","repository":"git@github.com:andrevenancio/lowww.git","scripts":{"test":"echo 'Error: no test specified' && exit 0"},"devDependencies":{},"dependencies":{"gl-matrix":"^2.5.1"}}
--------------------------------------------------------------------------------
/packages/geometries/src/hexahedron/index.js:
--------------------------------------------------------------------------------
1 | import Polyhedra from '../polyhedra';
2 |
3 | class Hexahedron extends Polyhedra {
4 | constructor(props) {
5 | const settings = Object.assign(
6 | {},
7 | {
8 | radius: 0.5,
9 | detail: 0,
10 | },
11 | props
12 | );
13 |
14 | const r = settings.radius * 2;
15 |
16 | const positions = [
17 | // Front face
18 | -1.0,
19 | -1.0,
20 | 1.0,
21 | 1.0,
22 | -1.0,
23 | 1.0,
24 | 1.0,
25 | 1.0,
26 | 1.0,
27 | -1.0,
28 | 1.0,
29 | 1.0,
30 | // Back face
31 | -1.0,
32 | -1.0,
33 | -1.0,
34 | -1.0,
35 | 1.0,
36 | -1.0,
37 | 1.0,
38 | 1.0,
39 | -1.0,
40 | 1.0,
41 | -1.0,
42 | -1.0,
43 | // Top face
44 | -1.0,
45 | 1.0,
46 | -1.0,
47 | -1.0,
48 | 1.0,
49 | 1.0,
50 | 1.0,
51 | 1.0,
52 | 1.0,
53 | 1.0,
54 | 1.0,
55 | -1.0,
56 | // Bottom face
57 | -1.0,
58 | -1.0,
59 | -1.0,
60 | 1.0,
61 | -1.0,
62 | -1.0,
63 | 1.0,
64 | -1.0,
65 | 1.0,
66 | -1.0,
67 | -1.0,
68 | 1.0,
69 | // Right face
70 | 1.0,
71 | -1.0,
72 | -1.0,
73 | 1.0,
74 | 1.0,
75 | -1.0,
76 | 1.0,
77 | 1.0,
78 | 1.0,
79 | 1.0,
80 | -1.0,
81 | 1.0,
82 | // Left face
83 | -1.0,
84 | -1.0,
85 | -1.0,
86 | -1.0,
87 | -1.0,
88 | 1.0,
89 | -1.0,
90 | 1.0,
91 | 1.0,
92 | -1.0,
93 | 1.0,
94 | -1.0,
95 | ];
96 |
97 | for (let i = 0; i < positions.length; i += 3) {
98 | positions[i + 0] *= r;
99 | positions[i + 1] *= r;
100 | positions[i + 2] *= r;
101 | }
102 |
103 | const indices = [
104 | // Front face
105 | 0,
106 | 1,
107 | 2,
108 | 0,
109 | 2,
110 | 3,
111 | // Back face
112 | 4,
113 | 5,
114 | 6,
115 | 4,
116 | 6,
117 | 7,
118 | // Top face
119 | 8,
120 | 9,
121 | 10,
122 | 8,
123 | 10,
124 | 11,
125 | // Bottom face
126 | 12,
127 | 13,
128 | 14,
129 | 12,
130 | 14,
131 | 15,
132 | // Right face
133 | 16,
134 | 17,
135 | 18,
136 | 16,
137 | 18,
138 | 19,
139 | // Left face
140 | 20,
141 | 21,
142 | 22,
143 | 20,
144 | 22,
145 | 23,
146 | ];
147 |
148 | super(positions, indices, r, settings.detail);
149 |
150 | return this.geometry;
151 | }
152 | }
153 |
154 | export default Hexahedron;
155 |
--------------------------------------------------------------------------------
/packages/geometries/src/icosahedron/index.js:
--------------------------------------------------------------------------------
1 | import Polyhedra from '../polyhedra';
2 |
3 | class Icosahedron extends Polyhedra {
4 | constructor(props) {
5 | const settings = Object.assign(
6 | {},
7 | {
8 | radius: 0.5,
9 | detail: 0,
10 | },
11 | props
12 | );
13 |
14 | const t = 0.5 + Math.sqrt(5) / 2;
15 | const r = settings.radius * 2;
16 |
17 | const positions = [
18 | -1,
19 | +t,
20 | 0,
21 | +1,
22 | +t,
23 | 0,
24 | -1,
25 | -t,
26 | 0,
27 | +1,
28 | -t,
29 | 0,
30 | 0,
31 | -1,
32 | +t,
33 | 0,
34 | +1,
35 | +t,
36 | 0,
37 | -1,
38 | -t,
39 | 0,
40 | +1,
41 | -t,
42 | +t,
43 | 0,
44 | -1,
45 | +t,
46 | 0,
47 | +1,
48 | -t,
49 | 0,
50 | -1,
51 | -t,
52 | 0,
53 | +1,
54 | ];
55 |
56 | const indices = [
57 | 0,
58 | 11,
59 | 5,
60 | 0,
61 | 5,
62 | 1,
63 | 0,
64 | 1,
65 | 7,
66 | 0,
67 | 7,
68 | 10,
69 | 0,
70 | 10,
71 | 11,
72 | 1,
73 | 5,
74 | 9,
75 | 5,
76 | 11,
77 | 4,
78 | 11,
79 | 10,
80 | 2,
81 | 10,
82 | 7,
83 | 6,
84 | 7,
85 | 1,
86 | 8,
87 | 3,
88 | 9,
89 | 4,
90 | 3,
91 | 4,
92 | 2,
93 | 3,
94 | 2,
95 | 6,
96 | 3,
97 | 6,
98 | 8,
99 | 3,
100 | 8,
101 | 9,
102 | 4,
103 | 9,
104 | 5,
105 | 2,
106 | 4,
107 | 11,
108 | 6,
109 | 2,
110 | 10,
111 | 8,
112 | 6,
113 | 7,
114 | 9,
115 | 8,
116 | 1,
117 | ];
118 |
119 | super(positions, indices, r, settings.detail);
120 |
121 | return this.geometry;
122 | }
123 | }
124 |
125 | export default Icosahedron;
126 |
--------------------------------------------------------------------------------
/packages/geometries/src/index.js:
--------------------------------------------------------------------------------
1 | import * as utils from './utils';
2 |
3 | import Tetrahedron from './tetrahedron';
4 | import Hexahedron from './hexahedron';
5 | import Octahedron from './octahedron';
6 | import Dodecahedron from './dodecahedron';
7 | import Icosahedron from './icosahedron';
8 |
9 | import Plane from './plane';
10 | import Box from './box';
11 | import Sphere from './sphere';
12 | import Torus from './torus';
13 | import TorusKnot from './torusknot';
14 | import Prism from './prism';
15 |
16 | export {
17 | utils,
18 | /* PLATONIC SOLIDS */
19 | Tetrahedron,
20 | Hexahedron,
21 | Octahedron,
22 | Dodecahedron,
23 | Icosahedron,
24 | /* OTHER */
25 | Plane,
26 | Box,
27 | Sphere,
28 | Torus,
29 | TorusKnot,
30 | Prism,
31 | };
32 |
--------------------------------------------------------------------------------
/packages/geometries/src/octahedron/index.js:
--------------------------------------------------------------------------------
1 | import Polyhedra from '../polyhedra';
2 |
3 | class Octahedron extends Polyhedra {
4 | constructor(props) {
5 | const settings = Object.assign(
6 | {},
7 | {
8 | radius: 0.5,
9 | detail: 0,
10 | },
11 | props
12 | );
13 |
14 | const positions = [
15 | 1,
16 | 0,
17 | 0,
18 | -1,
19 | 0,
20 | 0,
21 | 0,
22 | 1,
23 | 0,
24 | 0,
25 | -1,
26 | 0,
27 | 0,
28 | 0,
29 | 1,
30 | 0,
31 | 0,
32 | -1,
33 | ];
34 |
35 | const indices = [
36 | 0,
37 | 2,
38 | 4,
39 | 0,
40 | 4,
41 | 3,
42 | 0,
43 | 3,
44 | 5,
45 | 0,
46 | 5,
47 | 2,
48 | 1,
49 | 2,
50 | 5,
51 | 1,
52 | 5,
53 | 3,
54 | 1,
55 | 3,
56 | 4,
57 | 1,
58 | 4,
59 | 2,
60 | ];
61 |
62 | super(positions, indices, settings.radius * 2, settings.detail);
63 |
64 | return this.geometry;
65 | }
66 | }
67 |
68 | export default Octahedron;
69 |
--------------------------------------------------------------------------------
/packages/geometries/src/prism/index.js:
--------------------------------------------------------------------------------
1 | class Prism {
2 | constructor(props) {
3 | const settings = Object.assign(
4 | {},
5 | {
6 | width: 1,
7 | height: 1,
8 | depth: 1,
9 | },
10 | props
11 | );
12 |
13 | const positions = [
14 | // Front face
15 | -0.5,
16 | -0.5,
17 | +0.5, // 0
18 | +0.5,
19 | -0.5,
20 | +0.5, // 1
21 | +0.5,
22 | +0.5,
23 | -0.5, // 2
24 | -0.5,
25 | +0.5,
26 | -0.5, // 3
27 |
28 | // back
29 | +0.5,
30 | -0.5,
31 | -0.5, // 4
32 | -0.5,
33 | -0.5,
34 | -0.5, // 5
35 | ];
36 |
37 | for (let i = 0; i < positions.length; i += 3) {
38 | positions[i + 0] *= settings.width;
39 | positions[i + 1] *= settings.height;
40 | positions[i + 2] *= settings.depth;
41 | }
42 |
43 | const indices = [
44 | // Front face
45 | 0,
46 | 1,
47 | 2,
48 | 0,
49 | 2,
50 | 3,
51 | // Back face
52 | 4,
53 | 3,
54 | 2,
55 | 4,
56 | 5,
57 | 3,
58 | // bottom
59 | 1,
60 | 0,
61 | 5,
62 | 1,
63 | 5,
64 | 4,
65 | // left
66 | 5,
67 | 0,
68 | 3,
69 | // right
70 | 1,
71 | 4,
72 | 2,
73 | ];
74 |
75 | return {
76 | positions,
77 | indices,
78 | };
79 | }
80 | }
81 |
82 | export default Prism;
83 |
--------------------------------------------------------------------------------
/packages/geometries/src/sphere/index.js:
--------------------------------------------------------------------------------
1 | import { mat4, vec3 } from 'gl-matrix';
2 |
3 | const matRotY = mat4.create();
4 | const matRotZ = mat4.create();
5 | const up = vec3.fromValues(0, 1, 0);
6 | const tmpVec3 = vec3.create();
7 |
8 | class Sphere {
9 | constructor(props) {
10 | const settings = Object.assign(
11 | {},
12 | {
13 | radius: 0.5,
14 | segments: 8,
15 | },
16 | props
17 | );
18 |
19 | const positions = [];
20 | const indices = [];
21 | const normals = [];
22 | const uvs = [];
23 |
24 | const heightSegments = 2 + settings.segments;
25 | const widthSegments = 2 * heightSegments;
26 |
27 | for (let zStep = 0; zStep <= heightSegments; zStep++) {
28 | const v = zStep / heightSegments;
29 | const angleZ = v * Math.PI;
30 |
31 | for (let yStep = 0; yStep <= widthSegments; yStep++) {
32 | const u = yStep / widthSegments;
33 | const angleY = u * Math.PI * 2;
34 |
35 | mat4.identity(matRotZ);
36 | mat4.rotateZ(matRotZ, matRotZ, -angleZ);
37 |
38 | mat4.identity(matRotY);
39 | mat4.rotateY(matRotY, matRotY, angleY);
40 |
41 | vec3.transformMat4(tmpVec3, up, matRotZ);
42 | vec3.transformMat4(tmpVec3, tmpVec3, matRotY);
43 |
44 | vec3.scale(tmpVec3, tmpVec3, -(settings.radius * 2));
45 | positions.push(...tmpVec3);
46 |
47 | vec3.normalize(tmpVec3, tmpVec3);
48 | normals.push(...tmpVec3);
49 |
50 | uvs.push(u, v);
51 | }
52 |
53 | if (zStep > 0) {
54 | const vertices = positions.length / 3;
55 | let firstIndex = vertices - 2 * (widthSegments + 1);
56 | for (
57 | ;
58 | firstIndex + widthSegments + 2 < vertices;
59 | firstIndex++
60 | ) {
61 | indices.push(
62 | firstIndex,
63 | firstIndex + 1,
64 | firstIndex + widthSegments + 1
65 | );
66 | indices.push(
67 | firstIndex + widthSegments + 1,
68 | firstIndex + 1,
69 | firstIndex + widthSegments + 2
70 | );
71 | }
72 | }
73 | }
74 |
75 | return {
76 | positions,
77 | indices,
78 | normals,
79 | uvs,
80 | };
81 | }
82 | }
83 |
84 | export default Sphere;
85 |
--------------------------------------------------------------------------------
/packages/geometries/src/tetrahedron/index.js:
--------------------------------------------------------------------------------
1 | import Polyhedra from '../polyhedra';
2 |
3 | class Tetrahedron extends Polyhedra {
4 | constructor(props) {
5 | const settings = Object.assign(
6 | {},
7 | {
8 | radius: 0.5,
9 | detail: 0,
10 | },
11 | props
12 | );
13 |
14 | const positions = [1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1];
15 |
16 | const indices = [2, 1, 0, 0, 3, 2, 1, 3, 0, 2, 3, 1];
17 |
18 | super(positions, indices, settings.radius * 2, settings.detail);
19 |
20 | return this.geometry;
21 | }
22 | }
23 |
24 | export default Tetrahedron;
25 |
--------------------------------------------------------------------------------
/packages/geometries/src/torus/index.js:
--------------------------------------------------------------------------------
1 | import { vec3 } from 'gl-matrix';
2 |
3 | class Torus {
4 | constructor(props) {
5 | const settings = Object.assign(
6 | {},
7 | {
8 | radius: 1,
9 | tube: 0.375,
10 | tubularSegments: 16,
11 | radialSegments: 8,
12 | arc: Math.PI * 2,
13 | },
14 | props
15 | );
16 |
17 | const positions = [];
18 | const indices = [];
19 | const normals = [];
20 | const uvs = [];
21 |
22 | const center = vec3.create();
23 | const vertex = vec3.create();
24 | const normal = vec3.create();
25 |
26 | for (let j = 0; j <= settings.radialSegments; j++) {
27 | for (let i = 0; i <= settings.tubularSegments; i++) {
28 | const u = (i / settings.tubularSegments) * settings.arc;
29 | const v = (j / settings.radialSegments) * Math.PI * 2;
30 |
31 | vertex[0] =
32 | (settings.radius + settings.tube * Math.cos(v)) *
33 | Math.cos(u);
34 | vertex[1] =
35 | (settings.radius + settings.tube * Math.cos(v)) *
36 | Math.sin(u);
37 | vertex[2] = settings.tube * Math.sin(v);
38 |
39 | positions.push(...vertex);
40 |
41 | center[0] = settings.radius * Math.cos(u);
42 | center[1] = settings.radius * Math.sin(u);
43 | vec3.subtract(normal, vertex, center);
44 | vec3.normalize(normal, normal);
45 |
46 | normals.push(...normal);
47 |
48 | uvs.push(i / settings.tubularSegments);
49 | uvs.push(j / settings.radialSegments);
50 | }
51 | }
52 |
53 | for (let j = 1; j <= settings.radialSegments; j++) {
54 | for (let i = 1; i <= settings.tubularSegments; i++) {
55 | const a = (settings.tubularSegments + 1) * j + (i - 1);
56 | const b = (settings.tubularSegments + 1) * (j - 1) + (i - 1);
57 | const c = (settings.tubularSegments + 1) * (j - 1) + i;
58 | const d = (settings.tubularSegments + 1) * j + i;
59 |
60 | indices.push(a, b, d);
61 | indices.push(b, c, d);
62 | }
63 | }
64 |
65 | return {
66 | positions,
67 | indices,
68 | normals,
69 | uvs,
70 | };
71 | }
72 | }
73 |
74 | export default Torus;
75 |
--------------------------------------------------------------------------------
/packages/geometries/src/torusknot/index.js:
--------------------------------------------------------------------------------
1 | import { vec3 } from 'gl-matrix';
2 |
3 | class TorusKnot {
4 | constructor(props) {
5 | const settings = Object.assign(
6 | {},
7 | {
8 | radius: 0.5,
9 | tube: 0.2,
10 | tubularSegments: 64,
11 | radialSegments: 6,
12 | p: 2,
13 | q: 3,
14 | },
15 | props
16 | );
17 |
18 | const positions = [];
19 | const indices = [];
20 | const normals = [];
21 | const uvs = [];
22 |
23 | const vertex = vec3.create();
24 | const normal = vec3.create();
25 |
26 | const P1 = vec3.create();
27 | const P2 = vec3.create();
28 |
29 | const B = vec3.create();
30 | const T = vec3.create();
31 | const N = vec3.create();
32 |
33 | for (let i = 0; i <= settings.tubularSegments; i++) {
34 | const u = (i / settings.tubularSegments) * settings.p * Math.PI * 2;
35 | this.calculatePositionOnCurve(
36 | u,
37 | settings.p,
38 | settings.q,
39 | settings.radius,
40 | P1
41 | );
42 | this.calculatePositionOnCurve(
43 | u + 0.01,
44 | settings.p,
45 | settings.q,
46 | settings.radius,
47 | P2
48 | );
49 |
50 | vec3.subtract(T, P2, P1);
51 | vec3.add(N, P2, P1);
52 | vec3.cross(B, T, N);
53 | vec3.cross(N, B, T);
54 |
55 | vec3.normalize(B, B);
56 | vec3.normalize(N, N);
57 |
58 | for (let j = 0; j <= settings.radialSegments; j++) {
59 | const v = (j / settings.radialSegments) * Math.PI * 2;
60 | const cx = -settings.tube * Math.cos(v);
61 | const cy = settings.tube * Math.sin(v);
62 |
63 | vertex[0] = P1[0] + (cx * N[0] + cy * B[0]);
64 | vertex[1] = P1[1] + (cx * N[1] + cy * B[1]);
65 | vertex[2] = P1[2] + (cx * N[2] + cy * B[2]);
66 | positions.push(...vertex);
67 |
68 | vec3.subtract(normal, vertex, P1);
69 | vec3.normalize(normal, normal);
70 | normals.push(...normal);
71 |
72 | uvs.push(
73 | i / settings.tubularSegments,
74 | j / settings.radialSegments
75 | );
76 | }
77 | }
78 |
79 | for (let j = 1; j <= settings.tubularSegments; j++) {
80 | for (let i = 1; i <= settings.radialSegments; i++) {
81 | const a = (settings.radialSegments + 1) * (j - 1) + (i - 1);
82 | const b = (settings.radialSegments + 1) * j + (i - 1);
83 | const c = (settings.radialSegments + 1) * j + i;
84 | const d = (settings.radialSegments + 1) * (j - 1) + i;
85 |
86 | indices.push(a, b, d);
87 | indices.push(b, c, d);
88 | }
89 | }
90 |
91 | return {
92 | positions,
93 | indices,
94 | normals,
95 | uvs,
96 | };
97 | }
98 |
99 | calculatePositionOnCurve(u, p, q, radius, position) {
100 | const cu = Math.cos(u);
101 | const su = Math.sin(u);
102 | const quOverP = (q / p) * u;
103 | const cs = Math.cos(quOverP);
104 |
105 | position[0] = radius * (2 + cs) * 0.5 * cu;
106 | position[1] = radius * (2 + cs) * su * 0.5;
107 | position[2] = radius * Math.sin(quOverP) * 0.5;
108 | }
109 | }
110 |
111 | export default TorusKnot;
112 |
--------------------------------------------------------------------------------
/packages/geometries/src/utils/merge.js:
--------------------------------------------------------------------------------
1 | export const merge = (...props) => {
2 | console.log('merge', props);
3 |
4 | const positions = [];
5 | const indices = [];
6 | const normals = [];
7 | const uvs = [];
8 |
9 | return {
10 | positions,
11 | indices,
12 | normals,
13 | uvs,
14 | };
15 | };
16 |
--------------------------------------------------------------------------------
/packages/physics/README.md:
--------------------------------------------------------------------------------
1 | # lowww-physics
2 | Adds geometries for the [lowww](https://github.com/andrevenancio/lowww) engine.
3 |
4 | ## Installation
5 | `npm install --save lowww-physics`
6 |
7 |
8 | ## Usage
9 | ```javascript
10 | import { Renderer, Scene, cameras, Mesh } from 'lowww-core';
11 | import { Icosahedron } from 'lowww-geometries';
12 |
13 | let renderer;
14 | let camera;
15 | let scene;
16 | let mesh;
17 |
18 | init();
19 | update();
20 |
21 | const init = () => {
22 | renderer = new Renderer();
23 | renderer.setSize(400, 300);
24 | document.body.appendChild(renderer.domElement);
25 |
26 | camera = new cameras.Perspective();
27 | camera.position.set(0, 0, 500);
28 |
29 | scene = new Scene();
30 |
31 | const geometry = new Icosahedron({ radius: 10, detail: 1 });
32 | mesh = new Mesh({ geometry });
33 | scene.add(mesh);
34 | };
35 |
36 | const update = () => {
37 | renderer.render(scene, camera);
38 | requestAnimationFrame(update.bind(this));
39 | };
40 | ```
41 |
42 | ## TODO
43 | implement Octree for sorting bodies.
44 | (https://github.com/yomotsu/meshwalk.js/blob/master/src/core/Octree.js)
45 | Will improve performance of loops:
46 | ```
47 | for (let i = 0; i < this.bodies.length - 1; i++) {
48 | for (let j = i+1; j < this.bodies.length; j++) {
49 | // check collisions
50 | }
51 | }
52 | ```
53 |
54 |
55 | ## License
56 | MIT
57 |
--------------------------------------------------------------------------------
/packages/physics/package.json:
--------------------------------------------------------------------------------
1 | {"name":"lowww-physics","description":"WebGL 2 Engine extension","author":"Andre Venancio (info@andrevenancio.com)","version":"1.1.5","main":"src/index.js","module":"build/physics.module.js","repository":"git@github.com:andrevenancio/lowww.git","scripts":{"test":"echo 'Error: no test specified' && exit 0"},"devDependencies":{},"dependencies":{"gl-matrix":"^2.5.1"}}
--------------------------------------------------------------------------------
/packages/physics/src/colliders/aabb-collider.js:
--------------------------------------------------------------------------------
1 | import { vec3 } from 'gl-matrix';
2 | import { AABB_COLLIDER } from '../constants';
3 |
4 | class AABBCollider {
5 | constructor(params = {}) {
6 | Object.assign(
7 | this,
8 | {
9 | type: AABB_COLLIDER,
10 | width: 1,
11 | height: 1,
12 | depth: 1,
13 | bounds: vec3.create(),
14 | },
15 | params
16 | );
17 | }
18 |
19 | updateBounds(position) {
20 | const width = this.width / 2;
21 | const height = this.height / 2;
22 | const depth = this.depth / 2;
23 |
24 | // world space
25 | this.left = position[0] - width;
26 | this.right = position[0] + width;
27 |
28 | this.top = position[1] + height;
29 | this.bottom = position[1] - height;
30 |
31 | this.front = position[2] + depth;
32 | this.back = position[2] - depth;
33 |
34 | // local space
35 | this.bounds[0] = this.width;
36 | this.bounds[1] = this.height;
37 | this.bounds[2] = this.depth;
38 | }
39 | }
40 |
41 | export default AABBCollider;
42 |
--------------------------------------------------------------------------------
/packages/physics/src/colliders/sphere-collider.js:
--------------------------------------------------------------------------------
1 | import { vec3 } from 'gl-matrix';
2 | import { SPHERE_COLLIDER } from '../constants';
3 |
4 | class SphereCollider {
5 | constructor(params = {}) {
6 | Object.assign(
7 | this,
8 | {
9 | type: SPHERE_COLLIDER,
10 | radius: 1,
11 | bounds: vec3.create(),
12 | },
13 | params
14 | );
15 | }
16 |
17 | updateBounds(position) {
18 | // world space
19 | this.left = position[0] - this.radius;
20 | this.right = position[0] + this.radius;
21 |
22 | this.top = position[1] + this.radius;
23 | this.bottom = position[1] - this.radius;
24 |
25 | this.front = position[2] + this.radius;
26 | this.back = position[2] - this.radius;
27 |
28 | // local space
29 | this.bounds[0] = this.radius;
30 | this.bounds[1] = this.radius;
31 | this.bounds[2] = this.radius;
32 | }
33 | }
34 |
35 | export default SphereCollider;
36 |
--------------------------------------------------------------------------------
/packages/physics/src/constants.js:
--------------------------------------------------------------------------------
1 | // id's
2 | export const SPHERE_COLLIDER = 'sphere-collider';
3 | export const AABB_COLLIDER = 'aabb-collider';
4 | export const PLANE_COLLIDER = 'plane-collider';
5 | export const RIGID_BODY = 'rigid-body';
6 | export const FORCE = 'force';
7 |
8 | // default values
9 | export const DEFAULT_TIMESTEP = 1 / 180;
10 |
--------------------------------------------------------------------------------
/packages/physics/src/core/force.js:
--------------------------------------------------------------------------------
1 | import { vec3 } from 'gl-matrix';
2 | import { FORCE } from '../constants';
3 |
4 | class Force {
5 | constructor(x = 0, y = 0, z = 0) {
6 | this.type = FORCE;
7 | this.data = vec3.fromValues(x, y, z);
8 | }
9 | }
10 |
11 | export default Force;
12 |
--------------------------------------------------------------------------------
/packages/physics/src/core/rigid-body.js:
--------------------------------------------------------------------------------
1 | import { vec3 } from 'gl-matrix';
2 | import { RIGID_BODY, SPHERE_COLLIDER, AABB_COLLIDER } from '../constants';
3 |
4 | class RigidBody {
5 | constructor(params) {
6 | if (!params.collider) {
7 | throw new Error('Please provide a collider');
8 | }
9 |
10 | if (!params.mesh) {
11 | throw new Error('Please provide a mesh');
12 | }
13 |
14 | Object.assign(
15 | this,
16 | {
17 | type: RIGID_BODY,
18 | awake: true,
19 | lineardrag: 0.999,
20 | dynamic: true,
21 | velocity: vec3.create(),
22 | acceleration: vec3.create(),
23 | position: vec3.create(),
24 | force: vec3.create(),
25 | },
26 | params
27 | );
28 |
29 | // copy mesh position
30 | vec3.copy(this.position, this.mesh.position.data);
31 | }
32 |
33 | getInversemass() {
34 | return 1 / this.getMass();
35 | }
36 |
37 | getMass() {
38 | switch (this.collider.type) {
39 | case SPHERE_COLLIDER:
40 | return this.collider.radius;
41 | case AABB_COLLIDER:
42 | return 1;
43 | default:
44 | console.warn('unknown collider');
45 | return 1;
46 | }
47 | }
48 |
49 | // copies world force into body
50 | addForce(force) {
51 | vec3.copy(this.force, force);
52 | }
53 |
54 | integrate(deltatime) {
55 | if (!this.awake || !this.dynamic) {
56 | return;
57 | }
58 |
59 | // calculate acceleration
60 | const mass = this.getMass();
61 | this.acceleration[0] = this.force[0] / mass;
62 | this.acceleration[1] = this.force[1] / mass;
63 | this.acceleration[2] = this.force[2] / mass;
64 |
65 | // adding acceleration to velocity
66 | vec3.scaleAndAdd(
67 | this.velocity,
68 | this.velocity,
69 | this.acceleration,
70 | deltatime
71 | );
72 |
73 | // adding velocity to position
74 | vec3.scaleAndAdd(
75 | this.position,
76 | this.position,
77 | this.velocity,
78 | deltatime
79 | );
80 |
81 | // add drag to velocity
82 | this.velocity[0] *= this.lineardrag;
83 | this.velocity[1] *= this.lineardrag;
84 | this.velocity[2] *= this.lineardrag;
85 | }
86 |
87 | updateBounds() {
88 | this.collider.updateBounds(this.position);
89 | }
90 |
91 | render() {
92 | vec3.copy(this.mesh.position.data, this.position);
93 | }
94 | }
95 |
96 | export default RigidBody;
97 |
--------------------------------------------------------------------------------
/packages/physics/src/index.js:
--------------------------------------------------------------------------------
1 | // world
2 | import World from './core/world';
3 |
4 | // bodies
5 | import RigidBody from './core/rigid-body';
6 |
7 | // colliders
8 | import SphereCollider from './colliders/sphere-collider';
9 | import AABBCollider from './colliders/aabb-collider';
10 |
11 | // forces
12 | import Force from './core/force';
13 |
14 | export { World, RigidBody, SphereCollider, AABBCollider, Force };
15 |
--------------------------------------------------------------------------------
/packages/physics/src/workers/todo.js:
--------------------------------------------------------------------------------
1 | /* global Worker, Blob */
2 | const worker = new Worker(
3 | URL.createObjectURL(
4 | new Blob([
5 | `
6 | onmessage = event => {
7 | postMessage('Hello ' + event.data);
8 | };
9 | `,
10 | ])
11 | )
12 | );
13 | worker.onmessage = e => {
14 | console.log(e.data);
15 | };
16 | worker.postMessage('World');
17 |
--------------------------------------------------------------------------------
/packages/postprocessing/README.md:
--------------------------------------------------------------------------------
1 | # lowww-postprocessing
2 | Allows postprocessing effects on [lowww](https://github.com/andrevenancio/lowww) engine.
3 |
4 | ## Installation
5 | `npm install --save lowww-postprocessing`
6 |
7 |
8 | ## Usage
9 | ```javascript
10 | import { Composer, Scene, cameras, Pass, shaders } from 'lowww-core';
11 | import { Icosahedron } from 'lowww-geometries';
12 | import { Noise, tiltShift } from 'lowww-postprocessing';
13 |
14 | let composer;
15 | let camera;
16 | let scene;
17 | let mesh;
18 |
19 | let noise;
20 | let tiltshiftHorizontal;
21 | let tiltshiftVertical;
22 |
23 | init();
24 | update();
25 |
26 | const init = () => {
27 | composer = new Composer();
28 | composer.setSize(400, 300);
29 | document.body.appendChild(composer.domElement);
30 |
31 | camera = new cameras.Perspective();
32 | camera.position.set(0, 0, 500);
33 |
34 | scene = new Scene();
35 |
36 | const geometry = new Icosahedron({ radius: 100, detail: 1 });
37 | mesh = new Mesh({ geometry });
38 | scene.add(mesh);
39 |
40 | noise = new Pass(Noise);
41 | tiltshiftHorizontal = new Pass(tiltShift.Horizontal);
42 | tiltshiftVertical = new Pass(tiltShift.Vertical);
43 |
44 | composer.pass(noise);
45 | composer.pass(tiltshiftHorizontal);
46 | composer.pass(tiltshiftVertical);
47 | composer.compile();
48 | };
49 |
50 | const update = () => {
51 | composer.render(scene, camera);
52 | requestAnimationFrame(update.bind(this));
53 | };
54 | ```
55 |
56 |
57 | ## License
58 | MIT
59 |
--------------------------------------------------------------------------------
/packages/postprocessing/package.json:
--------------------------------------------------------------------------------
1 | {"name":"lowww-postprocessing","description":"WebGL 2 Engine extension","author":"Andre Venancio (info@andrevenancio.com)","version":"1.1.5","main":"src/index.js","module":"build/postprocessing.module.js","repository":"git@github.com:andrevenancio/lowww.git","scripts":{"test":"echo 'Error: no test specified' && exit 0"},"devDependencies":{},"dependencies":{"gl-matrix":"^2.5.1"}}
--------------------------------------------------------------------------------
/packages/postprocessing/src/bleach/index.js:
--------------------------------------------------------------------------------
1 | const Bleach = {
2 | uniforms: {
3 | u_input: { type: 'sampler2D', value: null },
4 | u_opacity: { type: 'float', value: 1.0 },
5 | },
6 |
7 | vertex: `
8 | out vec2 v_uv;
9 | void main() {
10 | gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(a_position, 1.0);
11 | v_uv = a_uv;
12 | }`,
13 |
14 | fragment: `
15 | in vec2 v_uv;
16 |
17 | uniform sampler2D u_input;
18 | uniform float u_opacity;
19 |
20 | void main() {
21 |
22 | vec4 base = texture(u_input, v_uv);
23 |
24 | vec3 lumCoeff = vec3(0.25, 0.65, 0.1);
25 | float lum = dot(lumCoeff, base.rgb);
26 | vec3 blend = vec3(lum);
27 |
28 | float L = min(1.0, max(0.0, 10.0 * (lum - 0.45)));
29 |
30 | vec3 result1 = 2.0 * base.rgb * blend;
31 | vec3 result2 = 1.0 - 2.0 * (1.0 - blend) * (1.0 - base.rgb);
32 |
33 | vec3 newColor = mix(result1, result2, L);
34 |
35 | float A2 = u_opacity * base.a;
36 | vec3 mixRGB = A2 * newColor.rgb;
37 | mixRGB += ((1.0 - A2) * base.rgb);
38 |
39 | outColor = vec4(mixRGB, base.a);
40 | }`,
41 | };
42 |
43 | export default Bleach;
44 |
--------------------------------------------------------------------------------
/packages/postprocessing/src/blur/horizontal.js:
--------------------------------------------------------------------------------
1 | const Horizontal = {
2 | uniforms: {
3 | u_input: { type: 'sampler2D', value: null },
4 | u_amount: { type: 'float', value: 512 },
5 | },
6 |
7 | vertex: `
8 | out vec2 v_uv;
9 | void main() {
10 | gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(a_position, 1.0);
11 | v_uv = a_uv;
12 | }`,
13 |
14 | fragment: `
15 | in vec2 v_uv;
16 |
17 | uniform sampler2D u_input;
18 | uniform float u_amount;
19 |
20 | void main() {
21 | vec4 sum = vec4(0.0);
22 | float hh = (1.0 / u_amount);
23 |
24 | sum += texture(u_input, vec2(v_uv.x - 4.0 * hh, v_uv.y)) * 0.051;
25 | sum += texture(u_input, vec2(v_uv.x - 3.0 * hh, v_uv.y)) * 0.0918;
26 | sum += texture(u_input, vec2(v_uv.x - 2.0 * hh, v_uv.y)) * 0.12245;
27 | sum += texture(u_input, vec2(v_uv.x - 1.0 * hh, v_uv.y)) * 0.1531;
28 | sum += texture(u_input, vec2(v_uv.x, v_uv.y ) ) * 0.1633;
29 | sum += texture(u_input, vec2(v_uv.x + 1.0 * hh, v_uv.y)) * 0.1531;
30 | sum += texture(u_input, vec2(v_uv.x + 2.0 * hh, v_uv.y)) * 0.12245;
31 | sum += texture(u_input, vec2(v_uv.x + 3.0 * hh, v_uv.y)) * 0.0918;
32 | sum += texture(u_input, vec2(v_uv.x + 4.0 * hh, v_uv.y)) * 0.051;
33 |
34 | outColor = sum;
35 | }`,
36 | };
37 |
38 | export default Horizontal;
39 |
--------------------------------------------------------------------------------
/packages/postprocessing/src/blur/index.js:
--------------------------------------------------------------------------------
1 | import Horizontal from './horizontal';
2 | import Vertical from './vertical';
3 |
4 | export { Horizontal, Vertical };
5 |
--------------------------------------------------------------------------------
/packages/postprocessing/src/blur/vertical.js:
--------------------------------------------------------------------------------
1 | const Vertical = {
2 | uniforms: {
3 | u_input: { type: 'sampler2D', value: null },
4 | u_amount: { type: 'float', value: 512 },
5 | },
6 |
7 | vertex: `
8 | out vec2 v_uv;
9 | void main() {
10 | gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(a_position, 1.0);
11 | v_uv = a_uv;
12 | }`,
13 |
14 | fragment: `
15 | in vec2 v_uv;
16 |
17 | uniform sampler2D u_input;
18 | uniform float u_amount;
19 |
20 | void main() {
21 | vec4 sum = vec4(0.0);
22 | float vv = (1.0 / u_amount);
23 |
24 | sum += texture(u_input, vec2(v_uv.x, v_uv.y - 4.0 * vv)) * 0.051;
25 | sum += texture(u_input, vec2(v_uv.x, v_uv.y - 3.0 * vv)) * 0.0918;
26 | sum += texture(u_input, vec2(v_uv.x, v_uv.y - 2.0 * vv)) * 0.12245;
27 | sum += texture(u_input, vec2(v_uv.x, v_uv.y - 1.0 * vv)) * 0.1531;
28 | sum += texture(u_input, vec2(v_uv.x, v_uv.y ) ) * 0.1633;
29 | sum += texture(u_input, vec2(v_uv.x, v_uv.y + 1.0 * vv)) * 0.1531;
30 | sum += texture(u_input, vec2(v_uv.x, v_uv.y + 2.0 * vv)) * 0.12245;
31 | sum += texture(u_input, vec2(v_uv.x, v_uv.y + 3.0 * vv)) * 0.0918;
32 | sum += texture(u_input, vec2(v_uv.x, v_uv.y + 4.0 * vv)) * 0.051;
33 |
34 | outColor = sum;
35 | }`,
36 | };
37 |
38 | export default Vertical;
39 |
--------------------------------------------------------------------------------
/packages/postprocessing/src/brightness/index.js:
--------------------------------------------------------------------------------
1 | const Brightness = {
2 | uniforms: {
3 | u_input: { type: 'sampler2D', value: null },
4 | u_treshold: { type: 'float', value: 0.0 },
5 | },
6 |
7 | vertex: `
8 | out vec2 v_uv;
9 | void main() {
10 | gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(a_position, 1.0);
11 | v_uv = a_uv;
12 | }`,
13 |
14 | fragment: `
15 | in vec2 v_uv;
16 |
17 | uniform sampler2D u_input;
18 | uniform float u_treshold;
19 |
20 | void main() {
21 | // relative luminance
22 | vec3 lum = vec3(0.2126, 0.7152, 0.0722);
23 | vec4 c = texture(u_input, v_uv);
24 |
25 | float luminance = dot(lum, c.xyz);
26 | luminance = max(0.0, luminance - u_treshold);
27 | c.xyz *= sign(luminance);
28 | c.a = 1.0;
29 |
30 | outColor = c;
31 | }`,
32 | };
33 |
34 | export default Brightness;
35 |
--------------------------------------------------------------------------------
/packages/postprocessing/src/dot-screen/index.js:
--------------------------------------------------------------------------------
1 | const DotScreen = {
2 | uniforms: {
3 | u_input: { type: 'sampler2D', value: null },
4 | u_size: { type: 'float', value: 256 },
5 | u_center: { type: 'vec2', value: [0.5, 0.5] },
6 | u_angle: { type: 'float', value: 1.57 },
7 | u_scale: { type: 'float', value: 1.0 },
8 | },
9 |
10 | vertex: `
11 | out vec2 v_uv;
12 | void main() {
13 | gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(a_position, 1.0);
14 | v_uv = a_uv;
15 | }`,
16 |
17 | fragment: `
18 | in vec2 v_uv;
19 |
20 | uniform sampler2D u_input;
21 |
22 | uniform vec2 u_center;
23 | uniform float u_angle;
24 | uniform float u_scale;
25 | uniform float u_size;
26 |
27 | float pattern() {
28 | float s = sin(u_angle), c = cos(u_angle);
29 |
30 | vec2 tex = v_uv * vec2(u_size) - u_center;
31 | vec2 point = vec2(c * tex.x - s * tex.y, s * tex.x + c * tex.y) * u_scale;
32 |
33 | return (sin(point.x) * sin(point.y)) * 4.0;
34 | }
35 |
36 | void main() {
37 | vec4 color = texture(u_input, v_uv);
38 |
39 | float average = (color.r + color.g + color.b) / 3.0;
40 |
41 | outColor = vec4(vec3(average * 10.0 - 5.0 + pattern()), color.a);
42 | }`,
43 | };
44 |
45 | export default DotScreen;
46 |
--------------------------------------------------------------------------------
/packages/postprocessing/src/glitch/index.js:
--------------------------------------------------------------------------------
1 | // inspired by: https://www.shadertoy.com/view/4t23Rc
2 | const Glitch = {
3 | uniforms: {
4 | u_input: { type: 'sampler2D', value: null },
5 | u_amplitude: { type: 'float', value: 3.0 },
6 | u_speed: { type: 'float', value: 2.0 },
7 | },
8 |
9 | vertex: `
10 | out vec2 v_uv;
11 | void main() {
12 | gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(a_position, 1.0);
13 | v_uv = a_uv;
14 | }`,
15 |
16 | fragment: `
17 | in vec2 v_uv;
18 |
19 | uniform sampler2D u_input;
20 | uniform float u_speed;
21 | uniform float u_amplitude;
22 |
23 | vec4 rgbShift(vec2 p, vec4 shift) {
24 | shift *= 2.0 * shift.w - 1.0;
25 | vec2 rs = vec2(shift.x, -shift.y);
26 | vec2 gs = vec2(shift.y, -shift.z);
27 | vec2 bs = vec2(shift.z, -shift.x);
28 |
29 | float r = texture(u_input, p + rs).x;
30 | float g = texture(u_input, p + gs).y;
31 | float b = texture(u_input, p + bs).z;
32 |
33 | return vec4(r, g, b, 1.0);
34 | }
35 |
36 | float rand(vec2 uv) {
37 | return fract(sin(dot(uv.xy, vec2(12.9898, 78.233))) * 43758.5453);
38 | }
39 |
40 | vec4 noise(vec2 n) {
41 | float r = rand(n.xy + 0.1);
42 | float g = rand(n.xy + 0.2);
43 | float b = rand(n.xy + 0.3);
44 | return vec4(r - 0.5, g - 0.5, b - 0.5, 1.0);
45 | }
46 |
47 | vec4 vec4pow(vec4 v, float p) {
48 | return vec4(pow(v.x, p), pow(v.y, p), pow(v.z, p), v.w);
49 | }
50 |
51 | void main() {
52 | vec4 color = texture(u_input, v_uv);
53 |
54 | vec4 c = vec4(0.0, 0.0, 0.0, 1.0);
55 |
56 | float v = clamp(sin(iGlobalTime * u_speed), 0.0, 1.0);
57 | vec4 shift = vec4pow(noise(vec2(1.0 - v, 0.0)), 8.0) * vec4(u_amplitude, u_amplitude, u_amplitude, 1.0) * v;
58 |
59 | c += rgbShift(v_uv, shift);
60 |
61 | outColor = c;
62 | }`,
63 | };
64 |
65 | export default Glitch;
66 |
--------------------------------------------------------------------------------
/packages/postprocessing/src/hue-saturation/index.js:
--------------------------------------------------------------------------------
1 | const HueSaturation = {
2 | uniforms: {
3 | u_input: { type: 'sampler2D', value: null },
4 | u_hue: { type: 'float', value: 0.0 }, // -1 to 1
5 | u_saturation: { type: 'float', value: 0.0 }, // -1 to 1
6 | },
7 |
8 | vertex: `
9 | out vec2 v_uv;
10 | void main() {
11 | gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(a_position, 1.0);
12 | v_uv = a_uv;
13 | }`,
14 |
15 | fragment: `
16 | in vec2 v_uv;
17 |
18 | uniform sampler2D u_input;
19 | uniform float u_hue;
20 | uniform float u_saturation;
21 |
22 | void main() {
23 | vec4 color = texture(u_input, v_uv);
24 | float angle = u_hue * 3.14159265;
25 | float s = sin(angle), c = cos(angle);
26 | vec3 weights = (vec3(2.0 * c, -sqrt(3.0) * s - c, sqrt(3.0) * s - c) + 1.0) / 3.0;
27 | float len = length(color.rgb);
28 | color.rgb = vec3(
29 | dot(color.rgb, weights.xyz),
30 | dot(color.rgb, weights.zxy),
31 | dot(color.rgb, weights.yzx)
32 | );
33 |
34 | float average = (color.r + color.g + color.b) / 3.0;
35 | if (u_saturation > 0.0) {
36 | color.rgb += (average - color.rgb) * (1.0 - 1.0 / (1.001 - u_saturation));
37 | } else {
38 | color.rgb += (average - color.rgb) * (-u_saturation);
39 | }
40 |
41 | outColor = color;
42 | }`,
43 | };
44 |
45 | export default HueSaturation;
46 |
--------------------------------------------------------------------------------
/packages/postprocessing/src/index.js:
--------------------------------------------------------------------------------
1 | import * as blur from './blur';
2 | import Bleach from './bleach';
3 | import Brightness from './brightness';
4 | import DotScreen from './dot-screen';
5 | import * as tiltShift from './tilt-shift';
6 | import Noise from './noise';
7 | import HueSaturation from './hue-saturation';
8 | import Glitch from './glitch';
9 |
10 | export {
11 | blur,
12 | Bleach,
13 | Brightness,
14 | DotScreen,
15 | tiltShift,
16 | Noise,
17 | HueSaturation,
18 | Glitch,
19 | };
20 |
21 | // resources:
22 | // http://evanw.github.io/glfx.js/demo/
23 | // http://pixijs.io/pixi-filters/tools/demo/
24 | // https://github.com/mrdoob/three.js/tree/dev/examples/js/shaders
25 | // https://github.com/spite/Wagner/tree/master/fragment-shaders
26 | // https://shadertoy.com
27 |
--------------------------------------------------------------------------------
/packages/postprocessing/src/noise/index.js:
--------------------------------------------------------------------------------
1 | const Noise = {
2 | uniforms: {
3 | u_input: { type: 'sampler2D', value: null },
4 | u_seed: { type: 'float', value: 0.01 },
5 | u_amount: { type: 'float', value: 0.5 },
6 | },
7 |
8 | vertex: `
9 | out vec2 v_uv;
10 | void main() {
11 | gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(a_position, 1.0);
12 | v_uv = a_uv;
13 | }`,
14 |
15 | fragment: `
16 | in vec2 v_uv;
17 |
18 | uniform sampler2D u_input;
19 | uniform float u_seed;
20 | uniform float u_amount;
21 |
22 | float rand(vec2 uv) {
23 | return fract(sin(dot(uv.xy, vec2(12.9898, 78.233))) * 43758.5453);
24 | }
25 |
26 | void main() {
27 | vec4 color = texture(u_input, v_uv);
28 | float random = rand(gl_FragCoord.xy * u_seed);
29 | float diff = (random - 0.5) * u_amount;
30 |
31 | color.r += diff;
32 | color.g += diff;
33 | color.b += diff;
34 |
35 | outColor = color;
36 | }`,
37 | };
38 |
39 | export default Noise;
40 |
--------------------------------------------------------------------------------
/packages/postprocessing/src/tilt-shift/horizontal.js:
--------------------------------------------------------------------------------
1 | const Horizontal = {
2 | uniforms: {
3 | u_input: { type: 'sampler2D', value: null },
4 | u_amount: { type: 'float', value: 128 },
5 | u_xscreenpos: { type: 'float', value: 0.5 },
6 | },
7 |
8 | vertex: `
9 | out vec2 v_uv;
10 | void main() {
11 | gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(a_position, 1.0);
12 | v_uv = a_uv;
13 | }`,
14 |
15 | fragment: `
16 | in vec2 v_uv;
17 |
18 | uniform sampler2D u_input;
19 | uniform float u_amount;
20 | uniform float u_xscreenpos;
21 |
22 | void main() {
23 | vec4 sum = vec4(0.0);
24 | float hh = (1.0 / u_amount) * abs(u_xscreenpos - v_uv.x);
25 |
26 | sum += texture(u_input, vec2(v_uv.x - 4.0 * hh, v_uv.y)) * 0.051;
27 | sum += texture(u_input, vec2(v_uv.x - 3.0 * hh, v_uv.y)) * 0.0918;
28 | sum += texture(u_input, vec2(v_uv.x - 2.0 * hh, v_uv.y)) * 0.12245;
29 | sum += texture(u_input, vec2(v_uv.x - 1.0 * hh, v_uv.y)) * 0.1531;
30 | sum += texture(u_input, vec2(v_uv.x, v_uv.y ) ) * 0.1633;
31 | sum += texture(u_input, vec2(v_uv.x + 1.0 * hh, v_uv.y)) * 0.1531;
32 | sum += texture(u_input, vec2(v_uv.x + 2.0 * hh, v_uv.y)) * 0.12245;
33 | sum += texture(u_input, vec2(v_uv.x + 3.0 * hh, v_uv.y)) * 0.0918;
34 | sum += texture(u_input, vec2(v_uv.x + 4.0 * hh, v_uv.y)) * 0.051;
35 |
36 | outColor = sum;
37 | }`,
38 | };
39 |
40 | export default Horizontal;
41 |
--------------------------------------------------------------------------------
/packages/postprocessing/src/tilt-shift/index.js:
--------------------------------------------------------------------------------
1 | import Horizontal from './horizontal';
2 | import Vertical from './vertical';
3 |
4 | export { Horizontal, Vertical };
5 |
--------------------------------------------------------------------------------
/packages/postprocessing/src/tilt-shift/vertical.js:
--------------------------------------------------------------------------------
1 | const Vertical = {
2 | uniforms: {
3 | u_input: { type: 'sampler2D', value: null },
4 | u_amount: { type: 'float', value: 128 },
5 | u_yscreenpos: { type: 'float', value: 0.5 },
6 | },
7 |
8 | vertex: `
9 | out vec2 v_uv;
10 | void main() {
11 | gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(a_position, 1.0);
12 | v_uv = a_uv;
13 | }`,
14 |
15 | fragment: `
16 | in vec2 v_uv;
17 |
18 | uniform sampler2D u_input;
19 | uniform float u_amount;
20 | uniform float u_yscreenpos;
21 |
22 | void main() {
23 | vec4 sum = vec4(0.0);
24 | float vv = (1.0 / u_amount) * abs(u_yscreenpos - v_uv.y);
25 |
26 | sum += texture(u_input, vec2(v_uv.x, v_uv.y - 4.0 * vv)) * 0.051;
27 | sum += texture(u_input, vec2(v_uv.x, v_uv.y - 3.0 * vv)) * 0.0918;
28 | sum += texture(u_input, vec2(v_uv.x, v_uv.y - 2.0 * vv)) * 0.12245;
29 | sum += texture(u_input, vec2(v_uv.x, v_uv.y - 1.0 * vv)) * 0.1531;
30 | sum += texture(u_input, vec2(v_uv.x, v_uv.y ) ) * 0.1633;
31 | sum += texture(u_input, vec2(v_uv.x, v_uv.y + 1.0 * vv)) * 0.1531;
32 | sum += texture(u_input, vec2(v_uv.x, v_uv.y + 2.0 * vv)) * 0.12245;
33 | sum += texture(u_input, vec2(v_uv.x, v_uv.y + 3.0 * vv)) * 0.0918;
34 | sum += texture(u_input, vec2(v_uv.x, v_uv.y + 4.0 * vv)) * 0.051;
35 |
36 | outColor = sum;
37 | }`,
38 | };
39 |
40 | export default Vertical;
41 |
--------------------------------------------------------------------------------
/scripts/node/generate-packages.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 |
3 | let packageName = '';
4 | if (process.env.PACKAGE) {
5 | packageName = `-${process.env.PACKAGE}`;
6 | }
7 |
8 | fs.readFile('package.json', 'utf8', (error, text) => {
9 | const pkg = JSON.parse(text);
10 | const json = {
11 | name: `${pkg.name}${packageName}`,
12 | description: 'WebGL 2 Engine extension',
13 | author: pkg.author,
14 | version: pkg.version,
15 | main: 'src/index.js',
16 | module: `build/${process.env.PACKAGE}.module.js`,
17 | repository: 'git@github.com:andrevenancio/lowww.git',
18 | scripts: {
19 | test: 'echo \'Error: no test specified\' && exit 0',
20 | },
21 | devDependencies: {},
22 | dependencies: {
23 | 'gl-matrix': '^2.5.1',
24 | },
25 | };
26 | fs.writeFile(`packages/${process.env.PACKAGE}/package.json`, JSON.stringify(json), 'utf8', () => {});
27 | });
28 |
--------------------------------------------------------------------------------
/scripts/node/minify-options.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 |
3 | let packageName = '';
4 | if (process.env.PACKAGE) {
5 | packageName = `-${process.env.PACKAGE}`;
6 | }
7 |
8 | fs.readFile('package.json', 'utf8', (error, text) => {
9 | const pkg = JSON.parse(text);
10 | const json = {
11 | toplevel: true,
12 | compress: {
13 | passes: 2,
14 | },
15 | output: {
16 | beautify: false,
17 | preamble: `/*\n${pkg.name}${packageName} - version: ${pkg.version}\nCopyright © ${(new Date()).getFullYear()} ${pkg.author}\n*/`,
18 | },
19 | };
20 | fs.writeFile('scripts/minify-options.json', JSON.stringify(json), 'utf8', () => {});
21 | });
22 |
--------------------------------------------------------------------------------
/scripts/rollup/examples.development.js:
--------------------------------------------------------------------------------
1 | import babel from 'rollup-plugin-babel';
2 | import glob from 'glob';
3 | import path from 'path';
4 | import resolve from 'rollup-plugin-node-resolve';
5 |
6 | import copy from './rollup-plugins/copy';
7 | import html from './rollup-plugins/html';
8 |
9 | // 1)
10 | // look through all files on the src folder
11 | const SRC = path.join(process.cwd(), 'src');
12 | const DEV = path.join(process.cwd(), 'dev');
13 |
14 | const files = glob.sync(path.join(SRC, '**/*.js')).filter((entry) => {
15 | const temp = entry.replace(SRC, '').split('/');
16 |
17 | // entry point can only be src/EXAMPLE_NAME/index.js,
18 | if (temp[2] === 'index.js') {
19 | return { name: temp[1] };
20 | }
21 |
22 | return false;
23 | });
24 |
25 | const examples = files.map((entry) => {
26 | const temp = entry.replace(SRC, '').split('/');
27 | const name = temp[1];
28 |
29 | return {
30 | name,
31 | thumb: `img/thumbnails/${name}.jpg`,
32 | url: `${name}.html`,
33 | };
34 | });
35 |
36 |
37 | // 2)
38 | // create a rollup config for each example
39 | const configs = files.map((entry) => {
40 | const temp = entry.replace(SRC, '').split('/');
41 | const name = temp[1];
42 |
43 | const setup = {
44 | input: path.join(SRC, name, 'index.js'),
45 | output: {
46 | format: 'umd',
47 | name: 'example',
48 | file: path.join(DEV, 'js', `${name}.js`),
49 | },
50 | watch: {
51 | include: [
52 | path.join(SRC, 'template.js'),
53 | path.join(SRC, name, '**'),
54 | ],
55 | },
56 | plugins: [
57 | resolve(),
58 | babel(),
59 | copy([
60 | { from: path.join(SRC, 'static'), to: path.join(DEV) },
61 | ]),
62 | html({
63 | output: path.join(DEV, `${name}.html`),
64 | metadata: {
65 | title: name,
66 | },
67 | css: [
68 | 'css/style.css',
69 | ],
70 | js: [
71 | 'https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.1/dat.gui.min.js',
72 | 'https://cdnjs.cloudflare.com/ajax/libs/gsap/2.0.1/TweenLite.min.js',
73 | '../packages/controls/build/controls.js',
74 | '../packages/core/build/core.js',
75 | '../packages/geometries/build/geometries.js',
76 | '../packages/postprocessing/build/postprocessing.js',
77 | '../packages/physics/build/physics.js',
78 | `js/${name}.js`,
79 | ],
80 | }),
81 | html({
82 | output: path.join(DEV, 'index.html'),
83 | isIndex: true,
84 | metadata: {
85 | title: 'DEVELOPMENT',
86 | },
87 | css: [
88 | 'css/style.css',
89 | ],
90 | examples,
91 | }),
92 | ],
93 | };
94 |
95 | return Object.assign({}, setup);
96 | });
97 |
98 | // 3)
99 | // export an array of configs
100 | export default configs;
101 |
--------------------------------------------------------------------------------
/scripts/rollup/examples.production.js:
--------------------------------------------------------------------------------
1 | import babel from 'rollup-plugin-babel';
2 | import glob from 'glob';
3 | import path from 'path';
4 | import resolve from 'rollup-plugin-node-resolve';
5 |
6 | import copy from './rollup-plugins/copy';
7 | import html from './rollup-plugins/html';
8 |
9 | // 1)
10 | // look through all files on the src folder
11 | const SRC = path.join(process.cwd(), 'src');
12 | const DEV = path.join(process.cwd(), 'site');
13 |
14 | const files = glob.sync(path.join(SRC, '**/*.js')).filter((entry) => {
15 | const temp = entry.replace(SRC, '').split('/');
16 |
17 | // entry point can only be src/EXAMPLE_NAME/index.js,
18 | if (temp[2] === 'index.js') {
19 | return { name: temp[1] };
20 | }
21 |
22 | return false;
23 | });
24 |
25 | const examples = files.map((entry) => {
26 | const temp = entry.replace(SRC, '').split('/');
27 | const name = temp[1];
28 |
29 | return {
30 | name,
31 | thumb: `img/thumbnails/${name}.jpg`,
32 | url: `${name}.html`,
33 | };
34 | });
35 |
36 | // 2)
37 | // create a rollup config for each example
38 | const configs = files.map((entry) => {
39 | const temp = entry.replace(SRC, '').split('/');
40 | const name = temp[1];
41 |
42 | const setup = {
43 | input: path.join(SRC, name, 'index.js'),
44 | output: {
45 | format: 'umd',
46 | name: 'example',
47 | file: path.join(DEV, 'js', `${name}.js`),
48 | },
49 | plugins: [
50 | babel(),
51 | resolve(),
52 | copy([
53 | { from: path.join(SRC, 'static'), to: path.join(DEV) },
54 | ]),
55 | html({
56 | output: path.join(DEV, `${name}.html`),
57 | minify: true,
58 | metadata: {
59 | title: name,
60 | description: `lowww engine ${name} example.`,
61 | thumbnail: `https://andrevenancio.github.io/lowww/img/thumbnails/${name}.jpg`,
62 | url: `https://andrevenancio.github.io/lowww/${name}.html`,
63 | },
64 | css: [
65 | 'css/style.css',
66 | ],
67 | js: [
68 | 'https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.1/dat.gui.min.js',
69 | 'https://rawgit.com/andrevenancio/lowww/master/packages/controls/build/controls.min.js',
70 | 'https://rawgit.com/andrevenancio/lowww/master/packages/core/build/core.min.js',
71 | 'https://rawgit.com/andrevenancio/lowww/master/packages/geometries/build/geometries.min.js',
72 | 'https://rawgit.com/andrevenancio/lowww/master/packages/postprocessing/build/postprocessing.min.js',
73 | 'https://rawgit.com/andrevenancio/lowww/master/packages/physics/build/physics.min.js',
74 | `js/${name}.js`,
75 | ],
76 | }),
77 | html({
78 | output: path.join(DEV, 'index.html'),
79 | minify: true,
80 | isIndex: true,
81 | metadata: {
82 | title: 'lowww',
83 | description: 'lowww engine example.',
84 | thumbnail: 'https://andrevenancio.github.io/lowww/img/thumbnails/facebook.jpg',
85 | url: 'https://andrevenancio.github.io/lowww/',
86 | },
87 | css: [
88 | 'css/style.css',
89 | ],
90 | examples,
91 | }),
92 | ],
93 | };
94 |
95 | return Object.assign({}, setup);
96 | });
97 |
98 | // 3)
99 | // export an array of configs
100 | export default configs;
101 |
--------------------------------------------------------------------------------
/scripts/rollup/rollup-plugins/copy.js:
--------------------------------------------------------------------------------
1 | import fse from 'fse';
2 |
3 | export default function replace(files) {
4 | return {
5 | name: 'copy',
6 |
7 | onwrite() {
8 | files.forEach((file) => {
9 | if (file.isFile) {
10 | fse.copyFile(file.from, file.to);
11 | } else {
12 | fse.copydir(file.from, file.to);
13 | }
14 | });
15 | },
16 | };
17 | }
18 |
--------------------------------------------------------------------------------
/scripts/rollup/rollup.es5.js:
--------------------------------------------------------------------------------
1 | import babel from 'rollup-plugin-babel';
2 | import path from 'path';
3 | import replace from 'rollup-plugin-replace';
4 | import resolve from 'rollup-plugin-node-resolve';
5 |
6 | import pkg from '../../package.json';
7 |
8 | const packageName = process.env.PACKAGE;
9 | const packagePath = path.join(process.cwd(), 'packages', packageName);
10 | const packageVersion = JSON.stringify(pkg.version);
11 |
12 | export default {
13 | input: path.join(packagePath, 'src', 'index.js'),
14 | output: {
15 | format: 'umd',
16 | name: `lowww.${packageName}`,
17 | file: path.join(packagePath, 'build', `${packageName}.js`),
18 | },
19 | watch: {
20 | include: path.join(packagePath, 'src', '**'),
21 | },
22 | plugins: [
23 | replace({
24 | __LIBRARY__: JSON.stringify(packageName),
25 | __VERSION__: packageVersion,
26 | }),
27 | resolve(),
28 | babel(),
29 | ],
30 | };
31 |
--------------------------------------------------------------------------------
/scripts/rollup/rollup.es6.js:
--------------------------------------------------------------------------------
1 | import babel from 'rollup-plugin-babel';
2 | import path from 'path';
3 | import replace from 'rollup-plugin-replace';
4 | import resolve from 'rollup-plugin-node-resolve';
5 |
6 | import pkg from '../../package.json';
7 |
8 | const packageName = process.env.PACKAGE;
9 | const packagePath = path.join(process.cwd(), 'packages', packageName);
10 | const packageVersion = JSON.stringify(pkg.version);
11 |
12 | export default {
13 | input: path.join(packagePath, 'src', 'index.js'),
14 | output: {
15 | format: 'es',
16 | name: `lowww.${packageName}`,
17 | file: path.join(packagePath, 'build', `${packageName}.module.js`),
18 | },
19 | watch: {
20 | include: path.join(packagePath, 'src', '**'),
21 | },
22 | plugins: [
23 | replace({
24 | __LIBRARY__: JSON.stringify(packageName),
25 | __VERSION__: packageVersion,
26 | }),
27 | resolve(),
28 | babel(), // allows arrow functions
29 | ],
30 | };
31 |
--------------------------------------------------------------------------------
/site/basic.html:
--------------------------------------------------------------------------------
1 | basic back source
--------------------------------------------------------------------------------
/site/clipping-planes.html:
--------------------------------------------------------------------------------
1 | clipping-planes back source
--------------------------------------------------------------------------------
/site/css/style.css:
--------------------------------------------------------------------------------
1 | html, body {
2 | margin: 0;
3 | background-color: #000;
4 | color: #fff;
5 | font-family: sans-serif;
6 | font-size: 14px;
7 | -moz-osx-font-smoothing: grayscale;
8 | -webkit-font-smoothing: antialiased;
9 | }
10 |
11 | canvas {
12 | display: block;
13 | }
14 |
15 | a {
16 | display: block;
17 | color: #fff;
18 | text-decoration: none;
19 | line-height: 20px;
20 | }
21 |
22 | a:hover {
23 | color: #fff;
24 | }
25 |
26 | a.back,
27 | a.source {
28 | position: fixed;
29 | background-color: rgba(255, 255, 255, 0.05);
30 | padding: 3px 6px;
31 | border-radius: 4px;
32 | font-family: monospace;
33 | font-size: 12px;
34 | }
35 |
36 | a.back:hover,
37 | a.source:hover {
38 | background-color: rgba(255, 255, 255, 0.1);
39 | }
40 |
41 | a.back {
42 | top: 20px;
43 | left: 20px;
44 | }
45 |
46 | a.source {
47 | bottom: 20px;
48 | right: 20px;
49 | }
50 |
51 | a.thumb {
52 | position: relative;
53 | display: inline-block;
54 | border: 1px solid #333;
55 | margin: 10px;
56 | }
57 | a.thumb img {
58 | width: 200px;
59 | height: 150px;
60 | opacity: 1;
61 | transition: all 0.15s ease-in-out;
62 | }
63 | a.thumb p {
64 | position: absolute;
65 | top: 50%;
66 | left: 50%;
67 | opacity: 0;
68 | transform: translateX(-50%) translateY(-100%);
69 | text-align: center;
70 | transition: all 0.15s ease-in-out;
71 | }
72 |
73 | a.thumb:hover img {
74 | opacity: 0.25;
75 | }
76 |
77 | a.thumb:hover p {
78 | top: 50%;
79 | opacity: 1;
80 | }
81 |
--------------------------------------------------------------------------------
/site/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/site/favicon.ico
--------------------------------------------------------------------------------
/site/geometries.html:
--------------------------------------------------------------------------------
1 | geometries back source
--------------------------------------------------------------------------------
/site/img/facebook.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/site/img/facebook.png
--------------------------------------------------------------------------------
/site/img/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/site/img/matcap/black-gloss.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/site/img/matcap/black-gloss.jpg
--------------------------------------------------------------------------------
/site/img/matcap/skin.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/site/img/matcap/skin.jpg
--------------------------------------------------------------------------------
/site/img/matcap/world.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/site/img/matcap/world.jpg
--------------------------------------------------------------------------------
/site/img/thumbnails/basic.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/site/img/thumbnails/basic.jpg
--------------------------------------------------------------------------------
/site/img/thumbnails/clipping-planes.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/site/img/thumbnails/clipping-planes.jpg
--------------------------------------------------------------------------------
/site/img/thumbnails/geometries.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/site/img/thumbnails/geometries.jpg
--------------------------------------------------------------------------------
/site/img/thumbnails/instancing.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/site/img/thumbnails/instancing.jpg
--------------------------------------------------------------------------------
/site/img/thumbnails/materials.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/site/img/thumbnails/materials.jpg
--------------------------------------------------------------------------------
/site/img/thumbnails/modify.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/site/img/thumbnails/modify.jpg
--------------------------------------------------------------------------------
/site/img/thumbnails/postprocessing.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/site/img/thumbnails/postprocessing.jpg
--------------------------------------------------------------------------------
/site/img/thumbnails/render-to-texture.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/site/img/thumbnails/render-to-texture.jpg
--------------------------------------------------------------------------------
/site/img/twitter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/site/img/twitter.png
--------------------------------------------------------------------------------
/site/img/uv.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/site/img/uv.png
--------------------------------------------------------------------------------
/site/index.html:
--------------------------------------------------------------------------------
1 | lowww basic
clipping-planes
geometries
instancing
materials
modify
postprocessing
render-to-texture
--------------------------------------------------------------------------------
/site/instancing.html:
--------------------------------------------------------------------------------
1 | instancing back source
--------------------------------------------------------------------------------
/site/materials.html:
--------------------------------------------------------------------------------
1 | materials back source
--------------------------------------------------------------------------------
/site/modify.html:
--------------------------------------------------------------------------------
1 | modify back source
--------------------------------------------------------------------------------
/site/physics.html:
--------------------------------------------------------------------------------
1 | physics back source
--------------------------------------------------------------------------------
/site/postprocessing.html:
--------------------------------------------------------------------------------
1 | postprocessing back source
--------------------------------------------------------------------------------
/site/render-to-texture.html:
--------------------------------------------------------------------------------
1 | render-to-texture back source
--------------------------------------------------------------------------------
/src/_prism/index.js:
--------------------------------------------------------------------------------
1 | import Template from '../template';
2 | import { L } from './letters';
3 |
4 | const { Renderer, Scene, cameras } = lowww.core;
5 | const { Orbit } = lowww.controls;
6 |
7 | class Main extends Template {
8 | setup() {
9 | this.renderer = new Renderer();
10 | document.body.appendChild(this.renderer.domElement);
11 |
12 | this.scene = new Scene();
13 |
14 | this.camera = new cameras.Perspective();
15 | this.camera.position.set(25, 25, 50);
16 |
17 | this.controls = new Orbit(this.camera, this.renderer.domElement);
18 |
19 | this.show = false;
20 |
21 | window.addEventListener(
22 | 'click',
23 | () => {
24 | console.log('toggle');
25 | if (this.show) {
26 | this.mesh.hide();
27 | this.show = false;
28 | } else {
29 | this.mesh.show();
30 | this.show = true;
31 | }
32 | },
33 | false
34 | );
35 | }
36 |
37 | init() {
38 | this.mesh = new L();
39 | this.scene.add(this.mesh);
40 | }
41 |
42 | resize(width, height, ratio) {
43 | this.renderer.setSize(width, height);
44 | this.renderer.setRatio(ratio);
45 | }
46 |
47 | pause() {}
48 |
49 | resume() {}
50 |
51 | update() {
52 | // const y = Math.cos(Date.now() / 500) * 0.5;
53 | // this.mesh.container.updateVertices([y], (2 * 3) + 1); // index 0 * xyz + 1 (y)
54 | // this.mesh.updateVertices([y], (3 * 3) + 1); // index 0 * xyz + 1 (y)
55 | // this.mesh.show();
56 | this.controls.update();
57 | this.renderer.render(this.scene, this.camera);
58 | }
59 | }
60 |
61 | export { Main };
62 |
--------------------------------------------------------------------------------
/src/basic/index.js:
--------------------------------------------------------------------------------
1 | import Template from '../template';
2 |
3 | const { Renderer, Scene, cameras, chunks, Model } = lowww.core;
4 |
5 | const { UBO } = chunks;
6 |
7 | class Main extends Template {
8 | setup() {
9 | this.renderer = new Renderer();
10 | document.body.appendChild(this.renderer.domElement);
11 |
12 | this.scene = new Scene();
13 |
14 | this.camera = new cameras.Perspective();
15 | this.camera.position.set(0, 0, 10);
16 | }
17 |
18 | init() {
19 | const vertex = `#version 300 es
20 | in vec3 a_position;
21 |
22 | ${UBO.scene()}
23 | ${UBO.model()}
24 |
25 | void main() {
26 | gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(a_position, 1.0);
27 | }
28 | `;
29 |
30 | const fragment = `#version 300 es
31 | precision highp float;
32 | precision highp int;
33 |
34 | out vec4 outColor;
35 |
36 | void main() {
37 | outColor = vec4(1.0);
38 | }
39 | `;
40 |
41 | const model = new Model();
42 | model.setAttribute(
43 | 'a_position',
44 | 'vec3',
45 | new Float32Array([-1, -1, 0, 1, -1, 0, 0, 1, 0])
46 | );
47 | model.setShader(vertex, fragment);
48 | this.scene.add(model);
49 |
50 | this.model = model;
51 | }
52 |
53 | resize(width, height, ratio) {
54 | this.renderer.setSize(width, height);
55 | this.renderer.setRatio(ratio);
56 | }
57 |
58 | update() {
59 | this.renderer.render(this.scene, this.camera);
60 | }
61 | }
62 |
63 | export { Main };
64 |
--------------------------------------------------------------------------------
/src/clipping-planes/index.js:
--------------------------------------------------------------------------------
1 | import Template from '../template';
2 |
3 | const { Renderer, Scene, cameras, Mesh, constants } = lowww.core;
4 | const { Orbit } = lowww.controls;
5 | const { Box } = lowww.geometries;
6 |
7 | const { SIDE } = constants;
8 |
9 | class Main extends Template {
10 | setup() {
11 | this.renderer = new Renderer();
12 | document.body.appendChild(this.renderer.domElement);
13 |
14 | this.scene = new Scene();
15 |
16 | this.camera = new cameras.Perspective();
17 | this.camera.position.set(0, 0, 10);
18 |
19 | this.controls = new Orbit(this.camera, this.renderer.domElement);
20 | }
21 |
22 | init() {
23 | const geometry = new Box();
24 | this.model = new Mesh({ geometry });
25 | this.model.side = SIDE.BOTH;
26 | this.scene.add(this.model);
27 |
28 | // global clipping
29 | this.scene.clipping.enable = false;
30 | this.scene.clipping.planes[0] = [0, 1, 0, 0.5];
31 |
32 | // local clipping
33 | this.model.clipping.enable = true;
34 | this.model.clipping.planes[0] = [1.5, 2.5, 0, 0.5];
35 |
36 | // gui
37 | this.gui
38 | .add(this.scene.clipping, 'enable')
39 | .name('global clipping')
40 | .onChange(e => (this.scene.clipping.enable = e));
41 | this.gui
42 | .add(this.model.clipping, 'enable')
43 | .name('local clipping')
44 | .onChange(e => (this.model.clipping.enable = e));
45 | }
46 |
47 | resize(width, height, ratio) {
48 | this.renderer.setSize(width, height);
49 | this.renderer.setRatio(ratio);
50 | }
51 |
52 | update() {
53 | this.controls.update();
54 | this.renderer.render(this.scene, this.camera);
55 | }
56 | }
57 |
58 | export { Main };
59 |
--------------------------------------------------------------------------------
/src/geometries/index.js:
--------------------------------------------------------------------------------
1 | import Template from '../template';
2 |
3 | const { Renderer, Scene, cameras, Mesh } = lowww.core;
4 | const { Orbit } = lowww.controls;
5 | const {
6 | Tetrahedron,
7 | Octahedron,
8 | Hexahedron,
9 | Icosahedron,
10 | Dodecahedron,
11 | Box,
12 | Plane,
13 | Sphere,
14 | Torus,
15 | TorusKnot,
16 | } = lowww.geometries;
17 |
18 | class Main extends Template {
19 | setup() {
20 | this.renderer = new Renderer();
21 | document.body.appendChild(this.renderer.domElement);
22 |
23 | this.scene = new Scene();
24 |
25 | this.camera = new cameras.Perspective();
26 | this.camera.position.set(0, 10, 20);
27 |
28 | this.controls = new Orbit(this.camera, this.renderer.domElement);
29 | }
30 |
31 | init() {
32 | const geometries = [
33 | Tetrahedron,
34 | Octahedron,
35 | Hexahedron,
36 | Icosahedron,
37 | Dodecahedron,
38 | Box,
39 | Plane,
40 | Sphere,
41 | Torus,
42 | TorusKnot,
43 | ];
44 |
45 | const radius = 4;
46 | const step = -(2 * Math.PI) / geometries.length;
47 | let angle = 0;
48 |
49 | for (let i = 0; i < geometries.length; i++) {
50 | const geometry = new geometries[i]();
51 | const mesh = new Mesh({ geometry });
52 | mesh.position.set(
53 | radius * Math.cos(angle),
54 | 0,
55 | radius * Math.sin(angle)
56 | );
57 | this.scene.add(mesh);
58 | angle += step;
59 | }
60 | }
61 |
62 | resize(width, height, ratio) {
63 | this.renderer.setSize(width, height);
64 | this.renderer.setRatio(ratio);
65 | }
66 |
67 | update() {
68 | this.controls.update();
69 | this.renderer.render(this.scene, this.camera);
70 | }
71 | }
72 |
73 | export { Main };
74 |
--------------------------------------------------------------------------------
/src/materials/index.js:
--------------------------------------------------------------------------------
1 | import Template from '../template';
2 |
3 | const { Renderer, Scene, cameras, Mesh, shaders } = lowww.core;
4 | const { Orbit } = lowww.controls;
5 | const { TorusKnot } = lowww.geometries;
6 |
7 | const { Basic, Default, Sem } = shaders;
8 |
9 | class Main extends Template {
10 | setup() {
11 | this.renderer = new Renderer();
12 | document.body.appendChild(this.renderer.domElement);
13 |
14 | this.scene = new Scene();
15 |
16 | this.camera = new cameras.Perspective();
17 | this.camera.position.set(0, 10, 20);
18 |
19 | this.controls = new Orbit(this.camera, this.renderer.domElement);
20 | }
21 |
22 | init() {
23 | const materials = [
24 | new Basic({ wireframe: true }),
25 | new Basic(),
26 | new Default(),
27 | new Sem({ map: './img/matcap/black-gloss.jpg' }),
28 | ];
29 |
30 | const geometry = new TorusKnot();
31 | for (let i = 0; i < materials.length; i++) {
32 | const mesh = new Mesh({ geometry, shader: materials[i] });
33 | mesh.position.set(3 * i - (3 * (materials.length - 1)) / 2, 0, 0);
34 | this.scene.add(mesh);
35 | }
36 | }
37 |
38 | resize(width, height, ratio) {
39 | this.renderer.setSize(width, height);
40 | this.renderer.setRatio(ratio);
41 | }
42 |
43 | update() {
44 | this.controls.update();
45 | this.renderer.render(this.scene, this.camera);
46 | }
47 | }
48 |
49 | export { Main };
50 |
--------------------------------------------------------------------------------
/src/modify/index.js:
--------------------------------------------------------------------------------
1 | import Template from '../template';
2 |
3 | const { Renderer, Scene, cameras, Mesh, constants } = lowww.core;
4 | const { Icosahedron, utils } = lowww.geometries;
5 |
6 | const { SIDE } = constants;
7 |
8 | class Main extends Template {
9 | setup() {
10 | this.renderer = new Renderer();
11 | document.body.appendChild(this.renderer.domElement);
12 |
13 | this.scene = new Scene();
14 | this.scene.fog.enable = true;
15 |
16 | this.camera = new cameras.Perspective();
17 | this.camera.position.set(0, 0, 10);
18 | }
19 |
20 | init() {
21 | this.settings = {
22 | data: ['none', 'modify', 'detach'],
23 | modifier: 'modify',
24 | };
25 |
26 | this.gui
27 | .add(this.settings, 'modifier', this.settings.data)
28 | .onChange(this.rebuild.bind(this));
29 |
30 | this.random = [];
31 | for (let i = 0; i < 3000; i++) {
32 | this.random.push(Math.random() * 0.2);
33 | }
34 |
35 | this.original = new Icosahedron({ detail: 2 });
36 | this.rebuild();
37 | }
38 |
39 | rebuild() {
40 | if (this.mesh) {
41 | this.scene.remove(this.mesh);
42 | this.mesh = null;
43 | }
44 |
45 | let geometry = this.original;
46 | let vertices = 1;
47 |
48 | if (this.settings.modifier === 'modify') {
49 | geometry = utils.Modify.modify(this.original);
50 | vertices = 3 * 3 * 4; // vertices * XYZ * 4 faces (1 original + 3 generated)
51 | } else if (this.settings.modifier === 'detach') {
52 | geometry = utils.Modify.detach(this.original);
53 | vertices = 3 * 3 * 1; // vertices * XYZ * 1 faces
54 | }
55 |
56 | for (let face = 0; face < geometry.positions.length; face += vertices) {
57 | let r = 1;
58 | if (this.settings.modifier !== 'none') {
59 | r += this.random[face % this.random.length];
60 | }
61 |
62 | for (let vertice = 0; vertice < vertices; vertice++) {
63 | geometry.positions[face + vertice] *= r;
64 | }
65 | }
66 |
67 | this.mesh = new Mesh({ geometry });
68 | this.mesh.side = SIDE.BOTH;
69 |
70 | this.scene.add(this.mesh);
71 | }
72 |
73 | resize(width, height, ratio) {
74 | this.renderer.setSize(width, height);
75 | this.renderer.setRatio(ratio);
76 | }
77 |
78 | update() {
79 | // this.mesh.rotation.x += 0.01;
80 | this.mesh.rotation.y += 0.01;
81 | this.renderer.render(this.scene, this.camera);
82 | }
83 | }
84 |
85 | export { Main };
86 |
--------------------------------------------------------------------------------
/src/static/css/style.css:
--------------------------------------------------------------------------------
1 | html, body {
2 | margin: 0;
3 | background-color: #000;
4 | color: #fff;
5 | font-family: sans-serif;
6 | font-size: 14px;
7 | -moz-osx-font-smoothing: grayscale;
8 | -webkit-font-smoothing: antialiased;
9 | }
10 |
11 | canvas {
12 | display: block;
13 | }
14 |
15 | a {
16 | display: block;
17 | color: #fff;
18 | text-decoration: none;
19 | line-height: 20px;
20 | }
21 |
22 | a:hover {
23 | color: #fff;
24 | }
25 |
26 | a.back,
27 | a.source {
28 | position: fixed;
29 | background-color: rgba(255, 255, 255, 0.05);
30 | padding: 3px 6px;
31 | border-radius: 4px;
32 | font-family: monospace;
33 | font-size: 12px;
34 | }
35 |
36 | a.back:hover,
37 | a.source:hover {
38 | background-color: rgba(255, 255, 255, 0.1);
39 | }
40 |
41 | a.back {
42 | top: 20px;
43 | left: 20px;
44 | }
45 |
46 | a.source {
47 | bottom: 20px;
48 | right: 20px;
49 | }
50 |
51 | a.thumb {
52 | position: relative;
53 | display: inline-block;
54 | border: 1px solid #333;
55 | margin: 10px;
56 | }
57 | a.thumb img {
58 | width: 200px;
59 | height: 150px;
60 | opacity: 1;
61 | transition: all 0.15s ease-in-out;
62 | }
63 | a.thumb p {
64 | position: absolute;
65 | top: 50%;
66 | left: 50%;
67 | opacity: 0;
68 | transform: translateX(-50%) translateY(-100%);
69 | text-align: center;
70 | transition: all 0.15s ease-in-out;
71 | }
72 |
73 | a.thumb:hover img {
74 | opacity: 0.25;
75 | }
76 |
77 | a.thumb:hover p {
78 | top: 50%;
79 | opacity: 1;
80 | }
81 |
--------------------------------------------------------------------------------
/src/static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/src/static/favicon.ico
--------------------------------------------------------------------------------
/src/static/img/facebook.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/src/static/img/facebook.png
--------------------------------------------------------------------------------
/src/static/img/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/static/img/matcap/black-gloss.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/src/static/img/matcap/black-gloss.jpg
--------------------------------------------------------------------------------
/src/static/img/matcap/skin.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/src/static/img/matcap/skin.jpg
--------------------------------------------------------------------------------
/src/static/img/matcap/world.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/src/static/img/matcap/world.jpg
--------------------------------------------------------------------------------
/src/static/img/thumbnails/2d-pattern3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/src/static/img/thumbnails/2d-pattern3.jpg
--------------------------------------------------------------------------------
/src/static/img/thumbnails/2d-pattern3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/src/static/img/thumbnails/2d-pattern3.png
--------------------------------------------------------------------------------
/src/static/img/thumbnails/basic.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/src/static/img/thumbnails/basic.jpg
--------------------------------------------------------------------------------
/src/static/img/thumbnails/clipping-planes.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/src/static/img/thumbnails/clipping-planes.jpg
--------------------------------------------------------------------------------
/src/static/img/thumbnails/geometries.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/src/static/img/thumbnails/geometries.jpg
--------------------------------------------------------------------------------
/src/static/img/thumbnails/instancing.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/src/static/img/thumbnails/instancing.jpg
--------------------------------------------------------------------------------
/src/static/img/thumbnails/materials.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/src/static/img/thumbnails/materials.jpg
--------------------------------------------------------------------------------
/src/static/img/thumbnails/modify.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/src/static/img/thumbnails/modify.jpg
--------------------------------------------------------------------------------
/src/static/img/thumbnails/postprocessing.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/src/static/img/thumbnails/postprocessing.jpg
--------------------------------------------------------------------------------
/src/static/img/thumbnails/render-to-texture.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/src/static/img/thumbnails/render-to-texture.jpg
--------------------------------------------------------------------------------
/src/static/img/twitter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/src/static/img/twitter.png
--------------------------------------------------------------------------------
/src/static/img/uv.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrevenancio/lowww/a65bac7583b400ffdda8130a98fd24b45e2b06c7/src/static/img/uv.png
--------------------------------------------------------------------------------
/src/template.js:
--------------------------------------------------------------------------------
1 | /* global dat */
2 | class Template {
3 | constructor() {
4 | window.addEventListener('resize', this.handleResize.bind(this), false);
5 | window.addEventListener('focus', this.handleResume.bind(this), false);
6 | window.addEventListener('blur', this.handlePause.bind(this), false);
7 |
8 | this.gui = new dat.GUI();
9 | this.gui.close();
10 |
11 | this.setup();
12 | this.init();
13 | this.handleResize();
14 | this.handleResume();
15 | }
16 |
17 | handleResize() {
18 | this.resize(
19 | window.innerWidth,
20 | window.innerHeight,
21 | window.devicePixelRatio
22 | );
23 | this.update();
24 | }
25 |
26 | handleResume() {
27 | this.raf = requestAnimationFrame(this.handleUpdate.bind(this));
28 | this.resume();
29 | }
30 |
31 | handlePause() {
32 | cancelAnimationFrame(this.raf);
33 | this.pause();
34 | }
35 |
36 | handleUpdate() {
37 | this.update();
38 | this.raf = requestAnimationFrame(this.handleUpdate.bind(this));
39 | }
40 |
41 | // to be overriden
42 | setup() {
43 | console.warn('please add the setup() method');
44 | }
45 | init() {
46 | console.warn('please add the init() method');
47 | }
48 | resize() {
49 | console.warn('please add the resize() method');
50 | }
51 | pause() {}
52 | resume() {}
53 | update() {
54 | console.warn('please add the update() method');
55 | }
56 | }
57 |
58 | export default Template;
59 |
--------------------------------------------------------------------------------