├── .babelrc
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── blacktie
├── css
│ └── black-tie.min.css
└── fonts
│ ├── bold
│ ├── BlackTie-Bold-webfont.eot
│ ├── BlackTie-Bold-webfont.svg
│ ├── BlackTie-Bold-webfont.ttf
│ ├── BlackTie-Bold-webfont.woff
│ └── BlackTie-Bold-webfont.woff2
│ ├── brands
│ ├── FontAwesomeBrands-Regular-webfont.eot
│ ├── FontAwesomeBrands-Regular-webfont.svg
│ ├── FontAwesomeBrands-Regular-webfont.ttf
│ ├── FontAwesomeBrands-Regular-webfont.woff
│ └── FontAwesomeBrands-Regular-webfont.woff2
│ ├── light
│ ├── BlackTie-Light-webfont.eot
│ ├── BlackTie-Light-webfont.svg
│ ├── BlackTie-Light-webfont.ttf
│ ├── BlackTie-Light-webfont.woff
│ └── BlackTie-Light-webfont.woff2
│ ├── medium
│ ├── BlackTie-Medium-webfont.eot
│ ├── BlackTie-Medium-webfont.svg
│ ├── BlackTie-Medium-webfont.ttf
│ ├── BlackTie-Medium-webfont.woff
│ └── BlackTie-Medium-webfont.woff2
│ └── solid
│ ├── BlackTie-Solid-webfont.eot
│ ├── BlackTie-Solid-webfont.svg
│ ├── BlackTie-Solid-webfont.ttf
│ ├── BlackTie-Solid-webfont.woff
│ └── BlackTie-Solid-webfont.woff2
├── index.html
├── lib
├── ace
│ ├── ace.js
│ ├── mode-glsl.js
│ ├── snippets
│ │ └── glsl.js
│ └── theme-twilight.js
├── editor
│ └── gk-inspector.js
├── exporter
│ └── exporter-obj.js
├── fabricate.js
├── gk-acewrap.js
├── gk-component.js
├── gk-core.js
├── gk-fixedshader.js
├── gk-framework.js
├── gk-gameobject.js
├── gk-glwrap.js
├── gk-logger.js
├── gk-mouseorbit.js
├── gk-renderer.js
├── gk-resmgr.js
├── gk-respanel.js
├── gk-scenemgr.js
├── gk-timer.js
├── loader
│ ├── loader-fbx.js
│ └── loader-osgjs.js
└── util
│ └── gl-matrix-extension.js
├── main.js
├── package.json
├── renderer.js
├── res
├── mesh
│ ├── box100.osgjs
│ ├── box100.osgjs.bin
│ ├── head.fbx
│ ├── lucyh.fbx
│ ├── quad2.osgjs
│ ├── quad2.osgjs.bin
│ ├── venusl.c4d
│ └── venusl.fbx
├── shader
│ ├── base_fs.glsl
│ └── base_vs.glsl
└── texture
│ ├── ground.jpg
│ ├── leaf.png
│ ├── matcap.jpg
│ ├── plaster.jpg
│ └── white.jpg
├── screenshot.png
├── style.css
└── test
├── loader-osgjs.js
├── package-build.js
└── pkg-postprocess.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "es2015",
4 | "react"
5 | ],
6 |
7 | "plugins": [
8 | "transform-object-rest-spread"
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 | .DS_Store
4 | bundle.js
5 | .idea
6 | *.log
7 | *.c4d
8 | res/package
9 | res/source
10 | electron-shadermonki*
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "6.9.1"
4 | before_install:
5 | - npm install npm@latest -g
6 | install:
7 | - npm install
8 | - npm install browserify
9 | script:
10 | - npm run build-js
11 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 gameKnife
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 | electron-shadermonki
2 | ---
3 |
4 | [](https://travis-ci.org/gameknife/electron-shadermonki)
5 |
6 | 
7 |
8 | a research [rendermonkey](http://developer.amd.com/tools-and-sdks/archive/games-cgi/rendermonkey-toolsuite/) like app based on [electron](https://github.com/electron/electron)
9 |
10 | ### Startup
11 |
12 | * install [node.js](https://nodejs.org)
13 | * update [npm](https://www.npmjs.com) to latest
14 | ```
15 | npm install npm@latest -g
16 | ```
17 | * install [cnpm](https://npm.taobao.org/) if ur under gfw
18 | ```
19 | npm install -g cnpm --registry=https://registry.npm.taobao.org
20 | ```
21 | * install dependency
22 | ```
23 | cnpm install
24 | ```
25 | * start running
26 | ```
27 | npm start
28 | ```
29 |
30 | ### Usage
31 |
32 | * edit vs & fs shader file
33 | * press Ctrl + S || Command + S to save change, preview will change at realtime.
34 |
35 | ### Future Task
36 |
37 | 1. binary fbx mesh loader
38 | 1. ~~resource management~~
39 | 1. ~~unity3d like gameobject & component system~~
40 | 1. ~~osgjs mesh loader~~
41 | 1. ~~obj format exporter~~
42 | 1. ~~gl-matrix-integrate~~
43 | 1. ~~real-time shadow~~
44 | 1. lightmap support
45 | 1. deferred shading chain & ssao
46 | 1. progressive rendering
47 | 1. normalmap support
48 |
49 | ### Thanks to
50 |
51 | * [ACE](https://github.com/ajaxorg/ace)
52 | * [glcubic.js](https://github.com/doxas/glcubic.js)
53 | * [three.js](https://github.com/mrdoob/three.js)
54 |
--------------------------------------------------------------------------------
/blacktie/css/black-tie.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * The Black Tie Font is commercial software. Please do not distribute.
3 | */
4 | /* FONT PATH
5 | * -------------------------- */
6 | @font-face {
7 | font-family: 'Black Tie';
8 | src: url('../fonts/solid/BlackTie-Solid-webfont.eot?v=1.0.0');
9 | src: url('../fonts/solid/BlackTie-Solid-webfont.eot?#iefix&v=1.0.0') format('embedded-opentype'), url('../fonts/solid/BlackTie-Solid-webfont.woff2?v=1.0.0') format('woff2'), url('../fonts/solid/BlackTie-Solid-webfont.woff?v=1.0.0') format('woff'), url('../fonts/solid/BlackTie-Solid-webfont.ttf?v=1.0.0') format('truetype'), url('../fonts/solid/BlackTie-Solid-webfont.svg?v=1.0.0#black_tiesolid') format('svg');
10 | font-weight: 900;
11 | font-style: normal;
12 | }
13 | @font-face {
14 | font-family: 'Black Tie';
15 | src: url('../fonts/bold/BlackTie-Bold-webfont.eot?v=1.0.0');
16 | src: url('../fonts/bold/BlackTie-Bold-webfont.eot?#iefix&v=1.0.0') format('embedded-opentype'), url('../fonts/bold/BlackTie-Bold-webfont.woff2?v=1.0.0') format('woff2'), url('../fonts/bold/BlackTie-Bold-webfont.woff?v=1.0.0') format('woff'), url('../fonts/bold/BlackTie-Bold-webfont.ttf?v=1.0.0') format('truetype'), url('../fonts/bold/BlackTie-Bold-webfont.svg?v=1.0.0#black_tiebold') format('svg');
17 | font-weight: 700;
18 | font-style: normal;
19 | }
20 | @font-face {
21 | font-family: 'Black Tie';
22 | src: url('../fonts/medium/BlackTie-Medium-webfont.eot?v=1.0.0');
23 | src: url('../fonts/medium/BlackTie-Medium-webfont.eot?#iefix&v=1.0.0') format('embedded-opentype'), url('../fonts/medium/BlackTie-Medium-webfont.woff2?v=1.0.0') format('woff2'), url('../fonts/medium/BlackTie-Medium-webfont.woff?v=1.0.0') format('woff'), url('../fonts/medium/BlackTie-Medium-webfont.ttf?v=1.0.0') format('truetype'), url('../fonts/medium/BlackTie-Medium-webfont.svg?v=1.0.0#black_tiemedium') format('svg');
24 | font-weight: 400;
25 | font-style: normal;
26 | }
27 | @font-face {
28 | font-family: 'Black Tie';
29 | src: url('../fonts/light/BlackTie-Light-webfont.eot?v=1.0.0');
30 | src: url('../fonts/light/BlackTie-Light-webfont.eot?#iefix&v=1.0.0') format('embedded-opentype'), url('../fonts/light/BlackTie-Light-webfont.woff2?v=1.0.0') format('woff2'), url('../fonts/light/BlackTie-Light-webfont.woff?v=1.0.0') format('woff'), url('../fonts/light/BlackTie-Light-webfont.ttf?v=1.0.0') format('truetype'), url('../fonts/light/BlackTie-Light-webfont.svg?v=1.0.0#black_tielight') format('svg');
31 | font-weight: 200;
32 | font-style: normal;
33 | }
34 | @font-face {
35 | font-family: 'Font Awesome Brands';
36 | src: url('../fonts/brands/FontAwesomeBrands-Regular-webfont.eot?v=1.0.0');
37 | src: url('../fonts/brands/FontAwesomeBrands-Regular-webfont.eot?#iefix&v=1.0.0') format('embedded-opentype'), url('../fonts/brands/FontAwesomeBrands-Regular-webfont.woff2?v=1.0.0') format('woff2'), url('../fonts/brands/FontAwesomeBrands-Regular-webfont.woff?v=1.0.0') format('woff'), url('../fonts/brands/FontAwesomeBrands-Regular-webfont.ttf?v=1.0.0') format('truetype'), url('../fonts/brands/FontAwesomeBrands-Regular-webfont.svg?v=1.0.0#font_awesome_brandsregular') format('svg');
38 | font-weight: normal;
39 | font-style: normal;
40 | }
41 | .bts,
42 | .btb,
43 | .btm,
44 | .btl,
45 | .fab {
46 | display: inline-block;
47 | font: normal normal normal 14px/1 "Black Tie";
48 | font-size: inherit;
49 | vertical-align: -14.28571429%;
50 | text-rendering: auto;
51 | -webkit-font-smoothing: antialiased;
52 | -moz-osx-font-smoothing: grayscale;
53 | transform: translate(0, 0);
54 | }
55 | .bts {
56 | font-weight: 900;
57 | }
58 | .btb {
59 | font-weight: 700;
60 | }
61 | .btl {
62 | font-weight: 200;
63 | }
64 | .fab {
65 | font-family: "Font Awesome Brands";
66 | }
67 | /* makes the font 25% smaller relative to the icon container */
68 | .bt-sm {
69 | font-size: .7em;
70 | vertical-align: baseline;
71 | }
72 | /* makes the font 33% larger relative to the icon container */
73 | .bt-lg {
74 | font-size: 1.33333333em;
75 | line-height: 0.75em;
76 | }
77 | .bt-2x {
78 | font-size: 2em;
79 | }
80 | .bt-3x {
81 | font-size: 3em;
82 | }
83 | .bt-4x {
84 | font-size: 4em;
85 | }
86 | .bt-5x {
87 | font-size: 5em;
88 | }
89 | .bt-lg,
90 | .bt-2x,
91 | .bt-3x,
92 | .bt-4x,
93 | .bt-5x {
94 | vertical-align: -30%;
95 | }
96 | .bt-fw {
97 | width: 1.28571429em;
98 | text-align: center;
99 | }
100 | .bt-ul {
101 | padding-left: 0;
102 | margin-left: 2.14285714em;
103 | list-style-type: none;
104 | }
105 | .bt-ul > li {
106 | position: relative;
107 | }
108 | .bt-li {
109 | position: absolute;
110 | left: -2.14285714em;
111 | width: 2.14285714em;
112 | top: 0.14285714em;
113 | text-align: center;
114 | }
115 | .bt-li.bt-lg {
116 | left: -2em;
117 | }
118 | .bt-border {
119 | padding: .2em;
120 | border: solid 0.08em #eeeeee;
121 | border-radius: .1em;
122 | }
123 | .pull-right {
124 | float: right;
125 | }
126 | .pull-left {
127 | float: left;
128 | }
129 | .bts.pull-left,
130 | .btb.pull-left,
131 | .btm.pull-left,
132 | .btl.pull-left,
133 | .fab.pull-left {
134 | margin-right: .3em;
135 | }
136 | .bts.pull-right,
137 | .btb.pull-right,
138 | .btm.pull-right,
139 | .btl.pull-right,
140 | .fab.pull-right {
141 | margin-left: .3em;
142 | }
143 | .bt-spin {
144 | -webkit-animation: bt-spin 2s infinite linear;
145 | animation: bt-spin 2s infinite linear;
146 | }
147 | .bt-pulse {
148 | -webkit-animation: bt-spin 1s infinite steps(8);
149 | animation: bt-spin 1s infinite steps(8);
150 | }
151 | @-webkit-keyframes bt-spin {
152 | 0% {
153 | -webkit-transform: rotate(0deg);
154 | transform: rotate(0deg);
155 | }
156 | 100% {
157 | -webkit-transform: rotate(359deg);
158 | transform: rotate(359deg);
159 | }
160 | }
161 | @keyframes bt-spin {
162 | 0% {
163 | -webkit-transform: rotate(0deg);
164 | transform: rotate(0deg);
165 | }
166 | 100% {
167 | -webkit-transform: rotate(359deg);
168 | transform: rotate(359deg);
169 | }
170 | }
171 | .bt-rotate-90 {
172 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1);
173 | -webkit-transform: rotate(90deg);
174 | -ms-transform: rotate(90deg);
175 | transform: rotate(90deg);
176 | }
177 | .bt-rotate-180 {
178 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2);
179 | -webkit-transform: rotate(180deg);
180 | -ms-transform: rotate(180deg);
181 | transform: rotate(180deg);
182 | }
183 | .bt-rotate-270 {
184 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3);
185 | -webkit-transform: rotate(270deg);
186 | -ms-transform: rotate(270deg);
187 | transform: rotate(270deg);
188 | }
189 | .bt-flip-horizontal {
190 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);
191 | -webkit-transform: scale(-1, 1);
192 | -ms-transform: scale(-1, 1);
193 | transform: scale(-1, 1);
194 | }
195 | .bt-flip-vertical {
196 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);
197 | -webkit-transform: scale(1, -1);
198 | -ms-transform: scale(1, -1);
199 | transform: scale(1, -1);
200 | }
201 | :root .bt-rotate-90,
202 | :root .bt-rotate-180,
203 | :root .bt-rotate-270,
204 | :root .bt-flip-horizontal,
205 | :root .bt-flip-vertical {
206 | filter: none;
207 | }
208 | .bt-stack {
209 | position: relative;
210 | display: inline-block;
211 | width: 1.28571429em;
212 | height: 1em;
213 | line-height: 1em;
214 | vertical-align: baseline;
215 | }
216 | .bt-stack-sm {
217 | position: absolute;
218 | top: 0;
219 | left: 0;
220 | line-height: inherit;
221 | font-size: .5em;
222 | }
223 | .bt-stack-1x,
224 | .bt-stack-sm {
225 | display: inline-block;
226 | width: 100%;
227 | text-align: center;
228 | }
229 | .bt-inverse {
230 | color: #ffffff;
231 | }
232 | /* Black Tie uses the Unicode Private Use Area (PUA) to ensure screen
233 | readers do not read off random characters that represent icons */
234 | .bt-bars:before {
235 | content: "\f000";
236 | }
237 | .bt-envelope:before {
238 | content: "\f001";
239 | }
240 | .bt-search:before {
241 | content: "\f002";
242 | }
243 | .bt-search-plus:before {
244 | content: "\f003";
245 | }
246 | .bt-search-minus:before {
247 | content: "\f004";
248 | }
249 | .bt-phone:before {
250 | content: "\f005";
251 | }
252 | .bt-comment:before {
253 | content: "\f007";
254 | }
255 | .bt-commenting:before {
256 | content: "\f008";
257 | }
258 | .bt-comments:before {
259 | content: "\f009";
260 | }
261 | .bt-rss:before {
262 | content: "\f00a";
263 | }
264 | .bt-times:before {
265 | content: "\f00c";
266 | }
267 | .bt-times-circle:before {
268 | content: "\f00d";
269 | }
270 | .bt-clock:before {
271 | content: "\f00e";
272 | }
273 | .bt-star:before {
274 | content: "\f010";
275 | }
276 | .bt-star-half:before {
277 | content: "\f011";
278 | }
279 | .bt-check:before {
280 | content: "\f012";
281 | }
282 | .bt-check-circle:before {
283 | content: "\f013";
284 | }
285 | .bt-check-square:before {
286 | content: "\f014";
287 | }
288 | .bt-th:before {
289 | content: "\f015";
290 | }
291 | .bt-th-large:before {
292 | content: "\f016";
293 | }
294 | .bt-heart:before {
295 | content: "\f017";
296 | }
297 | .bt-heart-half:before {
298 | content: "\f018";
299 | }
300 | .bt-calendar:before {
301 | content: "\f019";
302 | }
303 | .bt-shopping-cart:before {
304 | content: "\f01a";
305 | }
306 | .bt-plus:before {
307 | content: "\f01b";
308 | }
309 | .bt-plus-circle:before {
310 | content: "\f01c";
311 | }
312 | .bt-plus-square:before {
313 | content: "\f01d";
314 | }
315 | .bt-pen:before {
316 | content: "\f01e";
317 | }
318 | .bt-minus:before {
319 | content: "\f021";
320 | }
321 | .bt-minus-circle:before {
322 | content: "\f022";
323 | }
324 | .bt-minus-square:before {
325 | content: "\f023";
326 | }
327 | .bt-pencil:before {
328 | content: "\f024";
329 | }
330 | .bt-edit:before {
331 | content: "\f025";
332 | }
333 | .bt-thumbs-up:before {
334 | content: "\f026";
335 | }
336 | .bt-thumbs-down:before {
337 | content: "\f027";
338 | }
339 | .bt-gear:before {
340 | content: "\f028";
341 | }
342 | .bt-trash:before {
343 | content: "\f029";
344 | }
345 | .bt-file:before {
346 | content: "\f02a";
347 | }
348 | .bt-info-circle:before {
349 | content: "\f02b";
350 | }
351 | .bt-label:before {
352 | content: "\f02c";
353 | }
354 | .bt-rocket:before {
355 | content: "\f02d";
356 | }
357 | .bt-book:before {
358 | content: "\f02e";
359 | }
360 | .bt-book-open:before {
361 | content: "\f02f";
362 | }
363 | .bt-notebook:before {
364 | content: "\f030";
365 | }
366 | .bt-camera:before {
367 | content: "\f031";
368 | }
369 | .bt-folder:before {
370 | content: "\f032";
371 | }
372 | .bt-quote-left:before {
373 | content: "\f036";
374 | }
375 | .bt-quote-right:before {
376 | content: "\f037";
377 | }
378 | .bt-eye:before {
379 | content: "\f038";
380 | }
381 | .bt-lock:before {
382 | content: "\f039";
383 | }
384 | .bt-lock-open:before {
385 | content: "\f03a";
386 | }
387 | .bt-gift:before {
388 | content: "\f03b";
389 | }
390 | .bt-spinner-clock:before {
391 | content: "\f03c";
392 | }
393 | .bt-spinner:before {
394 | content: "\f03d";
395 | }
396 | .bt-wrench:before {
397 | content: "\f03e";
398 | }
399 | .bt-cloud:before {
400 | content: "\f040";
401 | }
402 | .bt-cloud-upload:before {
403 | content: "\f041";
404 | }
405 | .bt-cloud-download:before {
406 | content: "\f042";
407 | }
408 | .bt-sync:before {
409 | content: "\f043";
410 | }
411 | .bt-question-circle:before {
412 | content: "\f044";
413 | }
414 | .bt-share:before {
415 | content: "\f045";
416 | }
417 | .bt-briefcase:before {
418 | content: "\f046";
419 | }
420 | .bt-money:before {
421 | content: "\f047";
422 | }
423 | .bt-megaphone:before {
424 | content: "\f048";
425 | }
426 | .bt-sign-in:before {
427 | content: "\f049";
428 | }
429 | .bt-sign-out:before {
430 | content: "\f04a";
431 | }
432 | .bt-film:before {
433 | content: "\f04b";
434 | }
435 | .bt-trophy:before {
436 | content: "\f04c";
437 | }
438 | .bt-code:before {
439 | content: "\f04d";
440 | }
441 | .bt-light-bulb:before {
442 | content: "\f04e";
443 | }
444 | .bt-print:before {
445 | content: "\f050";
446 | }
447 | .bt-fax:before {
448 | content: "\f051";
449 | }
450 | .bt-video:before {
451 | content: "\f052";
452 | }
453 | .bt-signal:before {
454 | content: "\f053";
455 | }
456 | .bt-sitemap:before {
457 | content: "\f054";
458 | }
459 | .bt-upload:before {
460 | content: "\f055";
461 | }
462 | .bt-download:before {
463 | content: "\f056";
464 | }
465 | .bt-key:before {
466 | content: "\f057";
467 | }
468 | .bt-mug:before {
469 | content: "\f058";
470 | }
471 | .bt-bookmark:before {
472 | content: "\f059";
473 | }
474 | .bt-flag:before {
475 | content: "\f05a";
476 | }
477 | .bt-external-link:before {
478 | content: "\f05b";
479 | }
480 | .bt-smile:before {
481 | content: "\f05c";
482 | }
483 | .bt-frown:before {
484 | content: "\f05d";
485 | }
486 | .bt-meh:before {
487 | content: "\f05e";
488 | }
489 | .bt-magic:before {
490 | content: "\f060";
491 | }
492 | .bt-bolt:before {
493 | content: "\f061";
494 | }
495 | .bt-exclamation-triangle:before {
496 | content: "\f062";
497 | }
498 | .bt-exclamation-circle:before {
499 | content: "\f063";
500 | }
501 | .bt-flask:before {
502 | content: "\f064";
503 | }
504 | .bt-music:before {
505 | content: "\f065";
506 | }
507 | .bt-push-pin:before {
508 | content: "\f066";
509 | }
510 | .bt-shield:before {
511 | content: "\f067";
512 | }
513 | .bt-sort:before {
514 | content: "\f068";
515 | }
516 | .bt-reply:before {
517 | content: "\f069";
518 | }
519 | .bt-forward:before {
520 | content: "\f06a";
521 | }
522 | .bt-reply-all:before {
523 | content: "\f06b";
524 | }
525 | .bt-forward-all:before {
526 | content: "\f06c";
527 | }
528 | .bt-bell:before {
529 | content: "\f06d";
530 | }
531 | .bt-bell-off:before {
532 | content: "\f06e";
533 | }
534 | .bt-ban:before {
535 | content: "\f070";
536 | }
537 | .bt-database:before {
538 | content: "\f071";
539 | }
540 | .bt-hard-drive:before {
541 | content: "\f072";
542 | }
543 | .bt-merge:before {
544 | content: "\f073";
545 | }
546 | .bt-fork:before {
547 | content: "\f074";
548 | }
549 | .bt-wifi:before {
550 | content: "\f075";
551 | }
552 | .bt-paper-plane:before {
553 | content: "\f076";
554 | }
555 | .bt-inbox:before {
556 | content: "\f077";
557 | }
558 | .bt-fire:before {
559 | content: "\f078";
560 | }
561 | .bt-play:before {
562 | content: "\f079";
563 | }
564 | .bt-pause:before {
565 | content: "\f07a";
566 | }
567 | .bt-stop:before {
568 | content: "\f08b";
569 | }
570 | .bt-play-circle:before {
571 | content: "\f07b";
572 | }
573 | .bt-next:before {
574 | content: "\f07c";
575 | }
576 | .bt-previous:before {
577 | content: "\f07d";
578 | }
579 | .bt-repeat:before {
580 | content: "\f07e";
581 | }
582 | .bt-fast-forward:before {
583 | content: "\f080";
584 | }
585 | .bt-fast-reverse:before {
586 | content: "\f081";
587 | }
588 | .bt-volume:before {
589 | content: "\f082";
590 | }
591 | .bt-volume-off:before {
592 | content: "\f083";
593 | }
594 | .bt-volume-up:before {
595 | content: "\f084";
596 | }
597 | .bt-volume-down:before {
598 | content: "\f085";
599 | }
600 | .bt-maximize:before {
601 | content: "\f086";
602 | }
603 | .bt-minimize:before {
604 | content: "\f087";
605 | }
606 | .bt-closed-captions:before {
607 | content: "\f088";
608 | }
609 | .bt-shuffle:before {
610 | content: "\f089";
611 | }
612 | .bt-triangle:before {
613 | content: "\f08a";
614 | }
615 | .bt-square:before {
616 | content: "\f08b";
617 | }
618 | .bt-circle:before {
619 | content: "\f08c";
620 | }
621 | .bt-hexagon:before {
622 | content: "\f08d";
623 | }
624 | .bt-octagon:before {
625 | content: "\f08e";
626 | }
627 | .bt-angle-up:before {
628 | content: "\f090";
629 | }
630 | .bt-angle-down:before {
631 | content: "\f091";
632 | }
633 | .bt-angle-left:before {
634 | content: "\f092";
635 | }
636 | .bt-angle-right:before {
637 | content: "\f093";
638 | }
639 | .bt-angles-up:before {
640 | content: "\f094";
641 | }
642 | .bt-angles-down:before {
643 | content: "\f095";
644 | }
645 | .bt-angles-left:before {
646 | content: "\f096";
647 | }
648 | .bt-angles-right:before {
649 | content: "\f097";
650 | }
651 | .bt-arrow-up:before {
652 | content: "\f098";
653 | }
654 | .bt-arrow-down:before {
655 | content: "\f099";
656 | }
657 | .bt-arrow-left:before {
658 | content: "\f09a";
659 | }
660 | .bt-arrow-right:before {
661 | content: "\f09b";
662 | }
663 | .bt-bar-chart:before {
664 | content: "\f09c";
665 | }
666 | .bt-pie-chart:before {
667 | content: "\f09d";
668 | }
669 | .bt-circle-arrow-up:before {
670 | content: "\f0a0";
671 | }
672 | .bt-circle-arrow-down:before {
673 | content: "\f0a1";
674 | }
675 | .bt-circle-arrow-left:before {
676 | content: "\f0a2";
677 | }
678 | .bt-circle-arrow-right:before {
679 | content: "\f0a3";
680 | }
681 | .bt-caret-up:before {
682 | content: "\f0a4";
683 | }
684 | .bt-caret-down:before {
685 | content: "\f0a5";
686 | }
687 | .bt-caret-left:before {
688 | content: "\f0a6";
689 | }
690 | .bt-caret-right:before {
691 | content: "\f0a7";
692 | }
693 | .bt-long-arrow-up:before {
694 | content: "\f0a8";
695 | }
696 | .bt-long-arrow-down:before {
697 | content: "\f0a9";
698 | }
699 | .bt-long-arrow-left:before {
700 | content: "\f0aa";
701 | }
702 | .bt-long-arrow-right:before {
703 | content: "\f0ab";
704 | }
705 | .bt-Bold:before {
706 | content: "\f0ac";
707 | }
708 | .bt-italic:before {
709 | content: "\f0ad";
710 | }
711 | .bt-underline:before {
712 | content: "\f0ae";
713 | }
714 | .bt-link:before {
715 | content: "\f0b0";
716 | }
717 | .bt-paper-clip:before {
718 | content: "\f0b1";
719 | }
720 | .bt-align-left:before {
721 | content: "\f0b2";
722 | }
723 | .bt-align-center:before {
724 | content: "\f0b3";
725 | }
726 | .bt-align-right:before {
727 | content: "\f0b4";
728 | }
729 | .bt-align-justify:before {
730 | content: "\f0b5";
731 | }
732 | .bt-cut:before {
733 | content: "\f0b6";
734 | }
735 | .bt-copy:before {
736 | content: "\f0b7";
737 | }
738 | .bt-paste:before {
739 | content: "\f0b8";
740 | }
741 | .bt-photo:before {
742 | content: "\f0b9";
743 | }
744 | .bt-table:before {
745 | content: "\f0ba";
746 | }
747 | .bt-ulist:before {
748 | content: "\f0bb";
749 | }
750 | .bt-olist:before {
751 | content: "\f0bc";
752 | }
753 | .bt-indent:before {
754 | content: "\f0bd";
755 | }
756 | .bt-outdent:before {
757 | content: "\f0be";
758 | }
759 | .bt-undo:before {
760 | content: "\f0c0";
761 | }
762 | .bt-redo:before {
763 | content: "\f0c1";
764 | }
765 | .bt-sup:before {
766 | content: "\f0c2";
767 | }
768 | .bt-sub:before {
769 | content: "\f0c3";
770 | }
771 | .bt-text-size:before {
772 | content: "\f0c4";
773 | }
774 | .bt-text-color:before {
775 | content: "\f0c5";
776 | }
777 | .bt-remove-formatting:before {
778 | content: "\f0c6";
779 | }
780 | .bt-blockquote:before {
781 | content: "\f036";
782 | }
783 | .bt-globe:before {
784 | content: "\f0c7";
785 | }
786 | .bt-map:before {
787 | content: "\f0c8";
788 | }
789 | .bt-map-arrow:before {
790 | content: "\f0c9";
791 | }
792 | .bt-map-marker:before {
793 | content: "\f0ca";
794 | }
795 | .bt-map-pin:before {
796 | content: "\f0cb";
797 | }
798 | .bt-home:before {
799 | content: "\f0cc";
800 | }
801 | .bt-building:before {
802 | content: "\f0cd";
803 | }
804 | .bt-industry:before {
805 | content: "\f0ce";
806 | }
807 | .bt-desktop:before {
808 | content: "\f0d0";
809 | }
810 | .bt-laptop:before {
811 | content: "\f0d1";
812 | }
813 | .bt-tablet:before {
814 | content: "\f0d2";
815 | }
816 | .bt-mobile:before {
817 | content: "\f0d3";
818 | }
819 | .bt-tv:before {
820 | content: "\f0d4";
821 | }
822 | .bt-radio-checked:before {
823 | content: "\f0d5";
824 | }
825 | .bt-radio-unchecked:before {
826 | content: "\f08c";
827 | }
828 | .bt-checkbox-checked:before {
829 | content: "\f014";
830 | }
831 | .bt-checkbox-unchecked:before {
832 | content: "\f08b";
833 | }
834 | .bt-checkbox-intermediate:before {
835 | content: "\f023";
836 | }
837 | .bt-user:before {
838 | content: "\f0d6";
839 | }
840 | .bt-user-male:before {
841 | content: "\f0d6";
842 | }
843 | .bt-user-female:before {
844 | content: "\f0d7";
845 | }
846 | .bt-crown:before {
847 | content: "\f0d8";
848 | }
849 | .bt-credit-card:before {
850 | content: "\f0d9";
851 | }
852 | .bt-strikethrough:before {
853 | content: "\f0da";
854 | }
855 | .bt-eject:before {
856 | content: "\f0db";
857 | }
858 | .bt-ellipsis-h:before {
859 | content: "\f0dc";
860 | }
861 | .bt-ellipsis-v:before {
862 | content: "\f0dd";
863 | }
864 | .fab-facebook:before {
865 | content: "\f000";
866 | }
867 | .fab-facebook-alt:before {
868 | content: "\f001";
869 | }
870 | .fab-twitter:before {
871 | content: "\f002";
872 | }
873 | .fab-linkedin:before {
874 | content: "\f003";
875 | }
876 | .fab-linkedin-alt:before {
877 | content: "\f004";
878 | }
879 | .fab-instagram:before {
880 | content: "\f005";
881 | }
882 | .fab-github:before {
883 | content: "\f006";
884 | }
885 | .fab-github-alt:before {
886 | content: "\f007";
887 | }
888 | .fab-googleplus:before {
889 | content: "\f008";
890 | }
891 | .fab-googleplus-alt:before {
892 | content: "\f009";
893 | }
894 | .fab-pinterest:before {
895 | content: "\f00a";
896 | }
897 | .fab-pinterest-alt:before {
898 | content: "\f00b";
899 | }
900 | .fab-tumblr:before {
901 | content: "\f00c";
902 | }
903 | .fab-tumblr-alt:before {
904 | content: "\f00d";
905 | }
906 | .fab-bitcoin:before {
907 | content: "\f010";
908 | }
909 | .fab-bitcoin-alt:before {
910 | content: "\f011";
911 | }
912 | .fab-dropbox:before {
913 | content: "\f012";
914 | }
915 | .fab-stackexchange:before {
916 | content: "\f013";
917 | }
918 | .fab-stackoverflow:before {
919 | content: "\f014";
920 | }
921 | .fab-flickr:before {
922 | content: "\f015";
923 | }
924 | .fab-flickr-alt:before {
925 | content: "\f016";
926 | }
927 | .fab-bitbucket:before {
928 | content: "\f017";
929 | }
930 | .fab-html5:before {
931 | content: "\f018";
932 | }
933 | .fab-css3:before {
934 | content: "\f019";
935 | }
936 | .fab-apple:before {
937 | content: "\f01a";
938 | }
939 | .fab-windows:before {
940 | content: "\f01b";
941 | }
942 | .fab-android:before {
943 | content: "\f01c";
944 | }
945 | .fab-linux:before {
946 | content: "\f01d";
947 | }
948 | .fab-dribbble:before {
949 | content: "\f01e";
950 | }
951 | .fab-youtube:before {
952 | content: "\f021";
953 | }
954 | .fab-skype:before {
955 | content: "\f022";
956 | }
957 | .fab-foursquare:before {
958 | content: "\f023";
959 | }
960 | .fab-trello:before {
961 | content: "\f024";
962 | }
963 | .fab-maxcdn:before {
964 | content: "\f025";
965 | }
966 | .fab-gittip:before,
967 | .fab-gratipay:before {
968 | content: "\f026";
969 | }
970 | .fab-vimeo:before {
971 | content: "\f027";
972 | }
973 | .fab-vimeo-alt:before {
974 | content: "\f028";
975 | }
976 | .fab-slack:before {
977 | content: "\f029";
978 | }
979 | .fab-wordpress:before {
980 | content: "\f02a";
981 | }
982 | .fab-wordpress-alt:before {
983 | content: "\f02b";
984 | }
985 | .fab-openid:before {
986 | content: "\f02c";
987 | }
988 | .fab-yahoo:before {
989 | content: "\f02d";
990 | }
991 | .fab-yahoo-alt:before {
992 | content: "\f02e";
993 | }
994 | .fab-reddit:before {
995 | content: "\f02f";
996 | }
997 | .fab-google:before {
998 | content: "\f030";
999 | }
1000 | .fab-google-alt:before {
1001 | content: "\f031";
1002 | }
1003 | .fab-stumbleupon:before {
1004 | content: "\f032";
1005 | }
1006 | .fab-stumbleupon-alt:before {
1007 | content: "\f033";
1008 | }
1009 | .fab-delicious:before {
1010 | content: "\f034";
1011 | }
1012 | .fab-digg:before {
1013 | content: "\f035";
1014 | }
1015 | .fab-piedpiper:before {
1016 | content: "\f036";
1017 | }
1018 | .fab-piedpiper-alt:before {
1019 | content: "\f037";
1020 | }
1021 | .fab-drupal:before {
1022 | content: "\f038";
1023 | }
1024 | .fab-joomla:before {
1025 | content: "\f039";
1026 | }
1027 | .fab-behance:before {
1028 | content: "\f03a";
1029 | }
1030 | .fab-steam:before {
1031 | content: "\f03b";
1032 | }
1033 | .fab-steam-alt:before {
1034 | content: "\f03c";
1035 | }
1036 | .fab-spotify:before {
1037 | content: "\f03d";
1038 | }
1039 | .fab-deviantart:before {
1040 | content: "\f03e";
1041 | }
1042 | .fab-soundcloud:before {
1043 | content: "\f040";
1044 | }
1045 | .fab-vine:before {
1046 | content: "\f041";
1047 | }
1048 | .fab-codepen:before {
1049 | content: "\f042";
1050 | }
1051 | .fab-jsfiddle:before {
1052 | content: "\f043";
1053 | }
1054 | .fab-rebel:before {
1055 | content: "\f044";
1056 | }
1057 | .fab-empire:before {
1058 | content: "\f045";
1059 | }
1060 | .fab-git:before {
1061 | content: "\f046";
1062 | }
1063 | .fab-hackernews:before {
1064 | content: "\f047";
1065 | }
1066 | .fab-hackernews-alt:before {
1067 | content: "\f048";
1068 | }
1069 | .fab-slideshare:before {
1070 | content: "\f049";
1071 | }
1072 | .fab-twitch:before {
1073 | content: "\f04a";
1074 | }
1075 | .fab-yelp:before {
1076 | content: "\f04b";
1077 | }
1078 | .fab-paypal:before {
1079 | content: "\f04c";
1080 | }
1081 | .fab-google-wallet:before {
1082 | content: "\f04d";
1083 | }
1084 | .fab-angellist:before {
1085 | content: "\f04e";
1086 | }
1087 | .fab-cc-visa:before {
1088 | content: "\f050";
1089 | }
1090 | .fab-cc-mastercard:before {
1091 | content: "\f051";
1092 | }
1093 | .fab-cc-discover:before {
1094 | content: "\f052";
1095 | }
1096 | .fab-cc-amex:before {
1097 | content: "\f053";
1098 | }
1099 | .fab-cc-paypal:before {
1100 | content: "\f054";
1101 | }
1102 | .fab-cc-stripe:before {
1103 | content: "\f055";
1104 | }
1105 | .fab-lastfm:before {
1106 | content: "\f056";
1107 | }
1108 | .fab-whatsapp:before {
1109 | content: "\f057";
1110 | }
1111 | .fab-medium:before {
1112 | content: "\f058";
1113 | }
1114 | .fab-meanpath:before {
1115 | content: "\f059";
1116 | }
1117 | .fab-meanpath-alt:before {
1118 | content: "\f05a";
1119 | }
1120 | .fab-pagelines:before {
1121 | content: "\f05b";
1122 | }
1123 | .fab-ioxhost:before {
1124 | content: "\f060";
1125 | }
1126 | .fab-buysellads:before {
1127 | content: "\f061";
1128 | }
1129 | .fab-buysellads-alt:before {
1130 | content: "\f062";
1131 | }
1132 | .fab-connectdevelop:before {
1133 | content: "\f063";
1134 | }
1135 | .fab-dashcube:before {
1136 | content: "\f064";
1137 | }
1138 | .fab-forumbee:before {
1139 | content: "\f065";
1140 | }
1141 | .fab-leanpub:before {
1142 | content: "\f066";
1143 | }
1144 | .fab-sellsy:before {
1145 | content: "\f067";
1146 | }
1147 | .fab-shirtsinbulk:before {
1148 | content: "\f068";
1149 | }
1150 | .fab-simplybuilt:before {
1151 | content: "\f069";
1152 | }
1153 | .fab-skyatlas:before {
1154 | content: "\f06a";
1155 | }
1156 | .fab-viacoin:before {
1157 | content: "\f06b";
1158 | }
1159 | .fab-codiepie:before {
1160 | content: "\f06c";
1161 | }
1162 | .fab-queue:before {
1163 | content: "\f06d";
1164 | }
1165 | .fab-queue-alt:before {
1166 | content: "\f06e";
1167 | }
1168 | .fab-fonticons:before {
1169 | content: "\f070";
1170 | }
1171 | .fab-fonticons-alt:before {
1172 | content: "\f071";
1173 | }
1174 | .fab-blacktie:before {
1175 | content: "\f072";
1176 | }
1177 | .fab-blacktie-alt:before {
1178 | content: "\f073";
1179 | }
1180 | .fab-xing:before {
1181 | content: "\f090";
1182 | }
1183 | .fab-vk:before {
1184 | content: "\f091";
1185 | }
1186 | .fab-weibo:before {
1187 | content: "\f092";
1188 | }
1189 | .fab-renren:before {
1190 | content: "\f093";
1191 | }
1192 | .fab-tencent-weibo:before {
1193 | content: "\f094";
1194 | }
1195 | .fab-qq:before {
1196 | content: "\f095";
1197 | }
1198 | .fab-wechat:before,
1199 | .fab-weixin:before {
1200 | content: "\f096";
1201 | }
1202 |
--------------------------------------------------------------------------------
/blacktie/fonts/bold/BlackTie-Bold-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gameknife/electron-shadermonki/a6780567960fc0d0d6a523e8fab951cef1eef72a/blacktie/fonts/bold/BlackTie-Bold-webfont.eot
--------------------------------------------------------------------------------
/blacktie/fonts/bold/BlackTie-Bold-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gameknife/electron-shadermonki/a6780567960fc0d0d6a523e8fab951cef1eef72a/blacktie/fonts/bold/BlackTie-Bold-webfont.ttf
--------------------------------------------------------------------------------
/blacktie/fonts/bold/BlackTie-Bold-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gameknife/electron-shadermonki/a6780567960fc0d0d6a523e8fab951cef1eef72a/blacktie/fonts/bold/BlackTie-Bold-webfont.woff
--------------------------------------------------------------------------------
/blacktie/fonts/bold/BlackTie-Bold-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gameknife/electron-shadermonki/a6780567960fc0d0d6a523e8fab951cef1eef72a/blacktie/fonts/bold/BlackTie-Bold-webfont.woff2
--------------------------------------------------------------------------------
/blacktie/fonts/brands/FontAwesomeBrands-Regular-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gameknife/electron-shadermonki/a6780567960fc0d0d6a523e8fab951cef1eef72a/blacktie/fonts/brands/FontAwesomeBrands-Regular-webfont.eot
--------------------------------------------------------------------------------
/blacktie/fonts/brands/FontAwesomeBrands-Regular-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gameknife/electron-shadermonki/a6780567960fc0d0d6a523e8fab951cef1eef72a/blacktie/fonts/brands/FontAwesomeBrands-Regular-webfont.ttf
--------------------------------------------------------------------------------
/blacktie/fonts/brands/FontAwesomeBrands-Regular-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gameknife/electron-shadermonki/a6780567960fc0d0d6a523e8fab951cef1eef72a/blacktie/fonts/brands/FontAwesomeBrands-Regular-webfont.woff
--------------------------------------------------------------------------------
/blacktie/fonts/brands/FontAwesomeBrands-Regular-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gameknife/electron-shadermonki/a6780567960fc0d0d6a523e8fab951cef1eef72a/blacktie/fonts/brands/FontAwesomeBrands-Regular-webfont.woff2
--------------------------------------------------------------------------------
/blacktie/fonts/light/BlackTie-Light-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gameknife/electron-shadermonki/a6780567960fc0d0d6a523e8fab951cef1eef72a/blacktie/fonts/light/BlackTie-Light-webfont.eot
--------------------------------------------------------------------------------
/blacktie/fonts/light/BlackTie-Light-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gameknife/electron-shadermonki/a6780567960fc0d0d6a523e8fab951cef1eef72a/blacktie/fonts/light/BlackTie-Light-webfont.ttf
--------------------------------------------------------------------------------
/blacktie/fonts/light/BlackTie-Light-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gameknife/electron-shadermonki/a6780567960fc0d0d6a523e8fab951cef1eef72a/blacktie/fonts/light/BlackTie-Light-webfont.woff
--------------------------------------------------------------------------------
/blacktie/fonts/light/BlackTie-Light-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gameknife/electron-shadermonki/a6780567960fc0d0d6a523e8fab951cef1eef72a/blacktie/fonts/light/BlackTie-Light-webfont.woff2
--------------------------------------------------------------------------------
/blacktie/fonts/medium/BlackTie-Medium-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gameknife/electron-shadermonki/a6780567960fc0d0d6a523e8fab951cef1eef72a/blacktie/fonts/medium/BlackTie-Medium-webfont.eot
--------------------------------------------------------------------------------
/blacktie/fonts/medium/BlackTie-Medium-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gameknife/electron-shadermonki/a6780567960fc0d0d6a523e8fab951cef1eef72a/blacktie/fonts/medium/BlackTie-Medium-webfont.ttf
--------------------------------------------------------------------------------
/blacktie/fonts/medium/BlackTie-Medium-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gameknife/electron-shadermonki/a6780567960fc0d0d6a523e8fab951cef1eef72a/blacktie/fonts/medium/BlackTie-Medium-webfont.woff
--------------------------------------------------------------------------------
/blacktie/fonts/medium/BlackTie-Medium-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gameknife/electron-shadermonki/a6780567960fc0d0d6a523e8fab951cef1eef72a/blacktie/fonts/medium/BlackTie-Medium-webfont.woff2
--------------------------------------------------------------------------------
/blacktie/fonts/solid/BlackTie-Solid-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gameknife/electron-shadermonki/a6780567960fc0d0d6a523e8fab951cef1eef72a/blacktie/fonts/solid/BlackTie-Solid-webfont.eot
--------------------------------------------------------------------------------
/blacktie/fonts/solid/BlackTie-Solid-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gameknife/electron-shadermonki/a6780567960fc0d0d6a523e8fab951cef1eef72a/blacktie/fonts/solid/BlackTie-Solid-webfont.ttf
--------------------------------------------------------------------------------
/blacktie/fonts/solid/BlackTie-Solid-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gameknife/electron-shadermonki/a6780567960fc0d0d6a523e8fab951cef1eef72a/blacktie/fonts/solid/BlackTie-Solid-webfont.woff
--------------------------------------------------------------------------------
/blacktie/fonts/solid/BlackTie-Solid-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gameknife/electron-shadermonki/a6780567960fc0d0d6a523e8fab951cef1eef72a/blacktie/fonts/solid/BlackTie-Solid-webfont.woff2
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | shadermonk!
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
24 |
25 |
26 |
27 |
28 |
29 | Real-time Preview
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | Console
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 | Components
60 |
61 |
62 |
63 | Mesh-Filter
64 |
65 | RenderingMesh
66 |
67 |
68 | Drag mesh here!
69 |
70 |
71 |
72 |
73 | Material
74 |
75 | _MainTex
76 |
77 |
78 | Drag texture here!
79 |
80 |
81 |
82 |
83 | Export
84 |
85 | to .obj
86 |
87 |
88 | Export
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 | Vertex Shader Editor
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 | Fragment Shader Editor
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 | Resources
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 | ready.
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
144 |
145 |
--------------------------------------------------------------------------------
/lib/ace/mode-glsl.js:
--------------------------------------------------------------------------------
1 | define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"], function(require, exports, module) {
2 | "use strict";
3 |
4 | var oop = require("../lib/oop");
5 | var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
6 |
7 | var DocCommentHighlightRules = function() {
8 | this.$rules = {
9 | "start" : [ {
10 | token : "comment.doc.tag",
11 | regex : "@[\\w\\d_]+" // TODO: fix email addresses
12 | },
13 | DocCommentHighlightRules.getTagRule(),
14 | {
15 | defaultToken : "comment.doc",
16 | caseInsensitive: true
17 | }]
18 | };
19 | };
20 |
21 | oop.inherits(DocCommentHighlightRules, TextHighlightRules);
22 |
23 | DocCommentHighlightRules.getTagRule = function(start) {
24 | return {
25 | token : "comment.doc.tag.storage.type",
26 | regex : "\\b(?:TODO|FIXME|XXX|HACK)\\b"
27 | };
28 | }
29 |
30 | DocCommentHighlightRules.getStartRule = function(start) {
31 | return {
32 | token : "comment.doc", // doc comment
33 | regex : "\\/\\*(?=\\*)",
34 | next : start
35 | };
36 | };
37 |
38 | DocCommentHighlightRules.getEndRule = function (start) {
39 | return {
40 | token : "comment.doc", // closing comment
41 | regex : "\\*\\/",
42 | next : start
43 | };
44 | };
45 |
46 |
47 | exports.DocCommentHighlightRules = DocCommentHighlightRules;
48 |
49 | });
50 |
51 | define("ace/mode/c_cpp_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"], function(require, exports, module) {
52 | "use strict";
53 |
54 | var oop = require("../lib/oop");
55 | var DocCommentHighlightRules = require("./doc_comment_highlight_rules").DocCommentHighlightRules;
56 | var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
57 | var cFunctions = exports.cFunctions = "\\b(?:hypot(?:f|l)?|s(?:scanf|ystem|nprintf|ca(?:nf|lb(?:n(?:f|l)?|ln(?:f|l)?))|i(?:n(?:h(?:f|l)?|f|l)?|gn(?:al|bit))|tr(?:s(?:tr|pn)|nc(?:py|at|mp)|c(?:spn|hr|oll|py|at|mp)|to(?:imax|d|u(?:l(?:l)?|max)|k|f|l(?:d|l)?)|error|pbrk|ftime|len|rchr|xfrm)|printf|et(?:jmp|vbuf|locale|buf)|qrt(?:f|l)?|w(?:scanf|printf)|rand)|n(?:e(?:arbyint(?:f|l)?|xt(?:toward(?:f|l)?|after(?:f|l)?))|an(?:f|l)?)|c(?:s(?:in(?:h(?:f|l)?|f|l)?|qrt(?:f|l)?)|cos(?:h(?:f)?|f|l)?|imag(?:f|l)?|t(?:ime|an(?:h(?:f|l)?|f|l)?)|o(?:s(?:h(?:f|l)?|f|l)?|nj(?:f|l)?|pysign(?:f|l)?)|p(?:ow(?:f|l)?|roj(?:f|l)?)|e(?:il(?:f|l)?|xp(?:f|l)?)|l(?:o(?:ck|g(?:f|l)?)|earerr)|a(?:sin(?:h(?:f|l)?|f|l)?|cos(?:h(?:f|l)?|f|l)?|tan(?:h(?:f|l)?|f|l)?|lloc|rg(?:f|l)?|bs(?:f|l)?)|real(?:f|l)?|brt(?:f|l)?)|t(?:ime|o(?:upper|lower)|an(?:h(?:f|l)?|f|l)?|runc(?:f|l)?|gamma(?:f|l)?|mp(?:nam|file))|i(?:s(?:space|n(?:ormal|an)|cntrl|inf|digit|u(?:nordered|pper)|p(?:unct|rint)|finite|w(?:space|c(?:ntrl|type)|digit|upper|p(?:unct|rint)|lower|al(?:num|pha)|graph|xdigit|blank)|l(?:ower|ess(?:equal|greater)?)|al(?:num|pha)|gr(?:eater(?:equal)?|aph)|xdigit|blank)|logb(?:f|l)?|max(?:div|abs))|di(?:v|fftime)|_Exit|unget(?:c|wc)|p(?:ow(?:f|l)?|ut(?:s|c(?:har)?|wc(?:har)?)|error|rintf)|e(?:rf(?:c(?:f|l)?|f|l)?|x(?:it|p(?:2(?:f|l)?|f|l|m1(?:f|l)?)?))|v(?:s(?:scanf|nprintf|canf|printf|w(?:scanf|printf))|printf|f(?:scanf|printf|w(?:scanf|printf))|w(?:scanf|printf)|a_(?:start|copy|end|arg))|qsort|f(?:s(?:canf|e(?:tpos|ek))|close|tell|open|dim(?:f|l)?|p(?:classify|ut(?:s|c|w(?:s|c))|rintf)|e(?:holdexcept|set(?:e(?:nv|xceptflag)|round)|clearexcept|testexcept|of|updateenv|r(?:aiseexcept|ror)|get(?:e(?:nv|xceptflag)|round))|flush|w(?:scanf|ide|printf|rite)|loor(?:f|l)?|abs(?:f|l)?|get(?:s|c|pos|w(?:s|c))|re(?:open|e|ad|xp(?:f|l)?)|m(?:in(?:f|l)?|od(?:f|l)?|a(?:f|l|x(?:f|l)?)?))|l(?:d(?:iv|exp(?:f|l)?)|o(?:ngjmp|cal(?:time|econv)|g(?:1(?:p(?:f|l)?|0(?:f|l)?)|2(?:f|l)?|f|l|b(?:f|l)?)?)|abs|l(?:div|abs|r(?:int(?:f|l)?|ound(?:f|l)?))|r(?:int(?:f|l)?|ound(?:f|l)?)|gamma(?:f|l)?)|w(?:scanf|c(?:s(?:s(?:tr|pn)|nc(?:py|at|mp)|c(?:spn|hr|oll|py|at|mp)|to(?:imax|d|u(?:l(?:l)?|max)|k|f|l(?:d|l)?|mbs)|pbrk|ftime|len|r(?:chr|tombs)|xfrm)|to(?:b|mb)|rtomb)|printf|mem(?:set|c(?:hr|py|mp)|move))|a(?:s(?:sert|ctime|in(?:h(?:f|l)?|f|l)?)|cos(?:h(?:f|l)?|f|l)?|t(?:o(?:i|f|l(?:l)?)|exit|an(?:h(?:f|l)?|2(?:f|l)?|f|l)?)|b(?:s|ort))|g(?:et(?:s|c(?:har)?|env|wc(?:har)?)|mtime)|r(?:int(?:f|l)?|ound(?:f|l)?|e(?:name|alloc|wind|m(?:ove|quo(?:f|l)?|ainder(?:f|l)?))|a(?:nd|ise))|b(?:search|towc)|m(?:odf(?:f|l)?|em(?:set|c(?:hr|py|mp)|move)|ktime|alloc|b(?:s(?:init|towcs|rtowcs)|towc|len|r(?:towc|len))))\\b"
58 |
59 | var c_cppHighlightRules = function() {
60 |
61 | var keywordControls = (
62 | "break|case|continue|default|do|else|for|goto|if|_Pragma|" +
63 | "return|switch|while|catch|operator|try|throw|using"
64 | );
65 |
66 | var storageType = (
67 | "asm|__asm__|auto|bool|_Bool|char|_Complex|double|enum|float|" +
68 | "_Imaginary|int|long|short|signed|struct|typedef|union|unsigned|void|" +
69 | "class|wchar_t|template|char16_t|char32_t"
70 | );
71 |
72 | var storageModifiers = (
73 | "const|extern|register|restrict|static|volatile|inline|private|" +
74 | "protected|public|friend|explicit|virtual|export|mutable|typename|" +
75 | "constexpr|new|delete|alignas|alignof|decltype|noexcept|thread_local"
76 | );
77 |
78 | var keywordOperators = (
79 | "and|and_eq|bitand|bitor|compl|not|not_eq|or|or_eq|typeid|xor|xor_eq" +
80 | "const_cast|dynamic_cast|reinterpret_cast|static_cast|sizeof|namespace"
81 | );
82 |
83 | var builtinConstants = (
84 | "NULL|true|false|TRUE|FALSE|nullptr"
85 | );
86 |
87 | var keywordMapper = this.$keywords = this.createKeywordMapper({
88 | "keyword.control" : keywordControls,
89 | "storage.type" : storageType,
90 | "storage.modifier" : storageModifiers,
91 | "keyword.operator" : keywordOperators,
92 | "variable.language": "this",
93 | "constant.language": builtinConstants
94 | }, "identifier");
95 |
96 | var identifierRe = "[a-zA-Z\\$_\u00a1-\uffff][a-zA-Z\\d\\$_\u00a1-\uffff]*\\b";
97 | var escapeRe = /\\(?:['"?\\abfnrtv]|[0-7]{1,3}|x[a-fA-F\d]{2}|u[a-fA-F\d]{4}U[a-fA-F\d]{8}|.)/.source;
98 |
99 | this.$rules = {
100 | "start" : [
101 | {
102 | token : "comment",
103 | regex : "//$",
104 | next : "start"
105 | }, {
106 | token : "comment",
107 | regex : "//",
108 | next : "singleLineComment"
109 | },
110 | DocCommentHighlightRules.getStartRule("doc-start"),
111 | {
112 | token : "comment", // multi line comment
113 | regex : "\\/\\*",
114 | next : "comment"
115 | }, {
116 | token : "string", // character
117 | regex : "'(?:" + escapeRe + "|.)?'"
118 | }, {
119 | token : "string.start",
120 | regex : '"',
121 | stateName: "qqstring",
122 | next: [
123 | { token: "string", regex: /\\\s*$/, next: "qqstring" },
124 | { token: "constant.language.escape", regex: escapeRe },
125 | { token: "constant.language.escape", regex: /%[^'"\\]/ },
126 | { token: "string.end", regex: '"|$', next: "start" },
127 | { defaultToken: "string"}
128 | ]
129 | }, {
130 | token : "string.start",
131 | regex : 'R"\\(',
132 | stateName: "rawString",
133 | next: [
134 | { token: "string.end", regex: '\\)"', next: "start" },
135 | { defaultToken: "string"}
136 | ]
137 | }, {
138 | token : "constant.numeric", // hex
139 | regex : "0[xX][0-9a-fA-F]+(L|l|UL|ul|u|U|F|f|ll|LL|ull|ULL)?\\b"
140 | }, {
141 | token : "constant.numeric", // float
142 | regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?(L|l|UL|ul|u|U|F|f|ll|LL|ull|ULL)?\\b"
143 | }, {
144 | token : "keyword", // pre-compiler directives
145 | regex : "#\\s*(?:include|import|pragma|line|define|undef)\\b",
146 | next : "directive"
147 | }, {
148 | token : "keyword", // special case pre-compiler directive
149 | regex : "#\\s*(?:endif|if|ifdef|else|elif|ifndef)\\b"
150 | }, {
151 | token : "support.function.C99.c",
152 | regex : cFunctions
153 | }, {
154 | token : keywordMapper,
155 | regex : "[a-zA-Z_$][a-zA-Z0-9_$]*"
156 | }, {
157 | token : "keyword.operator",
158 | regex : /--|\+\+|<<=|>>=|>>>=|<>|&&|\|\||\?:|[*%\/+\-&\^|~!<>=]=?/
159 | }, {
160 | token : "punctuation.operator",
161 | regex : "\\?|\\:|\\,|\\;|\\."
162 | }, {
163 | token : "paren.lparen",
164 | regex : "[[({]"
165 | }, {
166 | token : "paren.rparen",
167 | regex : "[\\])}]"
168 | }, {
169 | token : "text",
170 | regex : "\\s+"
171 | }
172 | ],
173 | "comment" : [
174 | {
175 | token : "comment", // closing comment
176 | regex : ".*?\\*\\/",
177 | next : "start"
178 | }, {
179 | token : "comment", // comment spanning whole line
180 | regex : ".+"
181 | }
182 | ],
183 | "singleLineComment" : [
184 | {
185 | token : "comment",
186 | regex : /\\$/,
187 | next : "singleLineComment"
188 | }, {
189 | token : "comment",
190 | regex : /$/,
191 | next : "start"
192 | }, {
193 | defaultToken: "comment"
194 | }
195 | ],
196 | "directive" : [
197 | {
198 | token : "constant.other.multiline",
199 | regex : /\\/
200 | },
201 | {
202 | token : "constant.other.multiline",
203 | regex : /.*\\/
204 | },
205 | {
206 | token : "constant.other",
207 | regex : "\\s*<.+?>",
208 | next : "start"
209 | },
210 | {
211 | token : "constant.other", // single line
212 | regex : '\\s*["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]',
213 | next : "start"
214 | },
215 | {
216 | token : "constant.other", // single line
217 | regex : "\\s*['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']",
218 | next : "start"
219 | },
220 | {
221 | token : "constant.other",
222 | regex : /[^\\\/]+/,
223 | next : "start"
224 | }
225 | ]
226 | };
227 |
228 | this.embedRules(DocCommentHighlightRules, "doc-",
229 | [ DocCommentHighlightRules.getEndRule("start") ]);
230 | this.normalizeRules();
231 | };
232 |
233 | oop.inherits(c_cppHighlightRules, TextHighlightRules);
234 |
235 | exports.c_cppHighlightRules = c_cppHighlightRules;
236 | });
237 |
238 | define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"], function(require, exports, module) {
239 | "use strict";
240 |
241 | var Range = require("../range").Range;
242 |
243 | var MatchingBraceOutdent = function() {};
244 |
245 | (function() {
246 |
247 | this.checkOutdent = function(line, input) {
248 | if (! /^\s+$/.test(line))
249 | return false;
250 |
251 | return /^\s*\}/.test(input);
252 | };
253 |
254 | this.autoOutdent = function(doc, row) {
255 | var line = doc.getLine(row);
256 | var match = line.match(/^(\s*\})/);
257 |
258 | if (!match) return 0;
259 |
260 | var column = match[1].length;
261 | var openBracePos = doc.findMatchingBracket({row: row, column: column});
262 |
263 | if (!openBracePos || openBracePos.row == row) return 0;
264 |
265 | var indent = this.$getIndent(doc.getLine(openBracePos.row));
266 | doc.replace(new Range(row, 0, row, column-1), indent);
267 | };
268 |
269 | this.$getIndent = function(line) {
270 | return line.match(/^\s*/)[0];
271 | };
272 |
273 | }).call(MatchingBraceOutdent.prototype);
274 |
275 | exports.MatchingBraceOutdent = MatchingBraceOutdent;
276 | });
277 |
278 | define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"], function(require, exports, module) {
279 | "use strict";
280 |
281 | var oop = require("../../lib/oop");
282 | var Range = require("../../range").Range;
283 | var BaseFoldMode = require("./fold_mode").FoldMode;
284 |
285 | var FoldMode = exports.FoldMode = function(commentRegex) {
286 | if (commentRegex) {
287 | this.foldingStartMarker = new RegExp(
288 | this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start)
289 | );
290 | this.foldingStopMarker = new RegExp(
291 | this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end)
292 | );
293 | }
294 | };
295 | oop.inherits(FoldMode, BaseFoldMode);
296 |
297 | (function() {
298 |
299 | this.foldingStartMarker = /(\{|\[)[^\}\]]*$|^\s*(\/\*)/;
300 | this.foldingStopMarker = /^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/;
301 | this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/;
302 | this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/;
303 | this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/;
304 | this._getFoldWidgetBase = this.getFoldWidget;
305 | this.getFoldWidget = function(session, foldStyle, row) {
306 | var line = session.getLine(row);
307 |
308 | if (this.singleLineBlockCommentRe.test(line)) {
309 | if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line))
310 | return "";
311 | }
312 |
313 | var fw = this._getFoldWidgetBase(session, foldStyle, row);
314 |
315 | if (!fw && this.startRegionRe.test(line))
316 | return "start"; // lineCommentRegionStart
317 |
318 | return fw;
319 | };
320 |
321 | this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) {
322 | var line = session.getLine(row);
323 |
324 | if (this.startRegionRe.test(line))
325 | return this.getCommentRegionBlock(session, line, row);
326 |
327 | var match = line.match(this.foldingStartMarker);
328 | if (match) {
329 | var i = match.index;
330 |
331 | if (match[1])
332 | return this.openingBracketBlock(session, match[1], row, i);
333 |
334 | var range = session.getCommentFoldRange(row, i + match[0].length, 1);
335 |
336 | if (range && !range.isMultiLine()) {
337 | if (forceMultiline) {
338 | range = this.getSectionRange(session, row);
339 | } else if (foldStyle != "all")
340 | range = null;
341 | }
342 |
343 | return range;
344 | }
345 |
346 | if (foldStyle === "markbegin")
347 | return;
348 |
349 | var match = line.match(this.foldingStopMarker);
350 | if (match) {
351 | var i = match.index + match[0].length;
352 |
353 | if (match[1])
354 | return this.closingBracketBlock(session, match[1], row, i);
355 |
356 | return session.getCommentFoldRange(row, i, -1);
357 | }
358 | };
359 |
360 | this.getSectionRange = function(session, row) {
361 | var line = session.getLine(row);
362 | var startIndent = line.search(/\S/);
363 | var startRow = row;
364 | var startColumn = line.length;
365 | row = row + 1;
366 | var endRow = row;
367 | var maxRow = session.getLength();
368 | while (++row < maxRow) {
369 | line = session.getLine(row);
370 | var indent = line.search(/\S/);
371 | if (indent === -1)
372 | continue;
373 | if (startIndent > indent)
374 | break;
375 | var subRange = this.getFoldWidgetRange(session, "all", row);
376 |
377 | if (subRange) {
378 | if (subRange.start.row <= startRow) {
379 | break;
380 | } else if (subRange.isMultiLine()) {
381 | row = subRange.end.row;
382 | } else if (startIndent == indent) {
383 | break;
384 | }
385 | }
386 | endRow = row;
387 | }
388 |
389 | return new Range(startRow, startColumn, endRow, session.getLine(endRow).length);
390 | };
391 | this.getCommentRegionBlock = function(session, line, row) {
392 | var startColumn = line.search(/\s*$/);
393 | var maxRow = session.getLength();
394 | var startRow = row;
395 |
396 | var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/;
397 | var depth = 1;
398 | while (++row < maxRow) {
399 | line = session.getLine(row);
400 | var m = re.exec(line);
401 | if (!m) continue;
402 | if (m[1]) depth--;
403 | else depth++;
404 |
405 | if (!depth) break;
406 | }
407 |
408 | var endRow = row;
409 | if (endRow > startRow) {
410 | return new Range(startRow, startColumn, endRow, line.length);
411 | }
412 | };
413 |
414 | }).call(FoldMode.prototype);
415 |
416 | });
417 |
418 | define("ace/mode/c_cpp",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/c_cpp_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"], function(require, exports, module) {
419 | "use strict";
420 |
421 | var oop = require("../lib/oop");
422 | var TextMode = require("./text").Mode;
423 | var c_cppHighlightRules = require("./c_cpp_highlight_rules").c_cppHighlightRules;
424 | var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent;
425 | var Range = require("../range").Range;
426 | var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour;
427 | var CStyleFoldMode = require("./folding/cstyle").FoldMode;
428 |
429 | var Mode = function() {
430 | this.HighlightRules = c_cppHighlightRules;
431 |
432 | this.$outdent = new MatchingBraceOutdent();
433 | this.$behaviour = new CstyleBehaviour();
434 |
435 | this.foldingRules = new CStyleFoldMode();
436 | };
437 | oop.inherits(Mode, TextMode);
438 |
439 | (function() {
440 |
441 | this.lineCommentStart = "//";
442 | this.blockComment = {start: "/*", end: "*/"};
443 |
444 | this.getNextLineIndent = function(state, line, tab) {
445 | var indent = this.$getIndent(line);
446 |
447 | var tokenizedLine = this.getTokenizer().getLineTokens(line, state);
448 | var tokens = tokenizedLine.tokens;
449 | var endState = tokenizedLine.state;
450 |
451 | if (tokens.length && tokens[tokens.length-1].type == "comment") {
452 | return indent;
453 | }
454 |
455 | if (state == "start") {
456 | var match = line.match(/^.*[\{\(\[]\s*$/);
457 | if (match) {
458 | indent += tab;
459 | }
460 | } else if (state == "doc-start") {
461 | if (endState == "start") {
462 | return "";
463 | }
464 | var match = line.match(/^\s*(\/?)\*/);
465 | if (match) {
466 | if (match[1]) {
467 | indent += " ";
468 | }
469 | indent += "* ";
470 | }
471 | }
472 |
473 | return indent;
474 | };
475 |
476 | this.checkOutdent = function(state, line, input) {
477 | return this.$outdent.checkOutdent(line, input);
478 | };
479 |
480 | this.autoOutdent = function(state, doc, row) {
481 | this.$outdent.autoOutdent(doc, row);
482 | };
483 |
484 | this.$id = "ace/mode/c_cpp";
485 | }).call(Mode.prototype);
486 |
487 | exports.Mode = Mode;
488 | });
489 |
490 | define("ace/mode/glsl_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/c_cpp_highlight_rules"], function(require, exports, module) {
491 | "use strict";
492 |
493 | var oop = require("../lib/oop");
494 | var c_cppHighlightRules = require("./c_cpp_highlight_rules").c_cppHighlightRules;
495 |
496 | var glslHighlightRules = function() {
497 |
498 | var keywords = (
499 | "attribute|const|uniform|varying|break|continue|do|for|while|" +
500 | "if|else|in|out|inout|float|int|void|bool|true|false|" +
501 | "lowp|mediump|highp|precision|invariant|discard|return|mat2|mat3|" +
502 | "mat4|vec2|vec3|vec4|ivec2|ivec3|ivec4|bvec2|bvec3|bvec4|sampler2D|" +
503 | "samplerCube|struct"
504 | );
505 |
506 | var buildinConstants = (
507 | "radians|degrees|sin|cos|tan|asin|acos|atan|pow|" +
508 | "exp|log|exp2|log2|sqrt|inversesqrt|abs|sign|floor|ceil|fract|mod|" +
509 | "min|max|clamp|mix|step|smoothstep|length|distance|dot|cross|" +
510 | "normalize|faceforward|reflect|refract|matrixCompMult|lessThan|" +
511 | "lessThanEqual|greaterThan|greaterThanEqual|equal|notEqual|any|all|" +
512 | "not|dFdx|dFdy|fwidth|texture2D|texture2DProj|texture2DLod|" +
513 | "texture2DProjLod|textureCube|textureCubeLod|" +
514 | "gl_MaxVertexAttribs|gl_MaxVertexUniformVectors|gl_MaxVaryingVectors|" +
515 | "gl_MaxVertexTextureImageUnits|gl_MaxCombinedTextureImageUnits|" +
516 | "gl_MaxTextureImageUnits|gl_MaxFragmentUniformVectors|gl_MaxDrawBuffers|" +
517 | "gl_DepthRangeParameters|gl_DepthRange|" +
518 | "gl_Position|gl_PointSize|" +
519 | "gl_FragCoord|gl_FrontFacing|gl_PointCoord|gl_FragColor|gl_FragData"
520 | );
521 |
522 | var keywordMapper = this.createKeywordMapper({
523 | "variable.language": "this",
524 | "keyword": keywords,
525 | "constant.language": buildinConstants
526 | }, "identifier");
527 |
528 | this.$rules = new c_cppHighlightRules().$rules;
529 | this.$rules.start.forEach(function(rule) {
530 | if (typeof rule.token == "function")
531 | rule.token = keywordMapper;
532 | })
533 | };
534 |
535 | oop.inherits(glslHighlightRules, c_cppHighlightRules);
536 |
537 | exports.glslHighlightRules = glslHighlightRules;
538 | });
539 |
540 | define("ace/mode/glsl",["require","exports","module","ace/lib/oop","ace/mode/c_cpp","ace/mode/glsl_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"], function(require, exports, module) {
541 | "use strict";
542 |
543 | var oop = require("../lib/oop");
544 | var CMode = require("./c_cpp").Mode;
545 | var glslHighlightRules = require("./glsl_highlight_rules").glslHighlightRules;
546 | var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent;
547 | var Range = require("../range").Range;
548 | var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour;
549 | var CStyleFoldMode = require("./folding/cstyle").FoldMode;
550 |
551 | var Mode = function() {
552 | this.HighlightRules = glslHighlightRules;
553 |
554 | this.$outdent = new MatchingBraceOutdent();
555 | this.$behaviour = new CstyleBehaviour();
556 | this.foldingRules = new CStyleFoldMode();
557 | };
558 | oop.inherits(Mode, CMode);
559 |
560 | (function() {
561 | this.$id = "ace/mode/glsl";
562 | }).call(Mode.prototype);
563 |
564 | exports.Mode = Mode;
565 | });
566 |
--------------------------------------------------------------------------------
/lib/ace/snippets/glsl.js:
--------------------------------------------------------------------------------
1 | define("ace/snippets/glsl",["require","exports","module"], function(require, exports, module) {
2 | "use strict";
3 |
4 | exports.snippetText =undefined;
5 | exports.scope = "glsl";
6 |
7 | });
8 |
--------------------------------------------------------------------------------
/lib/ace/theme-twilight.js:
--------------------------------------------------------------------------------
1 | define("ace/theme/twilight",["require","exports","module","ace/lib/dom"], function(require, exports, module) {
2 |
3 | exports.isDark = true;
4 | exports.cssClass = "ace-twilight";
5 | exports.cssText = ".ace-twilight .ace_gutter {\
6 | background: #232323;\
7 | color: #E2E2E2\
8 | }\
9 | .ace-twilight .ace_print-margin {\
10 | width: 1px;\
11 | background: #232323\
12 | }\
13 | .ace-twilight {\
14 | background-color: #141414;\
15 | color: #F8F8F8\
16 | }\
17 | .ace-twilight .ace_cursor {\
18 | color: #A7A7A7\
19 | }\
20 | .ace-twilight .ace_marker-layer .ace_selection {\
21 | background: rgba(221, 240, 255, 0.20)\
22 | }\
23 | .ace-twilight.ace_multiselect .ace_selection.ace_start {\
24 | box-shadow: 0 0 3px 0px #141414;\
25 | }\
26 | .ace-twilight .ace_marker-layer .ace_step {\
27 | background: rgb(102, 82, 0)\
28 | }\
29 | .ace-twilight .ace_marker-layer .ace_bracket {\
30 | margin: -1px 0 0 -1px;\
31 | border: 1px solid rgba(255, 255, 255, 0.25)\
32 | }\
33 | .ace-twilight .ace_marker-layer .ace_active-line {\
34 | background: rgba(255, 255, 255, 0.031)\
35 | }\
36 | .ace-twilight .ace_gutter-active-line {\
37 | background-color: rgba(255, 255, 255, 0.031)\
38 | }\
39 | .ace-twilight .ace_marker-layer .ace_selected-word {\
40 | border: 1px solid rgba(221, 240, 255, 0.20)\
41 | }\
42 | .ace-twilight .ace_invisible {\
43 | color: rgba(255, 255, 255, 0.25)\
44 | }\
45 | .ace-twilight .ace_keyword,\
46 | .ace-twilight .ace_meta {\
47 | color: #CDA869\
48 | }\
49 | .ace-twilight .ace_constant,\
50 | .ace-twilight .ace_constant.ace_character,\
51 | .ace-twilight .ace_constant.ace_character.ace_escape,\
52 | .ace-twilight .ace_constant.ace_other,\
53 | .ace-twilight .ace_heading,\
54 | .ace-twilight .ace_markup.ace_heading,\
55 | .ace-twilight .ace_support.ace_constant {\
56 | color: #CF6A4C\
57 | }\
58 | .ace-twilight .ace_invalid.ace_illegal {\
59 | color: #F8F8F8;\
60 | background-color: rgba(86, 45, 86, 0.75)\
61 | }\
62 | .ace-twilight .ace_invalid.ace_deprecated {\
63 | text-decoration: underline;\
64 | font-style: italic;\
65 | color: #D2A8A1\
66 | }\
67 | .ace-twilight .ace_support {\
68 | color: #9B859D\
69 | }\
70 | .ace-twilight .ace_fold {\
71 | background-color: #AC885B;\
72 | border-color: #F8F8F8\
73 | }\
74 | .ace-twilight .ace_support.ace_function {\
75 | color: #DAD085\
76 | }\
77 | .ace-twilight .ace_list,\
78 | .ace-twilight .ace_markup.ace_list,\
79 | .ace-twilight .ace_storage {\
80 | color: #F9EE98\
81 | }\
82 | .ace-twilight .ace_entity.ace_name.ace_function,\
83 | .ace-twilight .ace_meta.ace_tag,\
84 | .ace-twilight .ace_variable {\
85 | color: #AC885B\
86 | }\
87 | .ace-twilight .ace_string {\
88 | color: #8F9D6A\
89 | }\
90 | .ace-twilight .ace_string.ace_regexp {\
91 | color: #E9C062\
92 | }\
93 | .ace-twilight .ace_comment {\
94 | font-style: italic;\
95 | color: #82a463\
96 | }\
97 | .ace-twilight .ace_variable {\
98 | color: #7587A6\
99 | }\
100 | .ace-twilight .ace_xml-pe {\
101 | color: #494949\
102 | }\
103 | .ace-twilight .ace_indent-guide {\
104 | background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWMQERFpYLC1tf0PAAgOAnPnhxyiAAAAAElFTkSuQmCC) right repeat-y\
105 | }";
106 |
107 | var dom = require("../lib/dom");
108 | dom.importCssString(exports.cssText, exports.cssClass);
109 | });
110 |
--------------------------------------------------------------------------------
/lib/editor/gk-inspector.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by gameKnife on 2016/12/13.
3 | */
4 | class Inspector {
5 |
6 | constructor() {
7 |
8 | }
9 |
10 | get Selection() {
11 |
12 | }
13 | set Selection( value ) {
14 |
15 | }
16 |
17 | updatePanel() {
18 |
19 | }
20 |
21 | }
22 |
23 | module.exports = Inspector;
--------------------------------------------------------------------------------
/lib/exporter/exporter-obj.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by kaimingyi on 2016/12/15.
3 | */
4 | const Component = require('../gk-component.js');
5 | const math = require('gl-matrix');
6 | const fs = require('fs');
7 | const path = require('path');
8 |
9 | var exporter_obj = exporter_obj || {};
10 | module.exports = exporter_obj;
11 |
12 | exporter_obj.normalizeName = function(str) {
13 |
14 | let ret = str.replace(/ /g, "_");
15 | ret = ret.replace(/#/g, "_");
16 | return ret;
17 |
18 | }
19 |
20 | exporter_obj.exportNode = function( rootGameObject, base_path )
21 | {
22 | // make root transform to root
23 | if( !(rootGameObject instanceof Component.Transform ) )
24 | {
25 | console.info('export error, root node must be Component.Transform');
26 | return;
27 | }
28 |
29 | let orgParent = rootGameObject.parent;
30 | rootGameObject.parent = null;
31 |
32 | // goThrough each MeshFilter, export into obj
33 | let mfs = rootGameObject.getComponent( Component.MeshFilter );
34 |
35 | let headerPart = 'mtllib ./exported.mtl\r';
36 |
37 | let vertexPart = '';
38 | let normalPart = '';
39 | let texcoordPart = '';
40 |
41 | let mtlFileContent = '';
42 |
43 | let facePart = '';
44 | let totalVertexPassed = 1;
45 | let totalObjectPassed = 0;
46 |
47 | let materialNames = [];
48 |
49 | mfs.forEach( meshFilter => {
50 | if( meshFilter.mesh )
51 | {
52 | facePart += 'o Geometry' + totalObjectPassed + '\r';
53 | let mr = meshFilter.host.components.get(Component.MeshRenderer);
54 | if( mr )
55 | {
56 | facePart += 'usemtl ' + exporter_obj.normalizeName(mr.material.name) + '\r';
57 |
58 | // write mat file here
59 | if(materialNames.indexOf( exporter_obj.normalizeName(mr.material.name) ) === -1)
60 | {
61 | mtlFileContent += '\r';
62 | mtlFileContent += 'newmtl ' + exporter_obj.normalizeName(mr.material.name) + '\r';
63 | mtlFileContent += 'Kd 1.00000000000000 1.00000000000000 1.00000000000000\r';
64 | mtlFileContent += 'map_Kd ' + path.basename( mr.material.mainTex.filetoken )+ '\r';
65 | mtlFileContent += 'Ks 1.00000000000000 1.00000000000000 1.00000000000000\r';
66 | mtlFileContent += 'Ns 100\rillum 7\r';
67 |
68 | materialNames.push( exporter_obj.normalizeName(mr.material.name) );
69 | }
70 |
71 | }
72 |
73 | let vbo = meshFilter.mesh.vboForReadback;
74 | let size = meshFilter.mesh.vertexSize / 4;
75 |
76 | let vertCount = vbo.length / size ;
77 | //console.log(vbo.length + ' / ' + size);
78 |
79 | for( let i=0; i < vertCount; ++i) {
80 |
81 | let position = math.vec3.fromValues(meshFilter.mesh.vboForReadback[i * size + 0], meshFilter.mesh.vboForReadback[i * size + 1],meshFilter.mesh.vboForReadback[i * size + 2]);
82 | let normal = math.vec3.fromValues(meshFilter.mesh.vboForReadback[i * size + 3], meshFilter.mesh.vboForReadback[i * size + 4],meshFilter.mesh.vboForReadback[i * size + 5]);
83 | let texcoord = math.vec2.fromValues(meshFilter.mesh.vboForReadback[i * size + 6], meshFilter.mesh.vboForReadback[i * size + 7]);
84 |
85 | let mtx = meshFilter.host.transform.localToWorldMatrix;
86 |
87 | math.vec3.transformMat4( position, position, mtx);
88 | math.vec3.normalize(normal,normal);
89 | let alignNormal = math.vec4.fromValues( normal[0], normal[1], normal[2], 0 );
90 | math.vec4.transformMat4( alignNormal, alignNormal, mtx);
91 | normal = math.vec3.clone( alignNormal );
92 | math.vec3.normalize(normal,normal);
93 |
94 | let vertexstring = 'v ' + position[0]
95 | + ' ' + position[1]
96 | + ' ' + position[2]
97 | + '\r';
98 | let normalstring = 'vn ' + normal[0]
99 | + ' ' + normal[1]
100 | + ' ' + normal[2]
101 | + '\r';
102 | let texcoordstring = 'vt ' + texcoord[0]
103 | + ' ' + (1.0 - texcoord[1])
104 | + '\r';
105 |
106 | vertexPart += vertexstring;
107 | normalPart += normalstring;
108 | texcoordPart += texcoordstring;
109 |
110 | //console.info( vertexstring + normalstring + texcoordstring );
111 | }
112 |
113 |
114 | // idx process
115 | let tristrip = meshFilter.mesh.tristripForReadback;
116 | let trilist = meshFilter.mesh.trilistForReadback;
117 |
118 | if(tristrip)
119 | {
120 | for( let i=0, len = tristrip.length - 2; i < len; ++i)
121 | {
122 | let v0 = tristrip[i] + totalVertexPassed;
123 | let v1 = tristrip[i+1] + totalVertexPassed;
124 | let v2 = tristrip[i+2] + totalVertexPassed;
125 |
126 | if(v0 != v1 && v0 != v2 && v1 != v2)
127 | {
128 | let faceString = 'f ';
129 | if( i % 2 === 0 ) {
130 | faceString = 'f ' + v0 + '/' + v0 + '/' + v0 + ' '
131 | + v1 + '/' + v1 + '/' + v1 + ' '
132 | + v2 + '/' + v2 + '/' + v2 + '\r';
133 | }
134 | else {
135 | faceString = 'f ' + v0 + '/' + v0 + '/' + v0 + ' '
136 | + v2 + '/' + v2 + '/' + v2 + ' '
137 | + v1 + '/' + v1 + '/' + v1 + '\r';
138 | }
139 |
140 | facePart += faceString;
141 | }
142 | }
143 | }
144 |
145 | if(trilist)
146 | {
147 | for( let i=0, len = trilist.length / 3; i < len; ++i)
148 | {
149 | let v0 = trilist[i * 3] + totalVertexPassed;
150 | let v1 = trilist[i * 3 + 1] + totalVertexPassed;
151 | let v2 = trilist[i * 3 + 2] + totalVertexPassed;
152 |
153 | if(v0 != v1 && v0 != v2 && v1 != v2)
154 | {
155 | let faceString = 'f ' + v0 + '/' + v0 + '/' + v0 + ' '
156 | + v1 + '/' + v1 + '/' + v1 + ' '
157 | + v2 + '/' + v2 + '/' + v2 + '\r';
158 |
159 | facePart += faceString;
160 | }
161 | }
162 | }
163 |
164 | totalVertexPassed += vertCount;
165 | totalObjectPassed++;
166 |
167 | }
168 | })
169 |
170 | fs.writeFile(path.join(base_path, 'res', "exported.obj"), headerPart + vertexPart + normalPart + texcoordPart + facePart ,function(err){
171 | if(!err)
172 | console.log("obj writed!");
173 | });
174 |
175 | fs.writeFile(path.join(base_path, 'res', 'exported.mtl'), mtlFileContent ,function(err){
176 | if(!err)
177 | console.log("obj writed!");
178 | });
179 |
180 | rootGameObject.parent = orgParent;
181 | }
--------------------------------------------------------------------------------
/lib/fabricate.js:
--------------------------------------------------------------------------------
1 | function Fabricate(prefab) {
2 | if(!prefab) {
3 | throw new Error("No prefab passed to Fabricate.");
4 | }
5 | const host = Object.create(prefab);
6 | host.components = new Map();
7 | if(prefab.components) {
8 | prefab.components.forEach(component => {
9 | let componentInst;
10 | if(component.prototype && component.prototype.constructor) {
11 | componentInst = new component();
12 | } else {
13 | componentInst = Object.create(component);
14 | }
15 | componentInst.host = host;
16 | host.components.set(component, componentInst);
17 | });
18 | }
19 | return host;
20 | }
21 |
22 | //export default Fabricate;
23 | module.exports = Fabricate;
--------------------------------------------------------------------------------
/lib/gk-acewrap.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by kaimingyi on 2016/11/18.
3 | */
4 | const fs = require('fs-promise');
5 | const Promise = require("bluebird");
6 | const path = require("path");
7 |
8 | class AceEditorWindow {
9 | constructor( elementId )
10 | {
11 | this.elementToken = elementId;
12 |
13 | {
14 | let container = document.getElementById(this.elementToken);
15 | let title = container.previousElementSibling;
16 | if(title === null)
17 | {
18 | title = container.nextElementSibling;
19 | }
20 | if(title !== null)
21 | {
22 | this.elementTitle = title;
23 | }
24 | }
25 |
26 | this.editor = ace.edit(elementId);
27 | this.editor.setTheme('ace/theme/twilight');
28 | let GLSLMode = ace.require("ace/mode/glsl").Mode;
29 | this.editor.session.setMode(new GLSLMode());
30 | this.callback = null;
31 | this.autoUpdate = true;
32 |
33 | this.editingFiletoken = "";
34 |
35 | let ref = this;
36 |
37 |
38 | this.loadCoroutine = Promise.coroutine(function* (url) {
39 | let source = yield fs.readFile(url);
40 | if (source === null) {
41 | console.warn('error : ' + err);
42 | return;
43 | }
44 | let text = source.toString();
45 | ref.editor.setValue(text);
46 | ref.editor.clearSelection();
47 |
48 | ref.elementTitle.textContent = path.basename(url);
49 |
50 | });
51 |
52 | this.saveCoroutine = Promise.coroutine(function* (url) {
53 | yield fs.writeFile(url, ref.editor.getValue());
54 | });
55 |
56 | // intereaction intialize
57 |
58 | // change
59 |
60 | this.editor.getSession().on('change', function(e) {
61 | let text = ref.editor.getValue();
62 | if(ref.callback != null)
63 | {
64 | ref.callback(text);
65 | }
66 | ref.elementTitle.className = 'title-bar-modify';
67 | });
68 |
69 | this.editor.commands.addCommand({
70 | name: 'save to',
71 | bindKey: {win: 'Ctrl-S', mac: 'Command-S'},
72 | exec: function(editor) {
73 | ref.saveFile();
74 | },
75 | readOnly: true // false if this command should not apply in readOnly mode
76 | });
77 |
78 |
79 | // drop
80 | let holder = document.getElementById(elementId);
81 | holder.ondrop = function( ev ) {
82 |
83 | ev.preventDefault();
84 | var filetoken = ev.dataTransfer.getData("restoken");
85 |
86 | let type = 0;
87 | let resobj = resMgr.gResmgr.get_res(filetoken);
88 | if( resobj !== null )
89 | {
90 | type = resobj.get_type();
91 |
92 | if(type === resMgr.RESTYPE.TEXT)
93 | {
94 | // save and load
95 |
96 | // save
97 | ref.saveFile();
98 |
99 | // load coroutine
100 | ref.loadFile(resobj.filetoken);
101 | }
102 | }
103 | }
104 |
105 | holder.ondragover = function (ev) {
106 | ev.preventDefault();
107 | }
108 | }
109 |
110 | loadFile(filetoken)
111 | {
112 | this.editingFiletoken = filetoken;
113 | this.loadCoroutine(this.editingFiletoken);
114 | }
115 |
116 | saveFile() {
117 | this.saveCoroutine(this.editingFiletoken);
118 | this.elementTitle.className = 'title-bar-saved';
119 | };
120 |
121 |
122 | autoUpdate( isAuto )
123 | {
124 |
125 | }
126 |
127 | setChangeCallback( callbackfun )
128 | {
129 | this.callback = callbackfun;
130 | }
131 | }
132 |
133 | module.exports = { AceEditorWindow };
--------------------------------------------------------------------------------
/lib/gk-component.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by kaimingyi on 2016/11/18.
3 | */
4 | const math = require("gl-matrix");
5 | const mathext = require('./util/gl-matrix-extension.js');
6 | const gkCore = window.gkCore;
7 |
8 | class Component {
9 | constructor() {
10 | this._host = null;
11 | }
12 |
13 | get host()
14 | {
15 | return this._host;
16 | }
17 |
18 | set host( target )
19 | {
20 | this._host = target;
21 | this.onStart();
22 | }
23 |
24 | onStart() {
25 |
26 | }
27 |
28 | onUpdate() {
29 | //console.info( this );
30 | }
31 |
32 | onRender() {
33 |
34 | }
35 | }
36 |
37 | class Transform extends Component {
38 | constructor() {
39 | super();
40 |
41 | this._position = math.vec3.fromValues(0,0,0);
42 | this._rotation = math.quat.identity(math.quat.create());
43 | this._scale = math.vec3.fromValues(1,1,1);
44 |
45 | this._dirty = true;
46 |
47 | this._localToWorldMatrx = math.mat4.identity(math.mat4.create());
48 |
49 |
50 | this._parent = null;
51 | this.children = new Set();
52 |
53 |
54 | this._worldposition = math.vec3.create();
55 | this._worldrotation = math.quat.create();
56 | }
57 |
58 | _markDirty()
59 | {
60 | this._dirtyComp = true;
61 | this._dirty = true;
62 |
63 | // all children mark dirty
64 | this.children.forEach( child => {
65 | child._markDirty();
66 | } );
67 | }
68 |
69 | get parent()
70 | {
71 | return this._parent;
72 | }
73 |
74 | set parent( target )
75 | {
76 | // detach
77 |
78 | if(this._parent !== null) {
79 | this._parent._removeChild(this);
80 | }
81 |
82 | this._parent = target;
83 |
84 | if( target instanceof Transform)
85 | {
86 | // attach
87 | this._parent._addChild(this);
88 | }
89 |
90 | this._markDirty();
91 |
92 | }
93 |
94 | _addChild( target )
95 | {
96 | this.children.add( target );
97 | }
98 |
99 | _removeChild( target )
100 | {
101 | if(this.children.has( target )) {
102 | this.children.delete(target);
103 | }
104 | }
105 |
106 | CheckCompDirty() {
107 | if (this._dirtyComp === true) {
108 | if(this._parent !== null)
109 | {
110 | this._worldposition = math.vec3.add(math.vec3.create(), this._parent.position, math.vec3.transformQuat(
111 | math.vec3.create(), this.localPosition, this._parent.rotation));
112 |
113 | this._worldrotation = math.quat.mul(math.quat.create(), this._parent.rotation, this.localRotation);
114 | }
115 | else
116 | {
117 | this._worldposition = this.localPosition;
118 | this._worldrotation = this.localRotation;
119 | }
120 | this._dirtyComp = false;
121 | }
122 | }
123 |
124 | get position() {
125 | if( this._parent === null )
126 | {
127 | return this._position;
128 | }
129 | this.CheckCompDirty();
130 | return this._worldposition;
131 | }
132 |
133 | get rotation() {
134 | if( this._parent === null )
135 | {
136 | return this._rotation;
137 | }
138 | this.CheckCompDirty();
139 | return this._worldrotation;
140 | }
141 |
142 | set position(value) {
143 | this._worldposition = value;
144 | if( this._parent !== null)
145 | {
146 | let distance = math.vec3.sub(math.vec3.create(), this._worldposition, this._parent.position);
147 | let invRotParent = math.quat.invert( math.quat.create(), this._parent.rotation );
148 | this.localPosition = math.vec3.transformQuat( math.vec3.create(), distance, invRotParent );
149 | }
150 | else
151 | {
152 | this.localPosition = this._worldposition;
153 | }
154 | }
155 |
156 | set rotation(value) {
157 | this._worldrotation = value;
158 | if( this._parent !== null) {
159 | let invRotParent = math.quat.invert(math.quat.create(), this._parent.rotation);
160 | this.localRotation = math.quat.mul(math.quat.create(), invRotParent, this._worldrotation);
161 | }
162 | else
163 | {
164 | this.localRotation = this._worldrotation;
165 | }
166 | }
167 |
168 | // native propery setter/getter
169 | get localPosition() {
170 | return this._position;
171 | }
172 | set localPosition(value) {
173 | this._markDirty();
174 | this._position = value;
175 | }
176 |
177 | get localRotation() {
178 | return this._rotation;
179 | }
180 | set localRotation(value) {
181 | this._markDirty();
182 | this._rotation = value;
183 | }
184 |
185 | get localScale() {
186 | return this._scale;
187 | }
188 | set localScale(value) {
189 | this._markDirty();
190 | this._scale = value;
191 | }
192 |
193 | // matrix access
194 | get localToWorldMatrix() {
195 | if(this._dirty)
196 | {
197 | this._dirty = false;
198 |
199 | let childmatrix = math.mat4.fromRotationTranslationScale(math.mat4.create(), this._rotation, this._position, this._scale );
200 |
201 | if(this._parent !== null)
202 | {
203 | this._localToWorldMatrx = math.mat4.mul( this._localToWorldMatrx, this._parent.localToWorldMatrix, childmatrix );
204 | }
205 | else
206 | {
207 | this._localToWorldMatrx = childmatrix;
208 | }
209 | }
210 | return this._localToWorldMatrx;
211 | }
212 |
213 | get forward() {
214 | // TODO
215 | return math.vec3.transformQuat(math.vec3.create(), math.vec3.fromValues(0,0,1), this.rotation );
216 | }
217 |
218 | get up() {
219 | // TODO
220 | return math.vec3.transformQuat(math.vec3.create(), math.vec3.fromValues(0,1,0), this.rotation );
221 | }
222 |
223 | get left() {
224 | // TODO
225 | return math.vec3.transformQuat(math.vec3.create(), math.vec3.fromValues(1,0,0), this.rotation );
226 | }
227 |
228 | // other method
229 | lookAt( target ) {
230 |
231 | // rebuild the quat axes with forward and up
232 | let forward = math.vec3.sub(math.vec3.create(), target, this.position);
233 | forward = math.vec3.normalize(forward, forward);
234 |
235 | let up = math.vec3.fromValues(0,1,0);
236 |
237 | let left = math.vec3.cross(math.vec3.create(), up, forward );
238 | left = math.vec3.normalize(left,left);
239 |
240 | up = math.vec3.cross(math.vec3.create(), forward, left );
241 | up = math.vec3.normalize(up, up);
242 |
243 | let matr = math.mat3.create();
244 | matr[0] = -left[0];
245 | matr[1] = -left[1];
246 | matr[2] = -left[2];
247 |
248 | matr[3] = up[0];
249 | matr[4] = up[1];
250 | matr[5] = up[2];
251 |
252 | matr[6] = -forward[0];
253 | matr[7] = -forward[1];
254 | matr[8] = -forward[2];
255 |
256 | this.rotation = math.quat.fromMat3(math.quat.create(), matr);
257 | }
258 |
259 | /**
260 | * Transforms in localspace
261 | *
262 | * @param {vec3} vector
263 | */
264 | translateLocal( vec ) {
265 | let trans = math.vec3.transformQuat( math.vec3.create(), vec, this.localRotation );
266 | this.localPosition = math.vec3.add( this.localPosition, this.localPosition, trans );
267 | }
268 |
269 | /**
270 | * Transforms in worldspace
271 | *
272 | * @param {vec3} vector
273 | */
274 | translateWorld( vec ) {
275 | let trans = math.vec3.transformQuat( math.vec3.create(), vec, this.rotation );
276 | this.position = math.vec3.add( math.vec3.create(), this.position, trans );
277 | }
278 |
279 | getComponent( comp ) {
280 | let returnArray = [];
281 |
282 | let component = this.host.components.get( comp );
283 | if(component)
284 | {
285 | returnArray.push(component);
286 | }
287 |
288 | this.children.forEach( child => {
289 | returnArray = returnArray.concat( child.getComponent( comp ) );
290 | });
291 |
292 | return returnArray;
293 | }
294 |
295 | onStart() {
296 | this.host.transform = this;
297 | }
298 | }
299 |
300 | class MeshFilter extends Component {
301 | constructor() {
302 | super();
303 | this._mesh = null;
304 |
305 | this._aabb = mathext.aabb.create();
306 | }
307 |
308 | set mesh(value) {
309 | this._mesh = value;
310 |
311 | // for each vertice in mesh
312 | // compare with _lbb & _rtf
313 | let vbo = this._mesh.vboForReadback;
314 | let size = this._mesh.vertexSize / 4;
315 |
316 | let vertCount = vbo.length / size ;
317 | //console.log(vbo.length + ' / ' + size);
318 |
319 | for( let i=0; i < vertCount; ++i) {
320 | let position = math.vec3.fromValues(this._mesh.vboForReadback[i * size + 0], this._mesh.vboForReadback[i * size + 1], this._mesh.vboForReadback[i * size + 2]);
321 |
322 | mathext.aabb.addPoint( this._aabb, position);
323 | }
324 | // complete
325 | }
326 |
327 | get mesh() {
328 | return this._mesh;
329 | }
330 | }
331 |
332 | class MeshRenderer extends Component {
333 | constructor() {
334 | super();
335 | this.material = null;
336 | }
337 |
338 | get bounds() {
339 |
340 | let mf = this.host.components.get(MeshFilter);
341 |
342 | // transform mesh bounds to world,
343 | let tmpaabb = mathext.aabb.create();
344 | mathext.aabb.mergeOBB( tmpaabb, mf._aabb, this.host.transform.localToWorldMatrix );
345 |
346 | // return the new bounds
347 | return tmpaabb;
348 | }
349 | }
350 |
351 | class Camera extends Component {
352 | constructor() {
353 | super();
354 | }
355 |
356 | onUpdate() {
357 | super.onUpdate();
358 | }
359 |
360 | onRender() {
361 | // prepare render queue
362 | let queue = gkCore.renderer.getOrCreateRenderQueue(0);
363 |
364 | // send per queue parameter set to queue
365 | queue.setupCamera( this );
366 |
367 | // push target mr to renderqueue
368 | let mrs = gkCore.sceneMgr.getMeshRenderers();
369 | mrs.forEach( mr => {
370 | // doing culling here
371 | queue.addRenderer( mr );
372 | });
373 | }
374 | }
375 |
376 | class Light extends Component {
377 | constructor() {
378 | super();
379 |
380 | this.intensity = 1.0;
381 | }
382 |
383 | onUpdate() {
384 | super.onUpdate();
385 | }
386 |
387 | onRender() {
388 | // TODO: add to everyqueue
389 | // prepare render queue
390 | let queue = gkCore.renderer.getOrCreateRenderQueue(0);
391 |
392 | // send per queue parameter set to queue
393 | queue.setupLight( this );
394 | }
395 | }
396 |
397 | module.exports = {Component, Transform, MeshFilter, MeshRenderer, Camera, Light};
398 |
399 |
--------------------------------------------------------------------------------
/lib/gk-core.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by gameKnife on 2016/12/5.
3 | */
4 | window.gkCore = exports;
5 |
6 | exports.Component = require('./gk-component.js');
7 | exports.GameObject = require('./gk-gameobject.js');
8 | const Renderer = require('./gk-renderer.js');
9 | exports.renderer = new Renderer();
10 | const SceneMgr = require('./gk-scenemgr.js');
11 | exports.sceneMgr = new SceneMgr();
12 | exports.math = require('gl-matrix');
13 | exports.mouse = require("./gk-mouseorbit.js");
14 | const BaseResMgr = require("./gk-resmgr").BaseResMgr;
15 | exports.resMgr = new BaseResMgr();
16 | exports.mathext = require("./util/gl-matrix-extension.js");
--------------------------------------------------------------------------------
/lib/gk-fixedshader.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by gameKnife on 2016/12/1.
3 | */
4 |
5 | var quadvsp = "attribute vec3 position;\
6 | varying vec2 vTexCoord;\
7 | void main(){\
8 | vTexCoord = ((position + 1.0) * 0.5).xy;\
9 | gl_Position = vec4(position, 1.0);\
10 | }\
11 | ";
12 |
13 | var noisefsp = "precision mediump float;\
14 | uniform sampler2D texture;\
15 | varying vec2 vTexCoord;\
16 | uniform float _TIME;\
17 | float snoise(vec2 co){\
18 | return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);\
19 | }\
20 | void main(){\
21 | float noise = fract(_TIME);\
22 | vec4 samplerColor = vec4(0.3,0.3,0.3,1.0);\
23 | float vignette = 1.0 - length((vTexCoord.xy - vec2(0.5,0.5)) * vec2(1.5, 1.5));\
24 | samplerColor *= vignette;\
25 | samplerColor += snoise(vTexCoord.xy + vec2(noise,noise)) * 0.04;\
26 | gl_FragColor = samplerColor;\
27 | }\
28 | ";
29 |
30 | var quadfsp = "precision highp float;\
31 | uniform sampler2D texture;\
32 | varying vec2 vTexCoord;\
33 | float DecodeFloatRGBA(vec4 enc){\
34 | vec4 kDecodeDot = vec4(1.0,1.0/255.0,1.0/65025.0,1.0/160581375.0);\
35 | return dot(enc, kDecodeDot);\
36 | }\
37 | void main(){\
38 | vec4 samplerColor = texture2D(texture, vTexCoord.xy);\
39 | gl_FragColor = samplerColor;\
40 | }\
41 | ";
42 |
43 | var shadowvsp = "attribute vec2 texcoord;\
44 | attribute vec3 normal;\
45 | attribute vec3 position;\
46 | uniform mat4 _MVP;\
47 | uniform mat4 _M2W;\
48 | \
49 | varying vec2 vTexCoord;\
50 | varying vec2 zOffset;\
51 | \
52 | void main(){\
53 | vTexCoord = texcoord;\
54 | gl_Position = _MVP * vec4(position, 1.0);\
55 | zOffset = gl_Position.zw;\
56 | }";
57 | var shadowfsp = "precision highp float;\
58 | uniform sampler2D _MainTex;\
59 | uniform sampler2D _AlphaTex;\
60 | varying vec2 vTexCoord;\
61 | varying vec2 zOffset;\
62 | \
63 | \
64 | float frac(float t)\
65 | {\
66 | return t - floor(t);\
67 | }\
68 | vec4 frac(vec4 t)\
69 | {\
70 | return t - floor(t);\
71 | }\
72 | vec4 EncodeFloatRGBA( float v )\
73 | {\
74 | vec4 kEncodeMul = vec4(1.0, 255.0, 65025.0, 160581375.0);\
75 | float kEncodeBit = 1.0/255.0;\
76 | vec4 enc = kEncodeMul * vec4(v,v,v,v);\
77 | enc = frac(enc);\
78 | enc -= enc.yzww * kEncodeBit;\
79 | return enc;\
80 | }\
81 | void main(){\
82 | vec4 encoded = EncodeFloatRGBA(zOffset.x / zOffset.y);\
83 | vec4 samplerColor = texture2D(_MainTex, vTexCoord.xy);\
84 | vec4 alphaSamplerColor = texture2D(_AlphaTex, vTexCoord.xy);\
85 | if(samplerColor.a < 0.05) discard;\
86 | gl_FragColor = encoded;\
87 | }";
88 |
89 | var simpleshadowvsp = "attribute vec2 texcoord;\
90 | attribute vec3 normal;\
91 | attribute vec3 position;\
92 | uniform mat4 _MVP;\
93 | uniform mat4 _M2W;\
94 | \
95 | varying vec2 vTexCoord;\
96 | \
97 | void main(){\
98 | vTexCoord = texcoord;\
99 | gl_Position = _MVP * vec4(position, 1.0);\
100 | }";
101 | var simpleshadowfsp = "precision highp float;\
102 | uniform sampler2D _MainTex;\
103 | uniform sampler2D _AlphaTex;\
104 | varying vec2 vTexCoord;\
105 | void main(){\
106 | vec4 alphaSamplerColor = texture2D(_AlphaTex, vTexCoord.xy);\
107 | if(alphaSamplerColor.a < 0.05) discard;\
108 | gl_FragColor = vec4(1.0,1.0,1.0,1.0);\
109 | }";
110 |
111 | var simplezpassvsp = "attribute vec2 texcoord;\
112 | attribute vec3 normal;\
113 | attribute vec3 position;\
114 | uniform mat4 _MVP;\
115 | uniform mat4 _M2W;\
116 | uniform mat4 _MV;\
117 | \
118 | varying vec2 vTexCoord;\
119 | varying vec4 vNormal;\
120 | \
121 | void main(){\
122 | vTexCoord = texcoord;\
123 | vNormal = _MV * vec4(normal, 0.0);\
124 | gl_Position = _MVP * vec4(position, 1.0);\
125 | }";
126 | var simplezpassfsp = "precision highp float;\
127 | uniform sampler2D _MainTex;\
128 | uniform sampler2D _AlphaTex;\
129 | varying vec2 vTexCoord;\
130 | varying vec4 vNormal;\
131 | void main(){\
132 | vec4 alphaSamplerColor = texture2D(_AlphaTex, vTexCoord.xy);\
133 | if(alphaSamplerColor.a < 0.05) discard;\
134 | gl_FragColor = vec4(vNormal.xyz * 0.5 + 0.5,1.0);\
135 | }";
136 |
137 | var ssaovsp = "attribute vec3 position;\
138 | varying vec2 vTexCoord;\
139 | void main(){\
140 | vTexCoord = ((position + 1.0) * 0.5).xy;\
141 | gl_Position = vec4(position, 1.0);\
142 | }\
143 | ";
144 |
145 | var ssaofsp = "precision mediump float;\
146 | uniform sampler2D _GlobalNormalMap;\
147 | uniform sampler2D _GlobalDepthMap;\
148 | uniform float _TIME;\
149 | varying vec2 vTexCoord;\
150 | const vec2 sobel1 = vec2(0,-1);\
151 | const vec2 sobel2 = vec2(-1.41,1.41);\
152 | const vec2 sobel3 = vec2(1.41,1.41);\
153 | const vec2 sobel4 = vec2(0,1);\
154 | const vec2 sobel5 = vec2(1.41,-1.41);\
155 | const vec2 sobel6 = vec2(-1.41,-1.41);\
156 | float DecodeFloatRGBA(vec4 enc){\
157 | vec4 kDecodeDot = vec4(1.0,1.0/255.0,1.0/65025.0,1.0/160581375.0);\
158 | return dot(enc, kDecodeDot);\
159 | }\
160 | float snoise(vec2 co){\
161 | return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);\
162 | }\
163 | float CalcAccumNormal(){\
164 | vec3 acc1 = vec3(0,0,0);\
165 | float noise = fract(_TIME);\
166 | float noiseMap = snoise(vTexCoord.xy + vec2(noise,noise)) * 1.0;\
167 | vec2 normal = vec2(noiseMap, 1.0 - noiseMap);\
168 | normal = normalize(normal);\
169 | vec2 s1 = reflect(normal, sobel1);\
170 | vec2 s2 = reflect(normal, sobel2);\
171 | vec2 s3 = reflect(normal, sobel3);\
172 | vec2 s4 = reflect(normal, sobel4);\
173 | vec2 s5 = reflect(normal, sobel5);\
174 | vec2 s6 = reflect(normal, sobel6);\
175 | \
176 | acc1.x = dot(vec3(s1,0.0), texture2D(_GlobalNormalMap, vTexCoord.xy + s1 * -0.003).xyz * 2.0 - 1.0);\
177 | acc1.y = dot(vec3(s2,0.0), texture2D(_GlobalNormalMap, vTexCoord.xy + s2 * -0.003).xyz * 2.0 - 1.0);\
178 | acc1.z = dot(vec3(s3,0.0), texture2D(_GlobalNormalMap, vTexCoord.xy + s3 * -0.003).xyz * 2.0 - 1.0);\
179 | acc1 = vec3(1,1,1) - min(acc1, vec3(1,1,1));\
180 | \
181 | vec3 acc2 = vec3(0,0,0);\
182 | acc2.x = dot(vec3(s4,0.0), texture2D(_GlobalNormalMap, vTexCoord.xy + s4 * -0.006).xyz * 2.0 - 1.0);\
183 | acc2.y = dot(vec3(s5,0.0), texture2D(_GlobalNormalMap, vTexCoord.xy + s5 * -0.006).xyz * 2.0 - 1.0);\
184 | acc2.z = dot(vec3(s6,0.0), texture2D(_GlobalNormalMap, vTexCoord.xy + s6 * -0.006).xyz * 2.0 - 1.0);\
185 | acc2 = vec3(1,1,1) - min(acc2, vec3(1,1,1));\
186 | \
187 | return dot(acc1, vec3(0.15,0.15,0.15)) + dot(acc2, vec3(0.15,0.15,0.15));\
188 | }\
189 | void main(){\
190 | float samplerColor = CalcAccumNormal();\
191 | gl_FragColor = vec4(samplerColor, samplerColor, samplerColor, 1.0);\
192 | }\
193 | ";
194 |
195 | module.exports = { quadvsp, noisefsp, quadfsp,
196 | shadowvsp, shadowfsp,
197 | simpleshadowvsp, simpleshadowfsp,
198 | simplezpassvsp, simplezpassfsp,
199 | ssaovsp, ssaofsp};
--------------------------------------------------------------------------------
/lib/gk-framework.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by gameKnife on 2016/12/1.
3 | */
4 | 'use strict';
5 | const gTimer = require("./gk-timer.js");
6 | const Fabricate = require("./fabricate.js");
7 |
8 | const gkCore = require("./gk-core.js");
9 | const acEditor = require('./gk-acewrap');
10 | const glw = require("./gk-glwrap");
11 |
12 | class Framework
13 | {
14 | constructor() {
15 |
16 | }
17 |
18 | init() {
19 |
20 | }
21 |
22 | update() {
23 |
24 | }
25 |
26 | destroy() {
27 |
28 | }
29 | }
30 |
31 | class ShaderMonkiFramework extends Framework
32 | {
33 | constructor() {
34 | super();
35 |
36 | this.renderer = null;
37 | this.sceneMgr = null;
38 |
39 | this.mainCamera = null;
40 |
41 |
42 | this.modelrotation = 0;
43 | this.camerarotationx = 0;
44 | this.camerarotationy = 0;
45 |
46 | this.camerapanx = 0;
47 | this.camerapany = 0;
48 |
49 | this.autoRotate = false;
50 |
51 | this.vsp_source = null;
52 | this.fsp_source = null;
53 |
54 | this.holderGameObject = null;
55 |
56 | this.cameraCenter = gkCore.math.vec3.create();
57 | this.cameraRadius = 500.0;
58 | }
59 |
60 | init() {
61 | gTimer.init();
62 |
63 | this.renderer = gkCore.renderer;
64 | this.renderer.init();
65 |
66 | this.sceneMgr = gkCore.sceneMgr;
67 | this.sceneMgr.init();
68 |
69 | this.mainCamera = Fabricate(gkCore.GameObject.Camera);
70 | this.mainCamera.transform.parent = this.sceneMgr.getSceneRoot().transform;
71 |
72 | // temporary camera transform setting
73 | this.mainCamera.transform.position = gkCore.math.vec3.fromValues(0,15,50);
74 | this.mainCamera.transform.lookAt( gkCore.math.vec3.fromValues(0,0,0) );
75 |
76 | this.mainLight = Fabricate(gkCore.GameObject.Light);
77 | this.mainLight.transform.position = gkCore.math.vec3.fromValues(-1000,1500,1000);
78 | this.mainLight.transform.lookAt( gkCore.math.vec3.fromValues(0,0,0) );
79 | this.mainLight.transform.parent = this.sceneMgr.getSceneRoot().transform;
80 |
81 | // create editor
82 | let refthis = this;
83 |
84 | let vseditor = new acEditor.AceEditorWindow("vs-editor-panel");
85 | vseditor.setChangeCallback( function(str) {
86 | refthis.vsp_source = str;
87 | refthis.updateShader();
88 | } )
89 |
90 | let fseditor = new acEditor.AceEditorWindow("fs-editor-panel");
91 | fseditor.setChangeCallback( function(str) {
92 | refthis.fsp_source = str;
93 | refthis.updateShader();
94 | } );
95 |
96 | // default assets loading
97 | vseditor.loadFile('res/shader/base_vs.glsl');
98 | fseditor.loadFile('res/shader/base_fs.glsl');
99 |
100 | }
101 |
102 | update() {
103 | gTimer.update();
104 |
105 | // update mouse
106 | let relDelta = gkCore.mouse.frameUpdate();
107 |
108 | if(gkCore.mouse.moveType === gkCore.mouse.HOLDLEFT)
109 | {
110 | this.camerarotationy -= relDelta.y * 0.005;
111 | this.camerarotationx -= relDelta.x * 0.005;
112 | }
113 | else if(gkCore.mouse.moveType === gkCore.mouse.HOLDMIDDLE)
114 | {
115 | this.camerapany += relDelta.y * (0.002 * this.cameraRadius);
116 | this.camerapanx -= relDelta.x * (0.002 * this.cameraRadius);
117 | }
118 |
119 | this.cameraRadius *= (1.0 - relDelta.z * 0.25);
120 |
121 | let rot = gkCore.math.quat.create();
122 | gkCore.math.quat.rotateY(rot, rot, this.camerarotationx);
123 | gkCore.math.quat.rotateX(rot, rot, this.camerarotationy);
124 | this.mainCamera.transform.rotation = rot;
125 | this.mainCamera.transform.position = this.cameraCenter;
126 | this.mainCamera.transform.translateLocal(gkCore.math.vec3.fromValues(this.camerapanx,this.camerapany,0));
127 | this.mainCamera.transform.translateLocal(gkCore.math.vec3.fromValues(0,0,this.cameraRadius));
128 |
129 | this.sceneMgr.update();
130 | this.renderer.render();
131 | }
132 |
133 | destory() {
134 |
135 | }
136 |
137 | updateShader() {
138 | if(this.vsp_source !== null && this.fsp_source !== null && this.vsp_source !== "" && this.fsp_source !== "") {
139 | let program = glw.createProgramObject(this.vsp_source, this.fsp_source);
140 | this.renderer.overrideProgram = program;
141 | }
142 | }
143 |
144 | bindShowObj( gameObject) {
145 |
146 | // load a mesh into gameobject struct
147 | if(this.holderGameObject !== null)
148 | {
149 | this.holderGameObject.transform.parent = null;
150 | }
151 | // bind it to scene root
152 | gameObject.transform.parent = gkCore.sceneMgr.getSceneRoot().transform;
153 | this.holderGameObject = gameObject;
154 |
155 | // camera target reset
156 | let mrs = gameObject.transform.getComponent( gkCore.Component.MeshRenderer );
157 | let aabbTotal = gkCore.mathext.aabb.create();
158 | mrs.forEach( meshRenderer => {
159 | let aabb = meshRenderer.bounds;
160 | gkCore.mathext.aabb.mergeAABB(aabbTotal, aabb);
161 | });
162 |
163 | this.cameraCenter = gkCore.mathext.aabb.center(gkCore.math.vec3.create(), aabbTotal);
164 | this.cameraRadius = gkCore.mathext.aabb.radius(aabbTotal) * 1.5;
165 | this.camerapanx = 0;
166 | this.camerapany = 0;
167 |
168 | //console.info(aabbTotal);
169 | if( isNaN( this.cameraCenter[0] ))
170 | {
171 | this.cameraCenter = gkCore.math.vec3.create();
172 | this.cameraRadius = 100.0;
173 | }
174 |
175 | console.info(this.cameraCenter);
176 | console.log(this.cameraRadius);
177 | }
178 | }
179 |
180 | module.exports = ShaderMonkiFramework;
--------------------------------------------------------------------------------
/lib/gk-gameobject.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by kaimingyi on 2016/11/18.
3 | */
4 | const Component = require('./gk-component.js');
5 |
6 | const Base = {
7 | name: "GameObject",
8 | transform: null,
9 | components: [Component.Transform]
10 | }
11 |
12 | const Camera = {
13 | name: "Camera",
14 | transform: null,
15 | components: [Component.Transform, Component.Camera]
16 | }
17 |
18 | const StaticMesh = {
19 | name: "StaticMesh",
20 | transform: null,
21 | components: [Component.Transform, Component.MeshFilter, Component.MeshRenderer]
22 | }
23 |
24 | const Light = {
25 | name: "Light",
26 | transform: null,
27 | components: [Component.Transform, Component.Light]
28 | }
29 |
30 | module.exports = {Base, Camera, StaticMesh, Light};
--------------------------------------------------------------------------------
/lib/gk-glwrap.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | const logger = require('./gk-logger.js');
3 | const math = require('gl-matrix');
4 |
5 | var glw = glw || {};
6 | module.exports = glw;
7 |
8 | // const
9 | glw.VERSION = '0.1';
10 | glw.PI2 = 6.28318530717958647692528676655900576;
11 | glw.PI = 3.14159265358979323846264338327950288;
12 | glw.PIH = 1.57079632679489661923132169163975144;
13 | glw.PIH2 = 0.78539816339744830961566084581987572;
14 |
15 | glw.VERTEX_LAYOUT_P = 0;
16 | glw.VERTEX_LAYOUT_N = 1;
17 | glw.VERTEX_LAYOUT_T0 = 2;
18 | glw.VERTEX_LAYOUT_T1 = 3;
19 | glw.VERTEX_LAYOUT_C = 4;
20 |
21 | // global member
22 | glw.ready = false;
23 | glw.canvas = null;
24 | glw.gl = null;
25 | glw.curr_program = null;
26 | glw.nullTexture = null;
27 | glw.glext_depth_texture = false;
28 |
29 | // public interface
30 |
31 | // initialize webgl
32 | glw.initGL = function(canvasId, options){
33 | this.ready = false;
34 | this.canvas = null;
35 | this.gl = null;
36 |
37 | if(Object.prototype.toString.call(canvasId) === '[object String]'){
38 | this.canvas = document.getElementById(canvasId);
39 | }else{
40 | if(Object.prototype.toString.call(canvasId) === '[object HTMLCanvasElement]'){
41 | this.canvas = canvasId;
42 | }
43 | }
44 |
45 | var opt = options || {};
46 | if(this.canvas == null){return false;}
47 | this.gl = this.canvas.getContext('webgl', opt)
48 | || this.canvas.getContext('experimental-webgl', opt);
49 |
50 | if(this.gl != null){
51 | this.ready = true;
52 | }
53 |
54 | let checkerData = new Uint8Array(16);
55 | checkerData[0] = 0;
56 | checkerData[1] = 0;
57 | checkerData[2] = 0;
58 | checkerData[3] = 0;
59 |
60 | glw.nullTexture = glw._create_procedural_texture(2,2,checkerData);
61 | let ext = this.gl.getExtension("WEBGL_depth_texture");
62 | glw.glext_depth_texture = (ext !== undefined);
63 |
64 | return this.ready;
65 | };
66 |
67 | // glclear
68 | glw.clear = function(color, depth, stencil){
69 | var gl = this.gl;
70 | var flg = gl.COLOR_BUFFER_BIT;
71 | gl.clearColor(color[0], color[1], color[2], color[3]);
72 | if(depth != null){
73 | gl.clearDepth(depth);
74 | flg = flg | gl.DEPTH_BUFFER_BIT;
75 | }
76 | if(stencil != null){
77 | gl.clearStencil(stencil);
78 | flg = flg | gl.STENCIL_BUFFER_BIT;
79 | }
80 | gl.clear(flg);
81 | };
82 |
83 | // glviewport
84 | glw.viewport = function(x, y, width, height){
85 | var X = x || 0;
86 | var Y = y || 0;
87 | var w = width || window.innerWidth;
88 | var h = height || window.innerHeight;
89 | this.gl.viewport(X, Y, w, h);
90 | };
91 |
92 | glw.set_uniform1f = function(name, fvalue)
93 | {
94 | if(this.curr_program != null) {
95 | var loc = this.gl.getUniformLocation(this.curr_program, name);
96 | if (loc != -1) {
97 | this.gl.uniform1f(loc, fvalue);
98 | }
99 | }
100 | };
101 |
102 | glw.set_uniform4f = function (name, fvalue)
103 | {
104 | if(this.curr_program != null)
105 | {
106 | var loc = this.gl.getUniformLocation(this.curr_program, name);
107 | if (loc != -1) {
108 | this.gl.uniform4f(loc, fvalue[0], fvalue[1], fvalue[2], fvalue[3]);
109 | }
110 | }
111 | };
112 |
113 | glw.set_uniform4x4fv = function(name, fvalue)
114 | {
115 | if(this.curr_program != null) {
116 | var loc = this.gl.getUniformLocation(this.curr_program, name);
117 | if (loc != -1) {
118 | this.gl.uniformMatrix4fv(loc, false, fvalue);
119 | }
120 | }
121 | };
122 |
123 |
124 | glw.bind_texture = function( texobj, unit )
125 | {
126 | let targetTO = texobj;
127 | if(texobj === null) {
128 | targetTO = glw.nullTexture;
129 | }
130 |
131 | if(this.curr_program != null)
132 | {
133 | var loc = this.gl.getUniformLocation(this.curr_program, '_MainTex');
134 | if (loc != -1) {
135 | this.gl.uniform1i(loc, 0);
136 | }
137 | loc = this.gl.getUniformLocation(this.curr_program, '_AlphaTex');
138 | if (loc != -1) {
139 | this.gl.uniform1i(loc, 1);
140 | }
141 | loc = this.gl.getUniformLocation(this.curr_program, '_GlobalNormalMap');
142 | if (loc != -1) {
143 | this.gl.uniform1i(loc, 5);
144 | }
145 | loc = this.gl.getUniformLocation(this.curr_program, '_GlobalOccMap');
146 | if (loc != -1) {
147 | this.gl.uniform1i(loc, 5);
148 | }
149 | loc = this.gl.getUniformLocation(this.curr_program, '_GlobalDepthMap');
150 | if (loc != -1) {
151 | this.gl.uniform1i(loc, 6);
152 | }
153 | loc = this.gl.getUniformLocation(this.curr_program, '_GlobalShadowMap');
154 | if (loc != -1) {
155 | this.gl.uniform1i(loc, 7);
156 | }
157 |
158 |
159 | }
160 |
161 | {
162 | this.gl.activeTexture(33984 + unit);
163 | this.gl.bindTexture(this.gl.TEXTURE_2D, targetTO);
164 | }
165 | };
166 |
167 | /// mesh obj
168 | glw.meshObject = function(webglContext){
169 | this.gl = webglContext;
170 | };
171 |
172 | // construct
173 | glw.createMeshObject = function ( res, vertexLayout ) {
174 |
175 | var newObj = new meshObject(this.gl);
176 |
177 | // res comes single one
178 | let vertexStream = res.vbo;
179 | let indexStream_list = res.ibo.trilist;
180 | let indexStream_strip = res.ibo.tristrip;
181 |
182 | newObj.vboForReadback = vertexStream;
183 | newObj.trilistForReadback = indexStream_list;
184 | newObj.tristripForReadback = indexStream_strip;
185 |
186 | newObj.vbo = glw._create_vbo(vertexStream);
187 | if(indexStream_list)
188 | {
189 | newObj.trilist = glw._create_ibo(indexStream_list);
190 | newObj.indexSize_list = indexStream_list.length;
191 | }
192 | else
193 | {
194 | newObj.indexSize_list = 0;
195 | }
196 | if(indexStream_strip)
197 | {
198 | newObj.tristrip = glw._create_ibo(indexStream_strip);
199 | newObj.indexSize_strip = indexStream_strip.length;
200 | }
201 | else
202 | {
203 | newObj.indexSize_strip = 0;
204 | }
205 |
206 | var size = 0;
207 | if(vertexLayout.indexOf(glw.VERTEX_LAYOUT_P) !== -1 )
208 | {
209 | size += 3 * 4;
210 | }
211 |
212 | if(vertexLayout.indexOf(glw.VERTEX_LAYOUT_N) !== -1 )
213 | {
214 | size += 3 * 4;
215 | }
216 |
217 | if(vertexLayout.indexOf(glw.VERTEX_LAYOUT_T0) !== -1 )
218 | {
219 | size += 2 * 4;
220 | }
221 | newObj.vertexSize = size;
222 | newObj.vertexLayout = vertexLayout;
223 |
224 | // calc bbox
225 | // for( let i=0, len = vertexStream.length / size; i < len; ++i)
226 | // {
227 | // let vertexPos = math.vec3.fromValues( vertexStream[i * size + 0], vertexStream[i * size + 1], vertexStream[i * size + 2]);
228 | // math.vec3.min( newObj.lbb, newObj.lbb, vertexPos );
229 | // math.vec3.max( newObj.rtf, newObj.rtf, vertexPos );
230 | // }
231 |
232 | return newObj;
233 | };
234 |
235 | class meshObject {
236 |
237 | constructor( glcontext ) {
238 | this.gl = glcontext;
239 | this.vbo = null;
240 | this.tristrip = null;
241 | this.trilist = null;
242 | this.vertexSize = null;
243 | this.vertexLayout = null;
244 | this.indexSize_list = 0;
245 | this.indexSize_strip = 0;
246 | this.lbb = math.vec3.fromValues(999999,999999,999999);
247 | this.rtf = math.vec3.fromValues(-999999,-999999,-999999);
248 |
249 | this.vboForReadback = null;
250 | this.trilistForReadback = null;
251 | this.tristripForReadback = null;
252 | }
253 |
254 | bind() {
255 | var offset = 0;
256 |
257 | if(this.vertexLayout.indexOf(glw.VERTEX_LAYOUT_P) !== -1 )
258 | {
259 | var location = this.gl.getAttribLocation(glw.curr_program, "position");
260 | if(location !== -1)
261 | {
262 | this.gl.enableVertexAttribArray(location);
263 | this.gl.vertexAttribPointer(location,3,this.gl.FLOAT,false,this.vertexSize,offset);
264 | }
265 | offset += 3 * 4;
266 | }
267 |
268 | if(this.vertexLayout.indexOf(glw.VERTEX_LAYOUT_N) !== -1 )
269 | {
270 | var location = this.gl.getAttribLocation(glw.curr_program, "normal");
271 | if(location !== -1) {
272 | this.gl.enableVertexAttribArray(location);
273 | this.gl.vertexAttribPointer(location, 3, this.gl.FLOAT, false, this.vertexSize, offset);
274 | }
275 | offset += 3 * 4;
276 | }
277 |
278 | if(this.vertexLayout.indexOf(glw.VERTEX_LAYOUT_T0) !== -1 )
279 | {
280 | var location = this.gl.getAttribLocation(glw.curr_program, "texcoord");
281 | if(location !== -1) {
282 | this.gl.enableVertexAttribArray(location);
283 | this.gl.vertexAttribPointer(location,2,this.gl.FLOAT,false,this.vertexSize,offset);
284 | }
285 | offset += 2 * 4;
286 | }
287 |
288 |
289 | }
290 |
291 | draw() {
292 |
293 | this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vbo);
294 | this.bind();
295 |
296 | if(this.indexSize_list > 0)
297 | {
298 | this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.trilist);
299 | glw._draw_elements(this.gl.TRIANGLES, this.indexSize_list);
300 | }
301 | if(this.indexSize_strip > 0)
302 | {
303 | this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.tristrip);
304 | glw._draw_elements(this.gl.TRIANGLE_STRIP, this.indexSize_strip);
305 | }
306 |
307 | }
308 |
309 | }
310 | // mesh obj
311 |
312 | /// material obj
313 | glw.createMaterialObject = function () {
314 | return new materialObject();
315 | };
316 | class materialObject
317 | {
318 | constructor() {
319 | this.mainTex = null;
320 | this.lightMapTex = null;
321 | this.name = 'default';
322 | }
323 |
324 | bind() {
325 |
326 | }
327 | }
328 |
329 | /// program obj
330 | glw.createProgramObject = function (vsSource, psSource) {
331 |
332 | var newObj = new programObject(this.gl);
333 | newObj.glprogram = newObj.create(vsSource, psSource);
334 | if(newObj.glprogram === null)
335 | {
336 | return null;
337 | }
338 | // analyze uniforms from vs & fs source
339 | newObj.loc[0] = this.gl.getAttribLocation(newObj.glprogram, "position");
340 | newObj.loc[1] = this.gl.getAttribLocation(newObj.glprogram, "normal");
341 | newObj.loc[2] = this.gl.getAttribLocation(newObj.glprogram, "texcoord");
342 |
343 | return newObj;
344 | };
345 |
346 | class programObject
347 | {
348 | constructor(glContext) {
349 | this.gl = glContext;
350 | this.glprogram = null;
351 | this.loc = {};
352 | }
353 |
354 | create(vsSource, fsSource) {
355 | var prg = null;
356 | var vs = glw._create_shader_from_source(vsSource, this.gl.VERTEX_SHADER);
357 | var fs = glw._create_shader_from_source(fsSource, this.gl.FRAGMENT_SHADER);
358 | prg = glw._create_program(vs, fs);
359 | return prg;
360 | };
361 |
362 | set_uniform( uniform_name, uniform_value )
363 | {
364 |
365 | };
366 |
367 | use()
368 | {
369 | glw._use_program( this.glprogram );
370 | };
371 | }
372 | // program obj
373 |
374 |
375 |
376 | /// internal interface
377 |
378 | // create shader
379 | glw._create_shader_from_source = function(source, type){
380 | var shader, msg;
381 | switch(type){
382 | case this.gl.VERTEX_SHADER:
383 | shader = this.gl.createShader(this.gl.VERTEX_SHADER);
384 | break;
385 | case this.gl.FRAGMENT_SHADER:
386 | shader = this.gl.createShader(this.gl.FRAGMENT_SHADER);
387 | break;
388 | default :
389 | return;
390 | }
391 | this.gl.shaderSource(shader, source);
392 | this.gl.compileShader(shader);
393 | if(this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)){
394 | return shader;
395 | }else{
396 | msg = this.gl.getShaderInfoLog(shader);
397 | // directly print to console
398 | logger.error(msg);
399 | console.warn('compile failed of shader: ' + msg);
400 | return null;
401 | }
402 | };
403 |
404 | // create program
405 | glw._create_program = function(vs, fs){
406 |
407 | if(vs == null || fs == null)
408 | {
409 | return null;
410 | }
411 |
412 | var program = this.gl.createProgram();
413 | this.gl.attachShader(program, vs);
414 | this.gl.attachShader(program, fs);
415 | this.gl.linkProgram(program);
416 | if(this.gl.getProgramParameter(program, this.gl.LINK_STATUS)){
417 | this.gl.useProgram(program);
418 | return program;
419 | }else{
420 | var msg = this.gl.getProgramInfoLog(program);
421 | logger.error(msg);
422 | console.warn('link program failed: ' + msg);
423 | return null;
424 | }
425 | };
426 |
427 | // use program
428 | glw._use_program = function(prg){
429 | this.gl.useProgram(prg);
430 | this.curr_program = prg;
431 | };
432 |
433 |
434 | // gen & bind vbo data
435 | // TODO: managed later
436 | glw._create_vbo = function(data){
437 | if(data == null){return;}
438 | var vbo = this.gl.createBuffer();
439 | this.gl.bindBuffer(this.gl.ARRAY_BUFFER, vbo);
440 | this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(data), this.gl.STATIC_DRAW);
441 | this.gl.bindBuffer(this.gl.ARRAY_BUFFER, null);
442 | return vbo;
443 | };
444 |
445 | // gen & bind ibo data
446 | // TODO: managed later
447 | glw._create_ibo = function(data){
448 |
449 | if(data == null){return;}
450 |
451 | var ibo = this.gl.createBuffer();
452 |
453 | this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, ibo);
454 | this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, new Int16Array(data), this.gl.STATIC_DRAW);
455 | this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, null);
456 |
457 | return ibo;
458 | };
459 |
460 | // gen & bind texture
461 | glw._create_procedural_texture = function(width, height, data){
462 |
463 | let gl = this.gl;
464 | let fTexture = gl.createTexture();
465 |
466 | gl.bindTexture(gl.TEXTURE_2D, fTexture);
467 | gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, data);
468 |
469 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
470 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
471 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
472 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
473 |
474 | return fTexture;
475 | };
476 |
477 |
478 | glw._create_bind_texture = function(data){
479 |
480 | let gl = this.gl;
481 | let buffer = gl.createTexture();
482 |
483 | gl.bindTexture(gl.TEXTURE_2D, buffer);
484 | gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, data);
485 |
486 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
487 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
488 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
489 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
490 | gl.bindTexture(gl.TEXTURE_2D, null);
491 |
492 | return buffer;
493 | };
494 |
495 | // fbo
496 | glw._create_framebuffer = function(width, height){
497 |
498 | // check & prepare
499 | if(width == null || height == null){return;}
500 | var gl = this.gl;
501 |
502 | // create fbo
503 | var frameBuffer = gl.createFramebuffer();
504 | gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);
505 |
506 | let depthComponent = null;
507 |
508 | if(glw.glext_depth_texture)
509 | {
510 | //console.info("bind depth texture");
511 | var fTexture = gl.createTexture();
512 | gl.bindTexture(gl.TEXTURE_2D, fTexture);
513 | gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH_COMPONENT, width, height, 0, gl.DEPTH_COMPONENT, gl.UNSIGNED_SHORT, null);
514 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
515 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
516 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
517 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
518 | gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, fTexture, 0);
519 |
520 | depthComponent = fTexture;
521 | }
522 | else
523 | {
524 | // depth by renderbuffer, compitable with all
525 | var depthRenderBuffer = gl.createRenderbuffer();
526 | gl.bindRenderbuffer(gl.RENDERBUFFER, depthRenderBuffer);
527 | gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, width, height);
528 | gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthRenderBuffer);
529 |
530 | depthComponent = depthRenderBuffer;
531 | }
532 |
533 |
534 |
535 |
536 |
537 | // color by render textrue
538 | var fTexture = gl.createTexture();
539 | gl.bindTexture(gl.TEXTURE_2D, fTexture);
540 | gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
541 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
542 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
543 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
544 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
545 | gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, fTexture, 0);
546 |
547 | // clear state
548 | gl.bindTexture(gl.TEXTURE_2D, null);
549 | gl.bindRenderbuffer(gl.RENDERBUFFER, null);
550 | gl.bindFramebuffer(gl.FRAMEBUFFER, null);
551 |
552 | return {framebuffer: frameBuffer, depthRenderbuffer: depthComponent, rendertexture: fTexture};
553 | };
554 |
555 | // dp
556 | glw._draw_arrays = function(primitive, vertexCount){
557 | this.gl.drawArrays(primitive, 0, vertexCount);
558 | };
559 |
560 | // dip
561 | glw._draw_elements = function(primitive, indexLength){
562 | this.gl.drawElements(primitive, indexLength, this.gl.UNSIGNED_SHORT, 0);
563 | };
564 |
--------------------------------------------------------------------------------
/lib/gk-logger.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by gameKnife on 2016/11/11.
3 | */
4 | class logger {
5 |
6 | static get LOGTYPE_INFO() {
7 | return 0;
8 | }
9 | static get LOGTYPE_WARN() {
10 | return 1;
11 | }
12 | static get LOGTYPE_ERRO() {
13 | return 2;
14 | }
15 |
16 | static init(console) {
17 | logger.console = console;
18 | logger.logcache = new Array();
19 | };
20 |
21 | static info(logstr) {
22 | logger.logcache.unshift([logger.LOGTYPE_INFO, logstr]);
23 | logger.refreshLog();
24 | };
25 |
26 | static warn(logstr) {
27 | logger.logcache.unshift([logger.LOGTYPE_WARN, logstr]);
28 | logger.refreshLog();
29 | };
30 |
31 | static error(logstr) {
32 | logger.logcache.unshift([logger.LOGTYPE_ERRO, logstr]);
33 | logger.refreshLog();
34 | };
35 |
36 | static refreshLog() {
37 | while (logger.console.firstChild) {
38 | logger.console.removeChild(logger.console.firstChild);
39 | }
40 |
41 | if (logger.logcache.length > 50) {
42 | var deleteCount = logger.logcache.length - 50;
43 | logger.logcache.splice(50, deleteCount);
44 | }
45 |
46 | var count = 0;
47 | logger.logcache.forEach(function (line) {
48 | var log_line = document.createElement('div');
49 | if (count++ % 2 === 0) {
50 | log_line.className = 'log-line-s';
51 | }
52 | else {
53 | log_line.className = 'log-line-d';
54 | }
55 |
56 | var infotype = line[0];
57 | var log_icon = document.createElement('i');
58 |
59 | switch (infotype) {
60 | case logger.LOGTYPE_INFO:
61 | log_icon.className = 'btm bt-info-circle';
62 | log_line.style.color = '#fff';
63 | break;
64 | case logger.LOGTYPE_WARN:
65 | log_icon.className = 'bts bt-exclamation-triangle';
66 | log_line.style.color = '#ff3';
67 | break;
68 | case logger.LOGTYPE_ERRO:
69 | log_icon.className = 'bts bt-ban';
70 | log_line.style.color = '#f33';
71 | break;
72 | }
73 |
74 | log_line.appendChild(log_icon);
75 |
76 | var log_text = document.createTextNode(' ' + line[1]);
77 | log_line.appendChild(log_text);
78 |
79 | logger.console.appendChild(log_line);
80 | });
81 |
82 | };
83 | }
84 |
85 | module.exports = logger;
86 |
87 |
--------------------------------------------------------------------------------
/lib/gk-mouseorbit.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by kaimingyi on 12/11/2016.
3 | */
4 | 'use strict'
5 | var mouseorbit = mouseorbit || {};
6 |
7 | module.exports = mouseorbit;
8 |
9 | mouseorbit.HOLDLEFT = 1;
10 | mouseorbit.HOLDMIDDLE = 2;
11 | mouseorbit.HOLDRIGHT = 3;
12 | mouseorbit.HOLDFREE = 0;
13 |
14 | mouseorbit.frame = null;
15 | mouseorbit.startPT = null;
16 | mouseorbit.movePT = null;
17 | mouseorbit.delta = { x: 0, y: 0};
18 |
19 | mouseorbit.deltaLast = { x: 0, y: 0, z: 0};
20 |
21 | mouseorbit.wheelStatus = 0;
22 | mouseorbit._wheelStatus = 0;
23 |
24 | mouseorbit.moveType = 0;
25 |
26 | mouseorbit.frameUpdate = function()
27 | {
28 | let relativeDelta = { x: mouseorbit.delta.x - mouseorbit.deltaLast.x, y : mouseorbit.delta.y - mouseorbit.deltaLast.y, z: mouseorbit.wheelStatus };
29 | mouseorbit.deltaLast = mouseorbit.delta;
30 | mouseorbit.wheelStatus = 0;
31 | return relativeDelta;
32 | }
33 |
34 | mouseorbit.updateDelta = function()
35 | {
36 | mouseorbit.delta = { x: mouseorbit.movePT.x - mouseorbit.startPT.x, y: mouseorbit.movePT.y - mouseorbit.startPT.y};
37 | }
38 |
39 | mouseorbit.onMouseDown = function( event )
40 | {
41 | event.preventDefault();
42 |
43 | mouseorbit.startPT = { x: event.clientX, y: event.clientY};
44 |
45 | if ('which' in event) {
46 | switch (event.which) {
47 | case 1:
48 | mouseorbit.moveType = mouseorbit.HOLDLEFT;
49 | break;
50 | case 2:
51 | mouseorbit.moveType = mouseorbit.HOLDMIDDLE;
52 | break;
53 | case 3:
54 | mouseorbit.moveType = mouseorbit.HOLDRIGHT;
55 | break;
56 | }
57 | }
58 |
59 | mouseorbit.frame.addEventListener( 'mousemove', mouseorbit.onMouseMove, false );
60 | mouseorbit.frame.addEventListener( 'mouseup', mouseorbit.onMouseUp, false );
61 |
62 | mouseorbit.delta = { x: 0, y: 0};
63 | mouseorbit.deltaLast = { x: 0, y: 0};
64 | }
65 |
66 | mouseorbit.onMouseMove = function( event )
67 | {
68 | mouseorbit.frame.style.setProperty( 'cursor', 'move' );
69 |
70 | event.preventDefault();
71 |
72 | mouseorbit.movePT = { x: event.clientX, y: event.clientY};
73 |
74 | mouseorbit.updateDelta();
75 | }
76 |
77 | mouseorbit.onMouseUp = function( event )
78 | {
79 | mouseorbit.frame.style.setProperty( 'cursor', 'pointer' );
80 |
81 | mouseorbit.moveType = mouseorbit.HOLDFREE;
82 |
83 | mouseorbit.frame.removeEventListener( 'mousemove', mouseorbit.onMouseMove, false);
84 | mouseorbit.frame.removeEventListener( 'mouseup', mouseorbit.onMouseUp, false);
85 | }
86 |
87 | mouseorbit.onMouseWheel = function( event ) {
88 |
89 | var value = event.wheelDelta || -event.detail;
90 | var delta = Math.max(-1, Math.min(1, value));
91 | mouseorbit.wheelStatus = delta;
92 | }
93 |
94 | mouseorbit.init = function( frame )
95 | {
96 | mouseorbit.frame = frame;
97 | mouseorbit.frame.addEventListener( 'mousedown', mouseorbit.onMouseDown, false );
98 | mouseorbit.frame.addEventListener( 'mousewheel', mouseorbit.onMouseWheel, false );
99 | }
--------------------------------------------------------------------------------
/lib/gk-renderer.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by gameKnife on 2016/12/1.
3 | */
4 | const glw = require("./gk-glwrap");
5 | const fixedshader = require("./gk-fixedshader");
6 | const resMgr = require("./gk-resmgr");
7 | const math = require("gl-matrix");
8 | const gTimer = require("./gk-timer");
9 | const mouse = require("./gk-mouseorbit");
10 |
11 |
12 | const GameObject = require("./gk-gameobject.js");
13 | const Component = require("./gk-component.js");
14 |
15 | class RenderQueue {
16 | constructor( _depth ) {
17 | this.depth = _depth;
18 | this.meshRenderers = [];
19 |
20 | // per queue uniform unit: { KEY: "_MVP", VALUE: mat4 / vec4 / etc }
21 | this.uniformPerQueue = new Map();
22 |
23 | this.camera = null;
24 | this.light = null;
25 | }
26 |
27 | setupCamera( cam ) {
28 |
29 | this.camera = cam;
30 |
31 | }
32 |
33 | setupLight( light ) {
34 |
35 | this.light = light;
36 | }
37 |
38 | clear() {
39 | this.meshRenderers = [];
40 | }
41 |
42 | addRenderer( mr ) {
43 | this.meshRenderers.push(mr);
44 | }
45 |
46 | sort() {
47 | // sort by material
48 | }
49 |
50 | prepare( rendererInst )
51 | {
52 | // prepare cam
53 | {
54 | let camts = this.camera.host.transform;
55 |
56 | let cameraPosition = camts.position;
57 | let cameraUpDirection = camts.up;
58 | let cameraForwardDirection = math.vec3.negate(math.vec3.create(), camts.forward);
59 | let centerPoint = math.vec3.add( math.vec3.create(), cameraPosition, cameraForwardDirection );
60 |
61 | let aspect = rendererInst.currentRenderTarget.width / rendererInst.currentRenderTarget.height;
62 |
63 | let projMatrix = math.mat4.perspective(math.mat4.create(), 45, aspect, 0.5, 5000.0);
64 | let viewMatrix = math.mat4.lookAt(math.mat4.create(), cameraPosition, centerPoint, cameraUpDirection);
65 | let vpMatrix = math.mat4.multiply(math.mat4.create(), projMatrix, viewMatrix);
66 |
67 | this.uniformPerQueue.set("_PROJ", projMatrix );
68 | this.uniformPerQueue.set("_VIEW", viewMatrix );
69 | this.uniformPerQueue.set("_VIEWPROJ", vpMatrix );
70 | }
71 |
72 | // prepare light
73 | {
74 | let lightDir = this.light.host.transform.forward;
75 | this.uniformPerQueue.set("_LIGHTDIR", lightDir);
76 |
77 | let camts = this.light.host.transform;
78 |
79 | let cameraPosition = camts.position;
80 | let cameraUpDirection = camts.up;
81 | let cameraForwardDirection = math.vec3.negate(math.vec3.create(), camts.forward);
82 | let centerPoint = math.vec3.add( math.vec3.create(), cameraPosition, cameraForwardDirection );
83 |
84 | let projMatrix = math.mat4.ortho(math.mat4.create(), -150, 150, -150, 150, 500, 3000);
85 | let viewMatrix = math.mat4.lookAt(math.mat4.create(), cameraPosition, centerPoint, cameraUpDirection);
86 | let vpMatrix = math.mat4.multiply(math.mat4.create(), projMatrix, viewMatrix);
87 |
88 | this.uniformPerQueue.set("_LIGHTPROJ", projMatrix );
89 | this.uniformPerQueue.set("_LIGHTVIEW", viewMatrix );
90 | this.uniformPerQueue.set("_LIGHTVIEWPROJ", vpMatrix );
91 |
92 | let vMatrixOfCam = this.uniformPerQueue.get("_VIEW");
93 | let cam2lightMtx = math.mat4.invert(math.mat4.create(), vMatrixOfCam);
94 |
95 | math.mat4.multiply(cam2lightMtx, vpMatrix, cam2lightMtx);
96 |
97 | this.uniformPerQueue.set("_CAM2LIGHTVIEWPROJ", cam2lightMtx );
98 | }
99 |
100 | }
101 |
102 | // func: param0 - renderer
103 | traverse( func, additionParam ) {
104 |
105 | for( let i=0, len = this.meshRenderers.length; i < len; ++i)
106 | {
107 | func( this.meshRenderers[i], this, additionParam );
108 | }
109 | }
110 | }
111 |
112 | // singleton
113 | let instance = null;
114 |
115 | class Renderer {
116 | constructor() {
117 | if(!instance){
118 | instance = this;
119 |
120 | this.bgMesh = null;
121 | this.bgProgram = null;
122 | this.noiseProgram = null;
123 | this.shadowmapProgram = null;
124 | this.zpassProgram = null;
125 |
126 | this.ssaoProgram = null;
127 |
128 | this.simBackBuffer = null;
129 | this.shadowMapBuffer = null;
130 | this.zpassFrameBuffer = null;
131 |
132 | this.overrideProgram = null;
133 |
134 | this.renderQueues = new Map();
135 |
136 | this.currentRenderTarget = null;
137 | }
138 |
139 | return instance;
140 | }
141 |
142 | init() {
143 |
144 | // initialize quad
145 | const quadPosition = [
146 | -1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0,
147 | 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0,
148 | -1.0, -1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0,
149 | 1.0, -1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0,
150 | ];
151 | const quadIndex = [
152 | 0, 1, 2, 2, 1, 3
153 | ];
154 | let res = null;
155 | let ibo = {};
156 | ibo.trilist = quadIndex;
157 | res = {vbo: quadPosition, ibo: ibo };
158 | this.bgMesh = glw.createMeshObject(res, [glw.VERTEX_LAYOUT_P, glw.VERTEX_LAYOUT_T0, glw.VERTEX_LAYOUT_N]);
159 |
160 | // initialize shader
161 | this.bgProgram = glw.createProgramObject(fixedshader.quadvsp, fixedshader.quadfsp);
162 | this.noiseProgram = glw.createProgramObject(fixedshader.quadvsp, fixedshader.noisefsp);
163 |
164 | if( glw.glext_depth_texture )
165 | {
166 | this.shadowmapProgram = glw.createProgramObject(fixedshader.simpleshadowvsp, fixedshader.simpleshadowfsp);
167 | }
168 | else
169 | {
170 | this.shadowmapProgram = glw.createProgramObject(fixedshader.shadowvsp, fixedshader.shadowfsp);
171 | }
172 |
173 | this.zpassProgram = glw.createProgramObject(fixedshader.simplezpassvsp, fixedshader.simplezpassfsp);
174 |
175 | this.ssaoProgram = glw.createProgramObject(fixedshader.ssaovsp, fixedshader.ssaofsp);
176 |
177 | // initialize render texture
178 | this.shadowMapBuffer = resMgr.gResmgr.create_render_texture(1024,1024);
179 | this.shadowMapBuffer.load();
180 |
181 | this.resize(1024, 1024);
182 |
183 | }
184 |
185 | resize( width, height )
186 | {
187 | this.simBackBuffer = resMgr.gResmgr.create_render_texture(width * 2, height * 2);
188 | this.simBackBuffer.load();
189 |
190 | this.zpassFrameBuffer = resMgr.gResmgr.create_render_texture(width * 2, height * 2);
191 | this.zpassFrameBuffer.load();
192 |
193 | this.occlusionFrameBuffer = resMgr.gResmgr.create_render_texture(width * 2, height * 2);
194 | this.occlusionFrameBuffer.load();
195 | }
196 |
197 | pushRenderTarget( renderTexture )
198 | {
199 | this.currentRenderTarget = renderTexture;
200 | glw.gl.bindFramebuffer(glw.gl.FRAMEBUFFER, renderTexture.fbo);
201 | glw.viewport(0, 0,renderTexture.width, renderTexture.height);
202 | }
203 |
204 | popRenderTarget()
205 | {
206 |
207 | }
208 |
209 | render() {
210 |
211 | // render queue sorting
212 | for (let queue of this.renderQueues.values()) {
213 | queue.sort();
214 | }
215 |
216 | ///////////////////
217 | // shadow map gen
218 | this.pushRenderTarget(this.shadowMapBuffer);
219 | // clear with a grey color
220 | glw.clear([1, 1, 1, 1], 1.0);
221 |
222 | // set z enable
223 | glw.gl.enable(glw.gl.DEPTH_TEST);
224 | glw.gl.depthFunc(glw.gl.LEQUAL);
225 | glw.gl.disable(glw.gl.CULL_FACE);
226 |
227 | this.shadowmapProgram.use();
228 |
229 | for (let queue of this.renderQueues.values()) {
230 | queue.traverse( this.renderSingleRendererShadowmp );
231 | }
232 |
233 |
234 | ///////////////////
235 | // zpass
236 | this.pushRenderTarget(this.zpassFrameBuffer);
237 | // clear with a normal color
238 | glw.clear([0.5, 0.5, 1.0, 1.0], 1.0);
239 |
240 | // set z enable
241 | glw.gl.enable(glw.gl.DEPTH_TEST);
242 | glw.gl.depthFunc(glw.gl.LEQUAL);
243 | glw.gl.disable(glw.gl.CULL_FACE);
244 |
245 | // for every render queue
246 | if(this.zpassProgram != null)
247 | {
248 | this.zpassProgram.use();
249 | }
250 |
251 | for (let queue of this.renderQueues.values()) {
252 |
253 | queue.prepare( this );
254 | // setup queue basic parameter
255 | queue.traverse( this.renderSingleRenderer );
256 | }
257 |
258 | ///////////////////
259 | // occlusion pass
260 |
261 | // ssao
262 | this.pushRenderTarget(this.occlusionFrameBuffer);
263 | // clear with white color
264 | glw.clear([1.0, 1.0, 1.0, 1.0], 1.0);
265 | if(this.ssaoProgram != null) {
266 | this.ssaoProgram.use();
267 | glw.bind_texture( this.zpassFrameBuffer.gltextureobject, 5 );
268 | glw.bind_texture( this.zpassFrameBuffer.depth, 6 );
269 | }
270 | this.bgMesh.draw();
271 |
272 | ///////////////////
273 | // general shading pass
274 |
275 | // bind general draw ssaa fbo
276 | this.pushRenderTarget(this.simBackBuffer);
277 | // clear with a grey color
278 | glw.clear([0.15, 0.15, 0.15, 1.0], 1.0);
279 |
280 | // set z enable
281 | glw.gl.enable(glw.gl.DEPTH_TEST);
282 | glw.gl.depthFunc(glw.gl.LEQUAL);
283 | glw.gl.disable(glw.gl.CULL_FACE);
284 |
285 | // render the noising background
286 | this.noiseProgram.use();
287 | glw.set_uniform1f("_TIME", gTimer.runTime * 0.001);
288 | this.bgMesh.draw();
289 |
290 | // main render process
291 |
292 | // for every render queue
293 | if(this.overrideProgram != null)
294 | {
295 | this.overrideProgram.use();
296 | }
297 |
298 | for (let queue of this.renderQueues.values()) {
299 |
300 | queue.prepare( this );
301 | // setup queue basic parameter
302 | queue.traverse( this.renderSingleRenderer );
303 | }
304 |
305 | // bind backbuffer, resolve ssaa
306 | glw.gl.bindFramebuffer(glw.gl.FRAMEBUFFER, null );
307 |
308 | // clear with a grey color
309 | glw.clear([0.15, 0.15, 0.15, 1.0], 1.0);
310 | glw.viewport(0, 0, glw.canvas.width, glw.canvas.height);
311 |
312 | this.bgProgram.use();
313 | glw.set_uniform1f("_TIME", gTimer.runTime * 0.001);
314 |
315 | // bind the draw buffer
316 | glw.bind_texture( this.simBackBuffer.gltextureobject, 0 );
317 |
318 | // bind the zpass buffer
319 | //glw.bind_texture( this.occlusionFrameBuffer.gltextureobject, 0);
320 |
321 | this.bgMesh.draw();
322 |
323 |
324 |
325 |
326 | // render queue clear
327 | for (let queue of this.renderQueues.values()) {
328 | queue.clear();
329 | }
330 | }
331 |
332 | destroy() {
333 |
334 | }
335 |
336 | getOrCreateRenderQueue( depth ) {
337 | if( !this.renderQueues.has( depth ) )
338 | {
339 | this.renderQueues.set( depth, new RenderQueue( depth ));
340 | }
341 |
342 | return this.renderQueues.get( depth );
343 | }
344 |
345 | renderSingleRendererShadowmp( renderer, queue ) {
346 | if( renderer instanceof Component.MeshRenderer )
347 | {
348 | // grab matrix
349 | let vpMatrix = queue.uniformPerQueue.get("_LIGHTVIEWPROJ");
350 |
351 | //renderer.host.transform._localToWorldMatrx;
352 | let mMatrix = renderer.host.transform.localToWorldMatrix;
353 |
354 | // set material
355 | let mat = renderer.material;
356 |
357 | glw.bind_texture( mat.mainTex.gltextureobject, 0 );
358 | glw.bind_texture( mat.opacityMapTex.gltextureobject, 1 );
359 |
360 | glw.set_uniform4x4fv("_MVP", math.mat4.mul(math.mat4.create(), vpMatrix, mMatrix));
361 | glw.set_uniform4x4fv("_M2W", mMatrix);
362 |
363 | // extract meshfilter
364 | let mf = renderer.host.components.get(Component.MeshFilter);
365 |
366 | // render
367 | if( mf.mesh !== null ) {
368 | //console.info(mf.mesh);
369 | mf.mesh.draw();
370 | }
371 | }
372 | }
373 |
374 | renderSingleRenderer( renderer, queue ) {
375 | if( renderer instanceof Component.MeshRenderer )
376 | {
377 | // grab matrix
378 | let vpMatrix = queue.uniformPerQueue.get("_VIEWPROJ");
379 | let vMatrix = queue.uniformPerQueue.get("_VIEW");
380 | let vpMatrix_Light = queue.uniformPerQueue.get("_CAM2LIGHTVIEWPROJ");
381 |
382 | //renderer.host.transform._localToWorldMatrx;
383 | let mMatrix = renderer.host.transform.localToWorldMatrix;
384 |
385 | // set material
386 | let mat = renderer.material;
387 |
388 | let lightDir = queue.uniformPerQueue.get("_LIGHTDIR");
389 | if(lightDir)
390 | {
391 | lightDir[3] = 0;
392 | glw.set_uniform4f("_LIGHTDIR", lightDir);
393 | }
394 |
395 | glw.bind_texture( mat.mainTex.gltextureobject, 0 );
396 | glw.bind_texture( mat.opacityMapTex.gltextureobject, 1 );
397 |
398 | glw.bind_texture( instance.zpassFrameBuffer.gltextureobject, 5 );
399 | if(glw.glext_depth_texture)
400 | {
401 | glw.bind_texture( instance.zpassFrameBuffer.depth, 6 );
402 | }
403 | else
404 | {
405 | //glw.bind_texture( instance.shadowMapBuffer.gltextureobject, 6 );
406 | }
407 |
408 | if(glw.glext_depth_texture)
409 | {
410 | glw.bind_texture( instance.shadowMapBuffer.depth, 7 );
411 | }
412 | else
413 | {
414 | glw.bind_texture( instance.shadowMapBuffer.gltextureobject, 7 );
415 | }
416 |
417 | glw.set_uniform4x4fv("_MVP", math.mat4.mul(math.mat4.create(), vpMatrix, mMatrix));
418 | glw.set_uniform4x4fv("_MV", math.mat4.mul(math.mat4.create(), vMatrix, mMatrix));
419 | glw.set_uniform4x4fv("_M2W", mMatrix);
420 |
421 | glw.set_uniform4x4fv("_MVP_LIGHT",vpMatrix_Light);
422 |
423 | // extract meshfilter
424 | let mf = renderer.host.components.get(Component.MeshFilter);
425 |
426 | // render
427 | if( mf.mesh !== null ) {
428 | //console.info(mf.mesh);
429 | mf.mesh.draw();
430 | }
431 | }
432 | }
433 | }
434 |
435 | module.exports = Renderer;
--------------------------------------------------------------------------------
/lib/gk-resmgr.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by kaimingyi on 14/11/2016.
3 | */
4 | const logger = require('./gk-logger.js');
5 | const path = require('path');
6 | const loader_fbx = require('./loader/loader-fbx.js');
7 | const loader_osgjs = require('./loader/loader-osgjs.js');
8 | const glw = require('./gk-glwrap.js');
9 | const Fabricate = require('./fabricate');
10 | const GameObject = require('./gk-gameobject');
11 | const Component = require('./gk-component');
12 | const math = require('gl-matrix');
13 |
14 | // type define
15 | var RESTYPE = RESTYPE || {};
16 | RESTYPE.INVALID = 0;
17 | RESTYPE.MESH = 1;
18 | RESTYPE.TEXTURE = 2;
19 | RESTYPE.TEXT = 3;
20 | RESTYPE.MATERIAL = 4;
21 |
22 | // base class obj
23 | class BaseResObj {
24 | constructor(token) {
25 | this.filetoken = token;
26 | this.loaded = false;
27 | this.type = RESTYPE.INVALID;
28 | this.dynamic = false;
29 | }
30 |
31 | get_type() {
32 | return this.type;
33 | }
34 |
35 | load(callback) {
36 | if( !this.loaded )
37 | {
38 | this.loadimpl(callback);
39 | }
40 | this.loaded = true;
41 | }
42 |
43 | unload() {
44 | if(this.loaded)
45 | {
46 | this.unloadimpl();
47 | }
48 | this.loaded = false;
49 | }
50 | }
51 |
52 | class MaterialResObj extends BaseResObj {
53 |
54 | }
55 |
56 | class MeshResObj extends BaseResObj {
57 | constructor(token) {
58 | super(token);
59 | this.type = RESTYPE.MESH;
60 | this.glmeshobject = null;
61 | this.gameObject = null;
62 | }
63 |
64 | loadimpl(callback) {
65 | // load fbx tmp
66 | let ref = this;
67 |
68 | let timestamp = Date.now();
69 |
70 |
71 | let ext = getFileExtension(this.filetoken);
72 | this.gameObject = Fabricate(GameObject.Base);
73 |
74 | switch (ext)
75 | {
76 | case 'fbx':
77 |
78 | loader_fbx.load( gResmgr, this.filetoken, function(res) {
79 | res.transform.parent = ref.gameObject.transform;
80 | let timeelapsed = Date.now() - timestamp;
81 | logger.info('Mesh ' + ref.filetoken + ' loaded in ' + timeelapsed + 'ms.');
82 | } );
83 |
84 | break;
85 | case 'osgjs':
86 |
87 | loader_osgjs.load( gResmgr, this.filetoken, function(res) {
88 | res.transform.parent = ref.gameObject.transform;
89 | let timeelapsed = Date.now() - timestamp;
90 | logger.info('Mesh ' + ref.filetoken + ' loaded in ' + timeelapsed + 'ms.');
91 |
92 | if(callback) {
93 | callback();
94 | }
95 | } );
96 |
97 | break;
98 | }
99 |
100 |
101 | }
102 |
103 | unloadimpl() {
104 | // release
105 | }
106 | }
107 |
108 | class TextureResObj extends BaseResObj {
109 | constructor(token) {
110 | super(token);
111 | this.type = RESTYPE.TEXTURE;
112 | this.gltextureobject = null;
113 | this.width = 0;
114 | this.height = 0;
115 | }
116 |
117 | loadimpl(callback) {
118 |
119 | let ref = this;
120 |
121 | let img = new Image();
122 | this.image = img;
123 | let timestamp = Date.now();
124 |
125 | img.onload = function () {
126 | ref.gltextureobject = glw._create_bind_texture(img);
127 | let timeelapsed = Date.now() - timestamp;
128 | logger.info('Texture ' + ref.filetoken + ' loaded in ' + timeelapsed + 'ms.');
129 |
130 | this.width = img.width;
131 | this.height = img.height;
132 | };
133 |
134 | // trigger loading
135 | img.src = this.filetoken;
136 | }
137 |
138 | unloadimpl() {
139 | // TODO
140 | }
141 | }
142 |
143 | class RenderTextureResObj extends TextureResObj {
144 | constructor(_width, _height) {
145 |
146 | let token = "dyn_" + gResmgr.dynamicTokenId;
147 | gResmgr.dynamicTokenId++;
148 |
149 | super(token);
150 | this.dynamic = true;
151 | this.width = _width;
152 | this.height = _height;
153 |
154 | this.fbo = null;
155 | this.depth = null;
156 | }
157 |
158 | loadimpl(callback) {
159 | let ret = glw._create_framebuffer(this.width, this.height);
160 | if(ret !== null)
161 | {
162 | this.gltextureobject = ret.rendertexture;
163 | this.fbo = ret.framebuffer;
164 | this.depth = ret.depthRenderbuffer;
165 | }
166 |
167 | }
168 |
169 | unloadimpl() {
170 | // TODO
171 | }
172 | }
173 |
174 | class TextResObj extends BaseResObj {
175 | constructor(token) {
176 | super(token);
177 | this.type = RESTYPE.TEXT;
178 | }
179 |
180 | loadimpl(callback) {
181 |
182 | }
183 |
184 | unloadimpl() {
185 |
186 | }
187 | }
188 |
189 | function getFileExtension(filename) {
190 | return (/[.]/.exec(filename)) ? /[^.]+$/.exec(filename)[0] : undefined;
191 | }
192 |
193 | let instance = null;
194 |
195 | class BaseResMgr {
196 |
197 | constructor() {
198 | if(!instance) {
199 | instance = this;
200 |
201 | this.resrefs = new Map();
202 | this.dynamicTokenId = 0;
203 | }
204 |
205 | return instance;
206 | }
207 |
208 | add_res(token) {
209 |
210 | if (this.resrefs.has(token)) {
211 | logger.error('Duplicate res added: ' + token);
212 | return;
213 | }
214 |
215 | let retRes = this.create_res_type_by_token(token);
216 | if (retRes !== null) {
217 | this.resrefs.set(token, retRes);
218 | }
219 |
220 | return retRes;
221 | }
222 |
223 | get_res(token) {
224 | token = path.normalize(token);
225 | return this.resrefs.get(token);
226 | }
227 |
228 | create_render_texture( _width, _height ) {
229 | let retRes = new RenderTextureResObj(_width, _height);
230 | if (retRes !== null) {
231 | this.resrefs.set(retRes.filetoken, retRes);
232 | }
233 | return retRes;
234 | }
235 |
236 | create_dyn_res_by_type(type) {
237 | switch (type) {
238 | case RESTYPE.MESH:
239 | return new MeshResObj(token);
240 | break;
241 | case RESTYPE.TEXTURE:
242 | return new TextureResObj(token);
243 | break;
244 | }
245 | return null;
246 | }
247 |
248 | create_res_type_by_token(token) {
249 |
250 | let ext = getFileExtension(token);
251 |
252 | if (ext !== undefined) {
253 | ext = ext.toLowerCase();
254 | switch (ext) {
255 | case 'fbx':
256 | case 'osgjs':
257 | return new MeshResObj(token);
258 | break;
259 | case 'jpg':
260 | case 'jpeg':
261 | case 'png':
262 | return new TextureResObj(token);
263 | break;
264 | case 'glsl':
265 | case 'js':
266 | return new TextResObj(token);
267 | break;
268 | }
269 | }
270 |
271 | return null;
272 | }
273 | }
274 |
275 | const gResmgr = new BaseResMgr();
276 |
277 | module.exports = {RESTYPE, BaseResMgr, BaseResObj, gResmgr};
--------------------------------------------------------------------------------
/lib/gk-respanel.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by kaimingyi on 2016/11/15.
3 | */
4 | const resMgr = require('./gk-resmgr.js');
5 | const fs = require('fs-extra');
6 | const path = require('path');
7 | const logger = require('./gk-logger.js');
8 |
9 | var respanel = respanel || {};
10 |
11 | module.exports = respanel;
12 |
13 |
14 | respanel.resFolderStruct = { '_folded' : false, '_name': 'root', '_child' : {} };
15 | respanel.resContainer = null;
16 | respanel.basedir = null;
17 | respanel.curr_selection = null;
18 |
19 | respanel.init = function(container, basedir)
20 | {
21 | respanel.resContainer = container;
22 | respanel.basedir = basedir;
23 | }
24 |
25 | respanel.rescan_resources = function () {
26 |
27 | let filelist = fs.walkSync(respanel.basedir + '/res/');
28 | filelist.forEach( item => {
29 |
30 | item = path.normalize(item);
31 | let filename = path.basename( item );
32 | let dirname = path.dirname(item);
33 | let relpath = path.relative( respanel.basedir, dirname );
34 | let token = path.normalize( relpath + path.sep + filename );
35 |
36 | resMgr.gResmgr.add_res(token);
37 | });
38 |
39 | }
40 |
41 | respanel.reconstruct_filetree = function () {
42 |
43 | // rebuild filetree with root
44 | respanel.resFolderStruct = { '_folded' : false, '_name': 'root', '_child' : {} };
45 |
46 | // build the folder struct
47 | resMgr.gResmgr.resrefs.forEach( item => {
48 |
49 | let folders = item.filetoken.split(path.sep);
50 |
51 | let currFolderLevel = respanel.resFolderStruct;
52 |
53 | // go check the folder links, choose the last
54 | for( let i=0; i < folders.length; ++i)
55 | {
56 | if( i === folders.length - 1)
57 | {
58 | // leaf
59 | currFolderLevel._child[folders[i]] = item;
60 | break;
61 | }
62 |
63 | if( folders[i] in currFolderLevel._child )
64 | {
65 | currFolderLevel = currFolderLevel._child[folders[i]];
66 | }
67 | else
68 | {
69 | currFolderLevel._child[folders[i]] = { '_folded' : true, '_child' : {} };
70 | currFolderLevel._child[folders[i]]._name = folders[i];
71 |
72 | currFolderLevel = currFolderLevel._child[folders[i]];
73 | }
74 | }
75 | });
76 |
77 | }
78 |
79 | respanel.refresh = function () {
80 | let timestamp = Date.now();
81 | respanel.clean_folder(respanel.resContainer);
82 | respanel.list_folder(respanel.resFolderStruct, 1);
83 | let timeelapsed = Date.now() - timestamp;
84 |
85 | //logger.info('respanel refresh take ' + timeelapsed + 'ms.');
86 | }
87 |
88 | //console.info(resFolderStruct);
89 | // dispatch res to resouce
90 |
91 | respanel.create_res_showobj = function(depth, filetoken, type, thumbMode = true) {
92 |
93 | var obj_container = document.createElement('div');
94 | // indent
95 | obj_container.style.padding = '0px ' + depth + 'px';
96 |
97 | // create inside button
98 | var obj_button = document.createElement('button');
99 | obj_button.className = 'obj-line';
100 | obj_button.id = 'btn-' + filetoken;
101 |
102 | // create icon
103 | var log_icon = null;
104 |
105 | switch (type) {
106 | case resMgr.RESTYPE.MESH:
107 | log_icon = document.createElement('i');
108 | log_icon.className = 'btm bt-database';
109 | break;
110 | case resMgr.RESTYPE.TEXTURE:
111 |
112 | // load resmgt
113 | let res = resMgr.gResmgr.get_res(filetoken);
114 | if(res !== null && !res.dynamic)
115 | {
116 | log_icon = document.createElement('img');
117 | log_icon.src = res.filetoken;
118 | if(thumbMode)
119 | {
120 | log_icon.width = '13';
121 | log_icon.height = '13';
122 | }
123 | else
124 | {
125 | log_icon.width = '48';
126 | log_icon.height = '48';
127 | }
128 |
129 | }
130 | else
131 | {
132 | log_icon = document.createElement('i');
133 | log_icon.className = 'bts bt-photo';
134 | }
135 | break;
136 | default:
137 | log_icon = document.createElement('i');
138 | log_icon.className = 'btm bt-file';
139 | break;
140 | }
141 | log_icon.style.color = '#8af';
142 |
143 | // create name text
144 | var log_text = document.createTextNode(' ' + filetoken.split(path.sep).pop());
145 |
146 | // compose
147 | obj_button.appendChild(log_icon);
148 | if(thumbMode)
149 | {
150 | obj_button.appendChild(log_text);
151 | }
152 | obj_container.appendChild(obj_button);
153 |
154 | // return
155 | return {obj_container: obj_container, obj_button: obj_button, obj_icon: log_icon};
156 | }
157 |
158 | respanel.list_folder = function (folderStruct, depth) {
159 |
160 | for (let element in folderStruct._child) {
161 |
162 | let folder = folderStruct._child[element];
163 | if(folder === undefined)
164 | {
165 | break;
166 | }
167 |
168 |
169 |
170 | if (folder instanceof resMgr.BaseResObj)
171 | {
172 | // create obj button
173 | let filetoken = folder.filetoken;
174 | let type = folder.get_type();
175 | let __ret = respanel.create_res_showobj(depth, filetoken, type);
176 | let obj_container = __ret.obj_container;
177 | let obj_button = __ret.obj_button;
178 | let obj_icon = __ret.obj_icon;
179 |
180 | if(folder.loaded)
181 | {
182 | obj_icon.style.color = '#7f7';
183 | }
184 |
185 | // selection status
186 | if (respanel.curr_selection === folder) {
187 | obj_button.className = 'obj-line-checked';
188 | }
189 |
190 | // click selection change
191 | obj_button.onclick = function () {
192 | respanel.curr_selection = folder;
193 | respanel.refresh();
194 | }
195 |
196 | // drag status
197 | obj_button.draggable = true;
198 | obj_button.ondragstart = function (ev) {
199 | ev.dataTransfer.setData("restoken", filetoken);
200 | }
201 |
202 | // db click
203 | obj_button.ondblclick = function () {
204 | //window.parent.renderer.updateMesh(folder.filetoken);
205 | }
206 |
207 | // append
208 | respanel.resContainer.appendChild(obj_container);
209 | }
210 | else
211 | {
212 | var obj_container = document.createElement('div');
213 | obj_container.style.padding = '0px ' + depth + 'px';
214 |
215 | var obj_button = document.createElement('button');
216 | obj_button.id = 'folder-' + folder._name;
217 | obj_button.className = 'obj-line';
218 |
219 | obj_button.onclick = function () {
220 | folder._folded = !folder._folded;
221 | respanel.refresh();
222 | }
223 |
224 | var log_icon = document.createElement('i');
225 | if (folder._folded) {
226 | log_icon.className = 'bts bt-folder';
227 | } else {
228 | log_icon.className = 'btm bt-folder';
229 | }
230 | log_icon.style.color = '#8af';
231 | var log_text = document.createTextNode(' ' + folder._name);
232 |
233 | // compose
234 | obj_button.appendChild(log_icon);
235 | obj_button.appendChild(log_text);
236 | obj_container.appendChild(obj_button);
237 |
238 | respanel.resContainer.appendChild(obj_container);
239 |
240 | if (folder._folded) {
241 |
242 | }
243 | else
244 | {
245 | //console.info(folder);
246 | respanel.list_folder(folder, depth + 10);
247 | }
248 | }
249 |
250 |
251 | //var log_icon = document.createElement('i');
252 |
253 | }
254 | ;
255 | }
256 |
257 | respanel.clean_folder = function(resContainer) {
258 | while (resContainer.firstChild) {
259 | resContainer.removeChild(resContainer.firstChild);
260 | }
261 | }
262 |
263 |
264 |
265 |
266 |
267 |
--------------------------------------------------------------------------------
/lib/gk-scenemgr.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by kaimingyi on 2016/12/1.
3 | */
4 | const Fabricate = require("./fabricate.js");
5 | const GameObject = require("./gk-gameobject.js");
6 | const Component = require("./gk-component.js");
7 |
8 | let instance = null;
9 |
10 | class SceneMgr {
11 | constructor() {
12 | if(!instance) {
13 | instance = this;
14 |
15 | this.root = null;
16 | this.meshRenderers = [];
17 | }
18 |
19 | return instance;
20 | }
21 |
22 | init() {
23 | this.root = Fabricate(GameObject.Base);
24 | }
25 |
26 | update() {
27 |
28 | // update
29 | this.traverseNode( this.root, this.updateComonents );
30 |
31 | // collect mr
32 | this.meshRenderers = [];
33 | this.traverseNode( this.root, this.collectRenderer );
34 |
35 | // onRender -> Camera Component
36 | this.traverseNode( this.root, this.renderComonents );
37 | }
38 |
39 | getSceneRoot() {
40 | return this.root;
41 | }
42 |
43 | getMeshRenderers() {
44 | return this.meshRenderers;
45 | }
46 |
47 | traverseNode(node, nodeProcess ) {
48 |
49 | nodeProcess( node );
50 |
51 | let transform = node.components.get(Component.Transform);
52 | if( transform )
53 | {
54 | let refthis = this;
55 | transform.children.forEach( child => {
56 | refthis.traverseNode( child.host, nodeProcess );
57 | });
58 | }
59 | }
60 |
61 | updateComonents( node ) {
62 | if( node.components )
63 | {
64 | for (let comp of node.components.values()) {
65 | if( comp instanceof Component.Component )
66 | {
67 | comp.onUpdate();
68 | }
69 | }
70 | }
71 | }
72 |
73 | renderComonents( node ) {
74 | if( node.components )
75 | {
76 | for (let comp of node.components.values()) {
77 | if( comp instanceof Component.Component )
78 | {
79 | comp.onRender();
80 | }
81 | }
82 | }
83 | }
84 |
85 | collectRenderer( node ) {
86 | if( node.components )
87 | {
88 | let mr = node.components.get(Component.MeshRenderer);
89 |
90 | if( mr !== undefined )
91 | {
92 | instance.meshRenderers.push(mr);
93 | }
94 | }
95 | }
96 |
97 |
98 | }
99 |
100 | module.exports = SceneMgr;
--------------------------------------------------------------------------------
/lib/gk-timer.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by gameKnife on 2016/12/1.
3 | */
4 | class GKTimer {
5 | constructor() {
6 | this.startUpTimer = 0.0;
7 | this.runTime = 0.0;
8 | this.lastFrameTime = 0.0;
9 | this.deltaTime = 0.0;
10 | }
11 |
12 | init() {
13 | this.startUpTimer = Date.now();
14 | this.lastFrameTime = this.startUpTimer;
15 | }
16 |
17 | update() {
18 | this.runTime = Date.now() - this.startUpTimer;
19 | this.deltaTime = this.runTime - this.lastFrameTime;
20 | this.lastFrameTime = this.runTime;
21 | }
22 | }
23 |
24 | const gTimer = new GKTimer();
25 |
26 | module.exports = gTimer;
--------------------------------------------------------------------------------
/lib/util/gl-matrix-extension.js:
--------------------------------------------------------------------------------
1 | const math = require('gl-matrix');
2 |
3 | var aabb = {};
4 |
5 | aabb.create = function () {
6 |
7 | var out = {};
8 |
9 | out.lbb = math.vec3.fromValues(9999999,9999999,9999999);
10 | out.rtf = math.vec3.fromValues(-9999999,-9999999,-9999999);
11 |
12 | return out;
13 | }
14 |
15 | aabb.addPoint = function ( out, _vertex ) {
16 | out.lbb = math.vec3.min(out.lbb, out.lbb, _vertex);
17 | out.rtf = math.vec3.max(out.rtf, out.rtf, _vertex);
18 | return out;
19 | }
20 |
21 | aabb.mergeAABB = function ( out, _aabb ) {
22 | aabb.addPoint( out, _aabb.lbb );
23 | aabb.addPoint( out, _aabb.rtf );
24 |
25 | return out;
26 | }
27 |
28 | aabb.mergeOBB = function ( out, _aabb, obj2worldMatrix ) {
29 | // extract to 8 point
30 | let lbb = math.vec3.clone(_aabb.lbb);
31 | let rtf = math.vec3.clone(_aabb.rtf);
32 | let ltb = math.vec3.fromValues( lbb[0], rtf[1], lbb[2] );
33 | let ltf = math.vec3.fromValues( lbb[0], rtf[1], rtf[2] );
34 | let lbf = math.vec3.fromValues( lbb[0], lbb[1], rtf[2] );
35 |
36 | let rbb = math.vec3.fromValues( rtf[0], lbb[1], lbb[2] );
37 | let rbf = math.vec3.fromValues( rtf[0], lbb[1], rtf[2] );
38 | let rtb = math.vec3.fromValues( rtf[0], rtf[1], lbb[2] );
39 |
40 | math.vec3.transformMat4(lbb, lbb, obj2worldMatrix);
41 | math.vec3.transformMat4(rtf, rtf, obj2worldMatrix);
42 | math.vec3.transformMat4(ltb, ltb, obj2worldMatrix);
43 | math.vec3.transformMat4(ltf, ltf, obj2worldMatrix);
44 | math.vec3.transformMat4(lbf, lbf, obj2worldMatrix);
45 | math.vec3.transformMat4(rbb, rbb, obj2worldMatrix);
46 | math.vec3.transformMat4(rbf, rbf, obj2worldMatrix);
47 | math.vec3.transformMat4(rtb, rtb, obj2worldMatrix);
48 |
49 | aabb.addPoint( out, lbb );
50 | aabb.addPoint( out, rtf );
51 | aabb.addPoint( out, ltb );
52 | aabb.addPoint( out, ltf );
53 | aabb.addPoint( out, lbf );
54 | aabb.addPoint( out, rbb );
55 | aabb.addPoint( out, rbf );
56 | aabb.addPoint( out, rtb );
57 |
58 | return out;
59 | }
60 |
61 | aabb.center = function (out, src) {
62 | math.vec3.add(out, src.lbb, src.rtf);
63 | math.vec3.scale(out, out, 0.5);
64 | return out;
65 | }
66 |
67 | aabb.radius = function (src) {
68 | let distance = math.vec3.sub( math.vec3.create(), src.lbb, src.rtf);
69 | return math.vec3.length(distance) * 0.5;
70 | }
71 |
72 |
73 | exports.aabb = aabb;
--------------------------------------------------------------------------------
/main.js:
--------------------------------------------------------------------------------
1 | const electron = require('electron')
2 | // Module to control application life.
3 | const app = electron.app
4 | // Module to create native browser window.
5 | const BrowserWindow = electron.BrowserWindow
6 |
7 | const path = require('path')
8 | const url = require('url')
9 |
10 | // Keep a global reference of the window object, if you don't, the window will
11 | // be closed automatically when the JavaScript object is garbage collected.
12 | let mainWindow
13 |
14 | function createWindow () {
15 | // Create the browser window.
16 |
17 | const {width, height} = electron.screen.getPrimaryDisplay().workAreaSize
18 |
19 | mainWindow = new BrowserWindow({width: width, height: height})
20 |
21 | // and load the index.html of the app.
22 | mainWindow.loadURL(url.format({
23 | pathname: path.join(__dirname, 'index.html'),
24 | protocol: 'file:',
25 | slashes: true
26 | }))
27 |
28 | // Open the DevTools.
29 | mainWindow.webContents.openDevTools()
30 |
31 | // Emitted when the window is closed.
32 | mainWindow.on('closed', function () {
33 | // Dereference the window object, usually you would store windows
34 | // in an array if your app supports multi windows, this is the time
35 | // when you should delete the corresponding element.
36 | mainWindow = null
37 | })
38 | }
39 |
40 | // This method will be called when Electron has finished
41 | // initialization and is ready to create browser windows.
42 | // Some APIs can only be used after this event occurs.
43 | app.on('ready', createWindow)
44 |
45 | // Quit when all windows are closed.
46 | app.on('window-all-closed', function () {
47 | // On OS X it is common for applications and their menu bar
48 | // to stay active until the user quits explicitly with Cmd + Q
49 | //if (process.platform !== 'darwin') {
50 | app.quit()
51 | //}
52 | })
53 |
54 | app.on('activate', function () {
55 | // On OS X it's common to re-create a window in the app when the
56 | // dock icon is clicked and there are no other windows open.
57 | if (mainWindow === null) {
58 | createWindow()
59 | }
60 | })
61 |
62 | // In this file you can include the rest of your app's specific main process
63 | // code. You can also put them in separate files and require them here.
64 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "electron-shadermonki",
3 | "version": "1.0.0",
4 | "description": "A research Electron app",
5 | "main": "main.js",
6 | "scripts": {
7 | "start": "electron .",
8 | "pack": "electron-packager . --arch=all",
9 | "watch-js": "watchify main.js -o bundle.js -dv",
10 | "build-js": "browserify main.js > bundle.js",
11 | "test": "tape test/loader-osgjs.js",
12 | "pkg-postprocess": "tape test/pkg-postprocess.js",
13 | "package-build": "tape test/package-build.js"
14 | },
15 | "repository": "https://github.com/gameknife/electron-shadermonki",
16 | "keywords": [
17 | "Electron",
18 | "Shader"
19 | ],
20 | "author": "gameKnife",
21 | "license": "MIT",
22 | "devDependencies": {
23 | "electron": "^1.4.1",
24 | "electron-packager": "^8.2.0",
25 | "browserify": "^13.1.1",
26 | "watchify": "^3.7.0",
27 | "tape": "~2.3.2"
28 | },
29 |
30 | "build": {
31 | "appId": "gameknife.shadermonki",
32 | "mac": {
33 | "category": "gameknife.app.category.utils"
34 | },
35 | "win": {
36 | "iconUrl": "(windows-only) https link to icon"
37 | }
38 | },
39 | "dependencies": {
40 | "fs-extra": "^1.0.0",
41 | "bluebird": "^3.4.6",
42 | "fs-promise": "^1.0.0",
43 | "gl-matrix": "2.3.2"
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/renderer.js:
--------------------------------------------------------------------------------
1 | // This file is required by the index.html file and will
2 | // be executed in the renderer process for that window.
3 | // All of the Node.js APIs are available in this process.
4 | 'use strict';
5 |
6 | const gkCore = require('./lib/gk-core');
7 |
8 | const logger = require('./lib/gk-logger');
9 | const glw = require('./lib/gk-glwrap');
10 | const mouse = require('./lib/gk-mouseorbit');
11 | const resMgr = require('./lib/gk-resmgr');
12 | const resPanel = require('./lib/gk-respanel');
13 | const Framework = require('./lib/gk-framework');
14 | const path = require('path');
15 |
16 | // initial
17 | window.onload = function(){
18 | // init logger
19 | logger.init(bid('console-log-container'));
20 | logger.info('shadermonki started.');
21 |
22 | // initialize rendering
23 | var canvas = bid('canvas');
24 | glw.initGL(canvas);
25 |
26 | switch_sceneview(false);
27 |
28 | if(!glw.ready){console.log('initialize error'); return;}
29 |
30 | // initialize mouse orbit
31 | mouse.init(canvas);
32 |
33 | // filter it and put it into resource manager
34 | resPanel.init(bid('res-container'), __dirname);
35 | resPanel.rescan_resources();
36 | resPanel.reconstruct_filetree();
37 | resPanel.refresh();
38 |
39 | // temporary feature
40 | let holder = bid('mesh-holder');
41 | let current_proj = '';
42 |
43 | holder.ondrop = function( ev ) {
44 |
45 | ev.preventDefault();
46 | var filetoken = ev.dataTransfer.getData("restoken");
47 |
48 | let type = 0;
49 | let resobj = resMgr.gResmgr.get_res(filetoken);
50 | if( resobj !== null )
51 | {
52 | current_proj = path.dirname(filetoken) + '/';
53 |
54 | type = resobj.get_type();
55 |
56 | if(type === resMgr.RESTYPE.MESH)
57 | {
58 | //create a mesh element
59 | let _ret = resPanel.create_res_showobj(0, filetoken, type);
60 |
61 | resPanel.clean_folder(this);
62 | this.appendChild(_ret.obj_container);
63 |
64 | // load mesh here
65 | if(!resobj.loaded)
66 | {
67 | resobj.load( onFinish => {
68 | framework.bindShowObj( resobj.gameObject );
69 | } );
70 | }
71 | else
72 | {
73 | framework.bindShowObj( resobj.gameObject );
74 | }
75 |
76 | resPanel.refresh();
77 |
78 |
79 | }
80 |
81 | }
82 |
83 | }
84 |
85 | holder.ondragover = function (ev) {
86 | ev.preventDefault();
87 | }
88 |
89 | let imgholder = bid('image-holder');
90 | imgholder.ondrop = function( ev ) {
91 |
92 | ev.preventDefault();
93 | var filetoken = ev.dataTransfer.getData("restoken");
94 |
95 | let type = 0;
96 | let resobj = resMgr.gResmgr.get_res(filetoken);
97 | if( resobj !== null )
98 | {
99 | type = resobj.get_type();
100 |
101 | if(type === resMgr.RESTYPE.TEXTURE)
102 | {
103 | //create a mesh element
104 | let _ret = resPanel.create_res_showobj(0, filetoken, type, false);
105 |
106 | resPanel.clean_folder(this);
107 | this.appendChild(_ret.obj_container);
108 |
109 | // load mesh here
110 | resobj.load();
111 | resPanel.refresh();
112 | //window.parent.renderer.updateTexure(resobj);
113 | }
114 |
115 | }
116 |
117 | }
118 |
119 | imgholder.ondragover = function (ev) {
120 | ev.preventDefault();
121 | }
122 |
123 | // framework start
124 | window.framework = new Framework();
125 | window.framework.init();
126 |
127 |
128 |
129 | // start and loop
130 | this.running = true;
131 | refresh_playbtn('btn_play', 'btn_play', window.running);
132 |
133 |
134 | // create render loop
135 | render_loop();
136 | function render_loop()
137 | {
138 | if(window.running) {
139 | window.framework.update();
140 | }
141 | requestAnimationFrame(render_loop);
142 | }
143 |
144 | // btn control
145 | {
146 | var playBtn = bid('btn_play');
147 | playBtn.onclick = function () {
148 | window.running = !window.running;
149 | refresh_playbtn('btn_play', 'btn_play', window.running);
150 | }
151 | }
152 |
153 | {
154 | // btn control
155 | let playBtn = bid('btn_auto_rotate');
156 | playBtn.onclick = function () {
157 | //refresh_playbtn('btn_auto_rotate', 'btn_square', renderer.autoRotate);
158 | }
159 | }
160 |
161 | this.fullscreen = false;
162 | {
163 | // btn control
164 | let targetBtn = bid('btn_next');
165 | targetBtn.onclick = function () {
166 | window.fullscreen = !window.fullscreen;
167 | switch_sceneview(window.fullscreen);
168 | }
169 | }
170 |
171 | };
172 |
173 | function refresh_playbtn( element_id, element_class, swt ) {
174 | var element = bid(element_id);
175 | if ( swt ) {
176 | element.className = element_class + '_on';
177 | }
178 | else {
179 | element.className = element_class;
180 | }
181 | }
182 |
183 | function switch_sceneview( fsmode ) {
184 |
185 | var canvas_fsholder = bid('fullscreen');
186 | var canvas = bid('canvas');
187 | var canvas_defaultHolder = bid('sceneview');
188 |
189 | //canvas_fsholder.style.visibility = 'hidden';
190 | //canvas_fsholder.appendChild(canvas);
191 | //canvas_defaultHolder.appendChild(canvas);
192 |
193 | if( fsmode ) {
194 | canvas_fsholder.style.visibility = 'visible';
195 | canvas_fsholder.appendChild(canvas);
196 | canvas.width = window.innerWidth;
197 | canvas.height = window.innerHeight;
198 |
199 | if( window.framework != undefined ) {
200 | window.framework.renderer.resize( window.innerWidth, window.innerHeight );
201 | }
202 | }
203 | else {
204 | canvas_fsholder.style.visibility = 'hidden';
205 | canvas_defaultHolder.appendChild(canvas);
206 | canvas.width = 512;
207 | canvas.height =512;
208 |
209 | if( window.framework != undefined ) {
210 | window.framework.renderer.resize(512, 512);
211 | }
212 | }
213 | }
214 |
215 | function bid(id){return document.getElementById(id);}
216 |
217 |
--------------------------------------------------------------------------------
/res/mesh/box100.osgjs:
--------------------------------------------------------------------------------
1 | {
2 | "Generator": "OpenSceneGraph 3.5.4",
3 | "Version": 9,
4 | "osg.Node": {
5 | "Children": [ {
6 | "osg.MatrixTransform": {
7 | "UniqueID": 0,
8 | "Name": "c30296831dfb46218b3eee3b15b9c5ca.fbx",
9 | "Children": [ {
10 | "osg.MatrixTransform": {
11 | "UniqueID": 2,
12 | "Name": "RootNode",
13 | "Children": [ {
14 | "osg.MatrixTransform": {
15 | "UniqueID": 5,
16 | "Name": "Cube",
17 | "Children": [ {
18 | "osg.Node": {
19 | "UniqueID": 6,
20 | "Name": "Cube",
21 | "Children": [ {
22 | "osg.Geometry": {
23 | "UniqueID": 7,
24 | "Name": "Cube__0",
25 | "PrimitiveSetList": [ {
26 | "DrawElementsUInt": {
27 | "UniqueID": 13,
28 | "Indices": {
29 | "UniqueID": 14,
30 | "Array": {
31 | "Uint32Array": {
32 | "File": "model_file.bin.gz",
33 | "Size": 15,
34 | "Offset": 0,
35 | "Encoding": "varint"
36 | }
37 | },
38 | "ItemSize": 1,
39 | "Type": "ELEMENT_ARRAY_BUFFER"
40 | },
41 | "Mode": "TRIANGLE_STRIP"
42 | }
43 | } ],
44 | "UserDataContainer": {
45 | "UniqueID": 8,
46 | "Values": [ {
47 | "Name": "attributes",
48 | "Value": "55"
49 | },
50 | {
51 | "Name": "vertex_bits",
52 | "Value": "8"
53 | },
54 | {
55 | "Name": "vertex_mode",
56 | "Value": "3"
57 | },
58 | {
59 | "Name": "uv_0_bits",
60 | "Value": "8"
61 | },
62 | {
63 | "Name": "uv_0_mode",
64 | "Value": "3"
65 | },
66 | {
67 | "Name": "epsilon",
68 | "Value": "0.25"
69 | },
70 | {
71 | "Name": "nphi",
72 | "Value": "720"
73 | },
74 | {
75 | "Name": "triangle_mode",
76 | "Value": "7"
77 | },
78 | {
79 | "Name": "vtx_bbl_x",
80 | "Value": "-100"
81 | },
82 | {
83 | "Name": "vtx_bbl_y",
84 | "Value": "-100"
85 | },
86 | {
87 | "Name": "vtx_bbl_z",
88 | "Value": "-100"
89 | },
90 | {
91 | "Name": "vtx_h_x",
92 | "Value": "1.5748"
93 | },
94 | {
95 | "Name": "vtx_h_y",
96 | "Value": "1.5748"
97 | },
98 | {
99 | "Name": "vtx_h_z",
100 | "Value": "1.5748"
101 | },
102 | {
103 | "Name": "uv_0_bbl_x",
104 | "Value": "0"
105 | },
106 | {
107 | "Name": "uv_0_bbl_y",
108 | "Value": "0"
109 | },
110 | {
111 | "Name": "uv_0_h_x",
112 | "Value": "0.00787402"
113 | },
114 | {
115 | "Name": "uv_0_h_y",
116 | "Value": "0.00787402"
117 | } ]
118 | },
119 | "VertexAttributeList": {
120 | "Normal": {
121 | "UniqueID": 10,
122 | "Array": {
123 | "Uint32Array": {
124 | "File": "model_file.bin.gz",
125 | "Size": 24,
126 | "Offset": 20,
127 | "Encoding": "varint"
128 | }
129 | },
130 | "ItemSize": 2,
131 | "Type": "ARRAY_BUFFER"
132 | },
133 | "Tangent": {
134 | "UniqueID": 12,
135 | "Array": {
136 | "Uint32Array": {
137 | "File": "model_file.bin.gz",
138 | "Size": 24,
139 | "Offset": 100,
140 | "Encoding": "varint"
141 | }
142 | },
143 | "ItemSize": 2,
144 | "Type": "ARRAY_BUFFER"
145 | },
146 | "TexCoord0": {
147 | "UniqueID": 11,
148 | "Array": {
149 | "Int32Array": {
150 | "File": "model_file.bin.gz",
151 | "Size": 24,
152 | "Offset": 172,
153 | "Encoding": "varint"
154 | }
155 | },
156 | "ItemSize": 2,
157 | "Type": "ARRAY_BUFFER"
158 | },
159 | "Vertex": {
160 | "UniqueID": 9,
161 | "Array": {
162 | "Int32Array": {
163 | "File": "model_file.bin.gz",
164 | "Size": 24,
165 | "Offset": 252,
166 | "Encoding": "varint"
167 | }
168 | },
169 | "ItemSize": 3,
170 | "Type": "ARRAY_BUFFER"
171 | }
172 | }
173 | }
174 | },
175 | {
176 | "osg.Geometry": {
177 | "UniqueID": 15,
178 | "Name": "Cube__0",
179 | "PrimitiveSetList": [ {
180 | "DrawElementsUByte": {
181 | "UniqueID": 17,
182 | "Indices": {
183 | "UniqueID": 18,
184 | "Array": {
185 | "Uint8Array": {
186 | "File": "model_file_wireframe.bin.gz",
187 | "Size": 48,
188 | "Offset": 0
189 | }
190 | },
191 | "ItemSize": 1,
192 | "Type": "ELEMENT_ARRAY_BUFFER"
193 | },
194 | "Mode": "LINES"
195 | }
196 | } ],
197 | "UserDataContainer": {
198 | "UniqueID": 16,
199 | "Values": [ {
200 | "Name": "wireframe",
201 | "Value": "1"
202 | },
203 | {
204 | "Name": "attributes",
205 | "Value": "1"
206 | } ]
207 | },
208 | "VertexAttributeList": {
209 | "Vertex": {
210 | "UniqueID": 9
211 | }
212 | }
213 | }
214 | } ]
215 | }
216 | } ],
217 | "Matrix": [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ]
218 | }
219 | } ],
220 | "Matrix": [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ],
221 | "StateSet": {
222 | "osg.StateSet": {
223 | "UniqueID": 3,
224 | "UserDataContainer": {
225 | "UniqueID": 4,
226 | "Values": [ {
227 | "Name": "UniqueID",
228 | "Value": "1"
229 | } ]
230 | }
231 | }
232 | }
233 | }
234 | } ],
235 | "Matrix": [ 1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1 ],
236 | "UserDataContainer": {
237 | "UniqueID": 1,
238 | "Values": [ {
239 | "Name": "source",
240 | "Value": "fbx"
241 | },
242 | {
243 | "Name": "authoring_tool",
244 | "Value": "CINEMA 4D R17"
245 | } ]
246 | }
247 | }
248 | } ]
249 | }
250 | }
--------------------------------------------------------------------------------
/res/mesh/box100.osgjs.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gameknife/electron-shadermonki/a6780567960fc0d0d6a523e8fab951cef1eef72a/res/mesh/box100.osgjs.bin
--------------------------------------------------------------------------------
/res/mesh/quad2.osgjs:
--------------------------------------------------------------------------------
1 | {
2 | "Generator": "OpenSceneGraph 3.5.4",
3 | "Version": 9,
4 | "osg.Node": {
5 | "Children": [ {
6 | "osg.MatrixTransform": {
7 | "UniqueID": 0,
8 | "Name": "fc2211c8bdc74a278e8b80ce09b87a00.fbx",
9 | "Children": [ {
10 | "osg.MatrixTransform": {
11 | "UniqueID": 2,
12 | "Name": "RootNode",
13 | "Children": [ {
14 | "osg.MatrixTransform": {
15 | "UniqueID": 5,
16 | "Name": "Plane_2",
17 | "Children": [ {
18 | "osg.Node": {
19 | "UniqueID": 6,
20 | "Name": "Plane_2",
21 | "Children": [ {
22 | "osg.Geometry": {
23 | "UniqueID": 7,
24 | "Name": "Plane_2__0",
25 | "PrimitiveSetList": [ {
26 | "DrawElementsUByte": {
27 | "UniqueID": 13,
28 | "Indices": {
29 | "UniqueID": 14,
30 | "Array": {
31 | "Uint8Array": {
32 | "File": "model_file.bin.gz",
33 | "Size": 6,
34 | "Offset": 0
35 | }
36 | },
37 | "ItemSize": 1,
38 | "Type": "ELEMENT_ARRAY_BUFFER"
39 | },
40 | "Mode": "TRIANGLE_STRIP"
41 | }
42 | } ],
43 | "UserDataContainer": {
44 | "UniqueID": 8,
45 | "Values": [ {
46 | "Name": "attributes",
47 | "Value": "55"
48 | },
49 | {
50 | "Name": "vertex_bits",
51 | "Value": "8"
52 | },
53 | {
54 | "Name": "vertex_mode",
55 | "Value": "3"
56 | },
57 | {
58 | "Name": "uv_0_bits",
59 | "Value": "8"
60 | },
61 | {
62 | "Name": "uv_0_mode",
63 | "Value": "3"
64 | },
65 | {
66 | "Name": "epsilon",
67 | "Value": "0.25"
68 | },
69 | {
70 | "Name": "nphi",
71 | "Value": "720"
72 | },
73 | {
74 | "Name": "triangle_mode",
75 | "Value": "7"
76 | },
77 | {
78 | "Name": "vtx_bbl_x",
79 | "Value": "-200"
80 | },
81 | {
82 | "Name": "vtx_bbl_y",
83 | "Value": "0"
84 | },
85 | {
86 | "Name": "vtx_bbl_z",
87 | "Value": "-200"
88 | },
89 | {
90 | "Name": "vtx_h_x",
91 | "Value": "3.14961"
92 | },
93 | {
94 | "Name": "vtx_h_y",
95 | "Value": "7.87402e-08"
96 | },
97 | {
98 | "Name": "vtx_h_z",
99 | "Value": "7.08661"
100 | },
101 | {
102 | "Name": "uv_0_bbl_x",
103 | "Value": "0"
104 | },
105 | {
106 | "Name": "uv_0_bbl_y",
107 | "Value": "0"
108 | },
109 | {
110 | "Name": "uv_0_h_x",
111 | "Value": "0.00787402"
112 | },
113 | {
114 | "Name": "uv_0_h_y",
115 | "Value": "0.00787402"
116 | } ]
117 | },
118 | "VertexAttributeList": {
119 | "Normal": {
120 | "UniqueID": 10,
121 | "Array": {
122 | "Uint32Array": {
123 | "File": "model_file.bin.gz",
124 | "Size": 8,
125 | "Offset": 8,
126 | "Encoding": "varint"
127 | }
128 | },
129 | "ItemSize": 2,
130 | "Type": "ARRAY_BUFFER"
131 | },
132 | "Tangent": {
133 | "UniqueID": 12,
134 | "Array": {
135 | "Uint32Array": {
136 | "File": "model_file.bin.gz",
137 | "Size": 8,
138 | "Offset": 40,
139 | "Encoding": "varint"
140 | }
141 | },
142 | "ItemSize": 2,
143 | "Type": "ARRAY_BUFFER"
144 | },
145 | "TexCoord0": {
146 | "UniqueID": 11,
147 | "Array": {
148 | "Int32Array": {
149 | "File": "model_file.bin.gz",
150 | "Size": 8,
151 | "Offset": 64,
152 | "Encoding": "varint"
153 | }
154 | },
155 | "ItemSize": 2,
156 | "Type": "ARRAY_BUFFER"
157 | },
158 | "Vertex": {
159 | "UniqueID": 9,
160 | "Array": {
161 | "Int32Array": {
162 | "File": "model_file.bin.gz",
163 | "Size": 8,
164 | "Offset": 88,
165 | "Encoding": "varint"
166 | }
167 | },
168 | "ItemSize": 3,
169 | "Type": "ARRAY_BUFFER"
170 | }
171 | }
172 | }
173 | },
174 | {
175 | "osg.Geometry": {
176 | "UniqueID": 15,
177 | "Name": "Plane_2__0",
178 | "PrimitiveSetList": [ {
179 | "DrawElementsUByte": {
180 | "UniqueID": 17,
181 | "Indices": {
182 | "UniqueID": 18,
183 | "Array": {
184 | "Uint8Array": {
185 | "File": "model_file_wireframe.bin.gz",
186 | "Size": 16,
187 | "Offset": 0
188 | }
189 | },
190 | "ItemSize": 1,
191 | "Type": "ELEMENT_ARRAY_BUFFER"
192 | },
193 | "Mode": "LINES"
194 | }
195 | } ],
196 | "UserDataContainer": {
197 | "UniqueID": 16,
198 | "Values": [ {
199 | "Name": "wireframe",
200 | "Value": "1"
201 | },
202 | {
203 | "Name": "attributes",
204 | "Value": "1"
205 | } ]
206 | },
207 | "VertexAttributeList": {
208 | "Vertex": {
209 | "UniqueID": 9
210 | }
211 | }
212 | }
213 | } ]
214 | }
215 | } ],
216 | "Matrix": [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, -500, 1 ]
217 | }
218 | } ],
219 | "Matrix": [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ],
220 | "StateSet": {
221 | "osg.StateSet": {
222 | "UniqueID": 3,
223 | "UserDataContainer": {
224 | "UniqueID": 4,
225 | "Values": [ {
226 | "Name": "UniqueID",
227 | "Value": "1"
228 | } ]
229 | }
230 | }
231 | }
232 | }
233 | } ],
234 | "Matrix": [ 1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1 ],
235 | "UserDataContainer": {
236 | "UniqueID": 1,
237 | "Values": [ {
238 | "Name": "source",
239 | "Value": "fbx"
240 | },
241 | {
242 | "Name": "authoring_tool",
243 | "Value": "CINEMA 4D R17"
244 | } ]
245 | }
246 | }
247 | } ]
248 | }
249 | }
--------------------------------------------------------------------------------
/res/mesh/quad2.osgjs.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gameknife/electron-shadermonki/a6780567960fc0d0d6a523e8fab951cef1eef72a/res/mesh/quad2.osgjs.bin
--------------------------------------------------------------------------------
/res/mesh/venusl.c4d:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gameknife/electron-shadermonki/a6780567960fc0d0d6a523e8fab951cef1eef72a/res/mesh/venusl.c4d
--------------------------------------------------------------------------------
/res/shader/base_fs.glsl:
--------------------------------------------------------------------------------
1 | /*
2 | _MainTex ('Main Texture', 2D) = 'white'
3 | _AlphaTex ('Alpha Texture', 2D) = 'white'
4 | */
5 | precision mediump float;
6 | uniform sampler2D _MainTex;
7 | uniform sampler2D _AlphaTex;
8 | uniform sampler2D _GlobalOccMap;
9 | uniform sampler2D _GlobalDepthMap;
10 | uniform sampler2D _GlobalShadowMap;
11 | varying vec2 vTexCoord;
12 | varying vec3 vNormal;
13 | varying vec4 vLightHPos;
14 | varying vec4 vHpos;
15 |
16 | uniform float _TIME;
17 | uniform vec4 _LIGHTDIR;
18 |
19 | #define BIA 0.0003
20 | #define SHADOWMAP_SIZE (1.0 / 1024.0)
21 |
22 | float DecodeFloatRGBA(vec4 enc){
23 | vec4 kDecodeDot = vec4(1.0,1.0/255.0,1.0/65025.0,1.0/160581375.0);
24 | return dot(enc, kDecodeDot);
25 | }
26 | float frac(float t)
27 | {
28 | return t - floor(t);
29 | }
30 |
31 | float snoise(vec2 co){
32 | return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
33 | }
34 |
35 | float sampleShadow(vec3 light_hpos)
36 | {
37 | float noise = fract(_TIME);
38 | float noiseMap = snoise(vTexCoord.xy + vec2(noise,noise)) * 1.0;
39 | vec2 normal = vec2(noiseMap, 1.0 - noiseMap);
40 | //normal = normalize(normal);
41 | vec4 shadow4;
42 |
43 | shadow4.x = sign(texture2D(_GlobalShadowMap, light_hpos.xy * 0.5
44 | + vec2(0.5,0.5)
45 | + reflect( normal, vec2(1,0))
46 | * SHADOWMAP_SIZE).r - (light_hpos.z * 0.5 + 0.5) + BIA);
47 |
48 | shadow4.y = sign(texture2D(_GlobalShadowMap, light_hpos.xy * 0.5
49 | + vec2(0.5,0.5)
50 | + reflect( normal, vec2(-1,0))
51 | * SHADOWMAP_SIZE).r - (light_hpos.z * 0.5 + 0.5) + BIA);
52 | shadow4.z = sign(texture2D(_GlobalShadowMap, light_hpos.xy * 0.5
53 | + vec2(0.5,0.5)
54 | + reflect( normal, vec2(0,1))
55 | * SHADOWMAP_SIZE).r - (light_hpos.z * 0.5 + 0.5) + BIA);
56 | shadow4.w = sign(texture2D(_GlobalShadowMap, light_hpos.xy * 0.5
57 | + vec2(0.5,0.5)
58 | + reflect( normal, vec2(0,-1))
59 | * SHADOWMAP_SIZE).r - (light_hpos.z * 0.5 + 0.5) + BIA);
60 |
61 | return max(0.0, dot(shadow4, vec4(0.25)) );
62 | }
63 | void main(){
64 |
65 | // shadow
66 | vec3 light_hpos = vLightHPos.xyz / vLightHPos.w;
67 | float shadow = sampleShadow(light_hpos);
68 |
69 | // occlusion
70 | vec2 hposuv = vHpos.xy / vHpos.w;
71 | float occ = texture2D(_GlobalOccMap, hposuv).x;
72 |
73 | vec4 samplerColor1 = vec4(frac(vTexCoord.x + _TIME),frac(vTexCoord.y + _TIME),0,1);
74 | vec4 samplerColor2 = vec4(vNormal * vec3(0.5,0.5,0.5) + vec3(0.5,0.5,0.5),1);
75 | float ndotl = max(0.0, dot(_LIGHTDIR.xyz, vNormal));
76 | vec4 samplerColor = texture2D(_MainTex, vTexCoord.xy);
77 | vec4 alphaSamplerColor = texture2D(_AlphaTex, vTexCoord.xy);
78 | samplerColor *= samplerColor;
79 | samplerColor.a *= alphaSamplerColor.r * alphaSamplerColor.a;
80 | if(samplerColor.a < 0.05) discard;
81 | samplerColor = samplerColor * (ndotl * shadow + vec4(0.2,0.3,0.7,1.0) * (vNormal.y * 0.4 + 0.6)) * occ;
82 | //samplerColor.rgb = vec3(occ,occ,occ);
83 | samplerColor.a = 1.0;
84 | //gl_FragColor = vec4(depthA,depthA,depthA,1.0);
85 | gl_FragColor = sqrt(samplerColor);
86 | }
87 |
--------------------------------------------------------------------------------
/res/shader/base_vs.glsl:
--------------------------------------------------------------------------------
1 | attribute vec2 texcoord;
2 | attribute vec3 normal;
3 | attribute vec3 position;
4 | uniform mat4 _MVP;
5 | uniform mat4 _MV;
6 | uniform mat4 _M2W;
7 | uniform mat4 _MVP_LIGHT;
8 |
9 | varying vec2 vTexCoord;
10 | varying vec3 vNormal;
11 | varying vec4 vLightHPos;
12 | varying vec4 vHpos;
13 |
14 | void main()
15 | {
16 | vTexCoord = (position * 0.075).xy;
17 | vTexCoord = texcoord;
18 | vNormal = (_M2W * vec4(normal, 0.0)).xyz;
19 | vLightHPos = _MV * vec4(position, 1.0);
20 | vLightHPos = _MVP_LIGHT * vLightHPos;
21 |
22 | /*gl_Position = vec4(position, 1.0);*/
23 | gl_Position = _MVP * vec4(position, 1.0);
24 |
25 | vHpos = gl_Position;
26 | vHpos.xy *= -1.0;
27 | vHpos.xyz = (vHpos.w - vHpos.xyz) * 0.5;
28 | }
--------------------------------------------------------------------------------
/res/texture/ground.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gameknife/electron-shadermonki/a6780567960fc0d0d6a523e8fab951cef1eef72a/res/texture/ground.jpg
--------------------------------------------------------------------------------
/res/texture/leaf.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gameknife/electron-shadermonki/a6780567960fc0d0d6a523e8fab951cef1eef72a/res/texture/leaf.png
--------------------------------------------------------------------------------
/res/texture/matcap.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gameknife/electron-shadermonki/a6780567960fc0d0d6a523e8fab951cef1eef72a/res/texture/matcap.jpg
--------------------------------------------------------------------------------
/res/texture/plaster.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gameknife/electron-shadermonki/a6780567960fc0d0d6a523e8fab951cef1eef72a/res/texture/plaster.jpg
--------------------------------------------------------------------------------
/res/texture/white.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gameknife/electron-shadermonki/a6780567960fc0d0d6a523e8fab951cef1eef72a/res/texture/white.jpg
--------------------------------------------------------------------------------
/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gameknife/electron-shadermonki/a6780567960fc0d0d6a523e8fab951cef1eef72a/screenshot.png
--------------------------------------------------------------------------------
/style.css:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | * {
4 | margin: 0px;
5 | padding: 0px;
6 | }
7 |
8 | html, body {
9 | font-family: 'arial','sans-serif','Monaco',monospace;
10 | width: 100%;
11 | height: 100%;
12 | min-width: 1024px;
13 | overflow: hidden;
14 | }
15 |
16 | #toolbar {
17 | background-color: #222;
18 | width: 100%;
19 | height: 36px;
20 | position: absolute;
21 | z-index: 10;
22 | box-shadow: 0 1px 2px rgba(0,0,0,.85),inset 0 1px 0 rgba(255,255,255,.15)
23 | }
24 | #toolbar .grp_control {
25 | width: 154px;
26 | margin: 0 auto;
27 | }
28 |
29 | .btn_wide {
30 |
31 | margin: 5px 10px;
32 | line-height: 28px;
33 | border: 1px solid #333;
34 | border-radius: 4px;
35 |
36 | box-shadow: 0 1px 2px rgba(0,0,0,.05),inset 0 1px 1px rgba(255,255,255,.25);
37 | color: #fff;
38 | font-size: 10px;
39 | text-align: center;
40 | outline: 0;
41 | cursor: pointer;
42 | -webkit-transition: all .2s ease-in-out;
43 | transition: all .2s ease-in-out;
44 |
45 | background: #444;
46 | background: -webkit-linear-gradient(top,#444,#333);
47 | background: linear-gradient(to bottom,#444,#333);
48 | }
49 |
50 | .btn_play, .btn_play_on, .btn_square, .btn_square_on {
51 |
52 | line-height: 28px;
53 | margin-top: 4px;
54 | border: 1px solid #333;
55 | border-radius: 4px;
56 |
57 | box-shadow: 0 1px 2px rgba(0,0,0,.05),inset 0 1px 1px rgba(255,255,255,.25);
58 | color: #fff;
59 | font-size: 10px;
60 | text-align: center;
61 | outline: 0;
62 | cursor: pointer;
63 | -webkit-transition: all .2s ease-in-out;
64 | transition: all .2s ease-in-out;
65 |
66 | background: #444;
67 | background: -webkit-linear-gradient(top,#444,#333);
68 | background: linear-gradient(to bottom,#444,#333);
69 | }
70 |
71 | .btn_square, .btn_square_on {
72 | width: 28px;
73 | height: 28px;
74 | font-size: 12px;
75 | }
76 |
77 | .btn_play, .btn_play_on {
78 | width: 48px;
79 | height: 28px;
80 | }
81 |
82 | .btn_play_on, .btn_square_on {
83 | background: #47c;
84 | background: -webkit-linear-gradient(top,#47c,#46a);
85 | background: linear-gradient(to bottom,#47c,#46a);
86 | }
87 |
88 | .btn_play:hover, .btn_square:hover {
89 | color: #47c;
90 | background: -webkit-linear-gradient(top,#333,#444);
91 | background: linear-gradient(to bottom,#333,#444);
92 | }
93 |
94 | .btn_play_on:hover, .btn_square_on:hover {
95 | color: #222;
96 | background: -webkit-linear-gradient(top,#46a,#47c);
97 | background: linear-gradient(to bottom,#46a,#47c);
98 | }
99 |
100 | #mainframe {
101 | background-color: #333;
102 | width: 100%;
103 | top: 36px;
104 | bottom: 20px;
105 | position: absolute;
106 |
107 | display: flex;
108 | flex-direction: row;
109 | }
110 |
111 | #status_bar {
112 | border: 1px solid #111;
113 | background-color: #222;
114 | width: 100%;
115 | margin-top: 20px;
116 | bottom: 0;
117 | position: absolute;
118 |
119 | z-index: -10;
120 | }
121 |
122 | #status_bar .status-content {
123 | color: #ccc;
124 | font-size: 13px;
125 | margin: 2px 0;
126 | }
127 |
128 | #left {
129 | background-color: #333;
130 | width: 512px;
131 |
132 | display: flex;
133 | flex-direction: column;
134 | }
135 |
136 | #left .canvas-frame {
137 | height: 536px;
138 | position: relative;
139 | }
140 |
141 | #left .canvas-ctlbtn {
142 | position: absolute;
143 | top: 20px;
144 | width: 512px;
145 | height: 30px;
146 | }
147 |
148 | #left .canvas-ctlbtn-cgrp {
149 | position: relative;
150 | top: -512px;
151 | width: 100px;
152 | margin: 0 auto;
153 | }
154 |
155 | #left .canvas-ctlbtn-rgrp {
156 | position: relative;
157 | top: -340px;
158 | left: 480px;
159 | width: 34px;
160 | height: 120px;
161 | }
162 |
163 | #left .console-frame {
164 | flex: 1;
165 |
166 | display: flex;
167 | flex-direction: column;
168 | }
169 |
170 | .obj-container {
171 | flex: 1;
172 | background-color: #333;
173 | overflow:scroll;
174 | }
175 |
176 | .obj-container::-webkit-scrollbar {
177 | width: 12px;
178 | }
179 |
180 | .obj-container::-webkit-scrollbar-track {
181 | border-radius: 1px;
182 | border: 1px #111;
183 | background-color: #222;
184 | }
185 |
186 | .obj-container::-webkit-scrollbar-thumb {
187 | border-radius: 1px;
188 | border: 1px #222;
189 | background-color: #111;
190 | }
191 |
192 | .obj-container::-webkit-scrollbar-corner {
193 | border-radius: 1px;
194 | border: 1px #111;
195 | background-color: #222;
196 | }
197 |
198 | .obj-line, .obj-line-checked {
199 | line-height: 16px;
200 | padding: 2px 10px;
201 | border: hidden;
202 |
203 | color: #aaa;
204 | font-size: 14px;
205 | text-align: center;
206 | outline: 0;
207 | cursor: pointer;
208 |
209 | -webkit-transition: all .1s ease-in-out;
210 | transition: all .1s ease-in-out;
211 |
212 | background: #333;
213 |
214 | white-space: nowrap;
215 | }
216 |
217 | .obj-line-checked {
218 | color: #fff;
219 | background: #47c;
220 | }
221 | .obj-line:hover {
222 | color: #fff;
223 | }
224 |
225 | #left .log-line-s {
226 | padding: 2px 10px;
227 | background-color: #2a2a2a;
228 | color: #fff;
229 | font-size: 12px;
230 | }
231 |
232 | #left .log-line-d {
233 | padding: 2px 10px;
234 | background-color: #222;
235 | color: #fff;
236 | font-size: 12px;
237 | }
238 |
239 | #parameter-bar {
240 | height: 100%;
241 | width: 200px;
242 | display: flex;
243 | flex-direction: column;
244 | }
245 |
246 | #right {
247 | height: 100%;
248 | flex: 2;
249 | display: flex;
250 | flex-direction: column;
251 | }
252 |
253 | #project-bar {
254 | height: 100%;
255 | width: 200px;
256 | display: flex;
257 | flex-direction: column;
258 | }
259 |
260 | .resobj-contain {
261 | padding: 2px 10px;
262 | }
263 |
264 | #right .editor-frame {
265 | background-color: #333;
266 | font-size: 14px;
267 | box-shadow: 0 1px 2px rgba(0,0,0,.85),inset 0 1px 0 rgba(255,255,255,.15);
268 | flex: 1;
269 | display: flex;
270 | flex-direction: column;
271 | /*display: none;*/
272 | }
273 |
274 | #right .editor {
275 | font-family: 'consolas', 'Menlo', monospace;
276 | color: #fff;
277 | background-color: #333;
278 | font-size: 12px;
279 | line-height: 1.25;
280 | flex: 1;
281 | /*display: none;*/
282 | }
283 |
284 | .title-bar, .title-bar-modify, .title-bar-saved {
285 | padding: 4px 10px;
286 | background-color: #444;
287 | color: #fff;
288 | font-weight: bold;
289 | font-size: 12px;
290 | }
291 |
292 | .title-bar-modify {
293 | background-color: #a43;
294 | }
295 |
296 | .title-bar-saved {
297 | background-color: #4a3;
298 | }
299 |
300 | .parameter-group {
301 | margin: 10px 2px;
302 | padding: 2px 2px;
303 | color: #777;
304 | font-size: 12px;
305 | box-shadow: 0 4px 2px rgba(0,0,0,.15);
306 | background: #373737;
307 | border: 1px dotted #777;
308 | }
309 |
310 | .droped-title {
311 | margin: 0px 0px;
312 | padding: 2px 5px;
313 | color: #47c;
314 | font-size: 12px;
315 | font-weight: bold;
316 | background: linear-gradient(to right,#222,#2a2a2a);
317 | }
318 |
319 | .droped-container {
320 |
321 | padding: 10px 5px;
322 | margin: 2px 10px 2px 10px;
323 | min-height: 20px;
324 | border: 1px dotted #777;
325 | border-radius: 2px;
326 |
327 | box-shadow: inset -4px -4px rgba(0,0,0,.05),inset 0 4px 2px rgba(0,0,0,.05);
328 | color: #fff;
329 | font-size: 12px;
330 | text-align: center;
331 | outline: 0;
332 | cursor: pointer;
333 | -webkit-transition: all .2s ease-in-out;
334 | transition: all .2s ease-in-out;
335 |
336 | background: #333;
337 | }
338 |
339 | .dotted-container {
340 |
341 | padding: 10px 60px;
342 | margin: 2px 10px 2px 10px;
343 | min-height: 20px;
344 | border: 1px dotted #777;
345 | border-radius: 2px;
346 |
347 | box-shadow: inset -4px -4px rgba(0,0,0,.05),inset 0 4px 2px rgba(0,0,0,.05);
348 | color: #fff;
349 | font-size: 12px;
350 | text-align: center;
351 | outline: 0;
352 | cursor: pointer;
353 | -webkit-transition: all .2s ease-in-out;
354 | transition: all .2s ease-in-out;
355 |
356 | background: #333;
357 | }
358 |
359 | .interactive-frame {
360 | cursor: pointer;
361 | }
362 |
363 | #fullscreen {
364 | position: absolute;
365 | top: 35px;
366 | bottom: 0px;
367 | left: 0px;
368 | right: 0px;
369 | z-index: 10;
370 | background: #333;
371 | color: #fff;
372 | display: inherit;
373 | }
--------------------------------------------------------------------------------
/test/loader-osgjs.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by kaimingyi on 2016/11/20.
3 | */
4 | var test = require('tape');
5 | var loader_osgjs = require('../lib/loader/loader-osgjs.js');
6 |
7 | test('loader-osgjs', function (t) {
8 | t.plan(1);
9 |
10 | loader_osgjs.load( "./res/package/blacksmith/model.osgjs", "./res/package/blacksmith/model.osgjs.bin", function(res) {
11 | //t.message( res );
12 | } );
13 |
14 | t.equal(1, 1);
15 | });
--------------------------------------------------------------------------------
/test/package-build.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by gameKnife on 2016/11/26.
3 | */
4 | var test = require('tape');
5 | var fs = require('fs-extra');
6 | var path = require('path');
7 | var http = require('http');
8 | var https = require('https');
9 | var zlib = require('zlib');
10 | test('package-build', function (t) {
11 | t.plan(1);
12 |
13 | console.info('shader monki package builder v0.1');
14 |
15 | let packageWaitForBuild = [];
16 |
17 | let filelist = fs.walkSync('res/package/');
18 | filelist.forEach( item => {
19 |
20 | item = path.normalize(item);
21 | let filename = path.basename( item );
22 | let dirname = path.dirname(item);
23 | let relpath = path.relative( 'res/package/', dirname );
24 | let extname = path.extname(item);
25 | let purefilename = path.basename( item, extname );
26 | if(extname == '.spkg')
27 | {
28 | let pkgDir = path.join( dirname , purefilename);
29 |
30 | try {
31 | console.info('spkg found: ' + pkgDir);
32 | fs.accessSync(pkgDir, fs.F_OK);
33 |
34 | // TODO to remove
35 | packageWaitForBuild.push(item);
36 | } catch (e) {
37 | // It isn't accessible
38 |
39 | // push it & mkdir
40 | try {
41 | fs.mkdirSync(pkgDir);
42 | packageWaitForBuild.push(item);
43 | }
44 | catch (e){
45 | console.error('spkg dir create failed!!!');
46 | }
47 | }
48 |
49 |
50 | }
51 | });
52 |
53 | //console.info(packageWaitForBuild);
54 |
55 | packageWaitForBuild.forEach( spkgpath => {
56 | try {
57 |
58 | let buffer = fs.readFileSync(spkgpath);
59 | let text = buffer.toString();
60 | let pkgJSON = JSON.parse(text);
61 | //console.info(pkgJSON);
62 |
63 | let extname = path.extname(spkgpath);
64 | let purefilename = path.basename( spkgpath, extname );
65 | let dirname = path.dirname(spkgpath);
66 | let pkgDir = path.join( dirname , purefilename);
67 | ParsePkg(pkgJSON, pkgDir);
68 |
69 | } catch (e) {
70 |
71 | }
72 |
73 | } );
74 |
75 | t.equal(1, 1);
76 | });
77 |
78 | function DownloadFile(dir, osgfile, downloadfile) {
79 |
80 | let absDir = path.join(dir, downloadfile);
81 | try {
82 | fs.accessSync(absDir, fs.F_OK);
83 | } catch (e) {
84 | var file = fs.createWriteStream(absDir);
85 | var request = https.get(osgfile, function (response) {
86 |
87 | switch (response.headers['content-encoding']) {
88 | // or, just use zlib.createUnzip() to handle both cases
89 | case 'gzip':
90 | response.pipe(zlib.createGunzip()).pipe(file);
91 | break;
92 | case 'deflate':
93 | response.pipe(zlib.createInflate()).pipe(file);
94 | break;
95 | default:
96 | response.pipe(file);
97 | break;
98 | }
99 |
100 | var len = parseInt(response.headers['content-length'], 10);
101 | var body = "";
102 | var cur = 0;
103 | var total = len / 1048576; //1048576 - bytes in 1Megabyte
104 |
105 | response.on("data", function(chunk) {
106 | body += chunk;
107 | cur += chunk.length;
108 |
109 | let outData = "Downloading " + downloadfile + ' - ' + (100.0 * cur / len).toFixed(2) + "% ";
110 | console.log(outData);
111 | });
112 |
113 | response.on("end", function() {
114 |
115 | });
116 | });
117 | }
118 | }
119 | function ParsePkg( pkgObject, dir ){
120 | //console.info(pkgObject);
121 | console.info('pkg building...\nwork dir: ' + dir);
122 |
123 | // mesh files
124 | let osgfile = pkgObject.files[0].osgjsUrl;
125 | let osgModelfile = osgfile.replace('file.osgjs.gz', 'model_file.bin.gz');
126 | DownloadFile(dir, osgfile, 'model.osgjs');
127 | DownloadFile(dir, osgModelfile, 'model.osgjs.bin');
128 |
129 | // material files
130 | let options = pkgObject.options;
131 | let materials = options.materials;
132 |
133 | for( let mat in materials )
134 | {
135 | let matnode = materials[mat];
136 |
137 | let mattext = JSON.stringify(matnode);
138 | var file = fs.createWriteStream(path.join(dir, matnode.name + '.mat'));
139 | file.write(mattext);
140 | file.close();
141 |
142 |
143 | // download all textures
144 | for( let channel in matnode.channels)
145 | {
146 | //console.info(matnode);
147 | let channelnode = matnode.channels[channel];
148 | if( channelnode.texture )
149 | {
150 | let image = channelnode.texture.image;
151 | let name = image.name;
152 | let images = image.images;
153 |
154 | let toplodurl = '';
155 | let maxWidth = 0;
156 | for( let i=0; i < images.length; ++i)
157 | {
158 | let currImage = images[i];
159 | if( currImage.width > maxWidth )
160 | {
161 | maxWidth = currImage.width;
162 | toplodurl = currImage.url;
163 | }
164 | }
165 | let ext = path.extname(toplodurl);
166 | DownloadFile( dir, toplodurl, name + ext );
167 |
168 | }
169 | }
170 | }
171 |
172 | }
173 |
174 |
--------------------------------------------------------------------------------
/test/pkg-postprocess.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by kaimingyi on 2016/11/20.
3 | */
4 | var test = require('tape');
5 | var fs = require('fs');
6 | var path = require('path');
7 |
8 | test('loader-osgjs', function (t) {
9 | t.plan(1);
10 |
11 | let basepath = 'res/package/game/';
12 |
13 | fs.readFile(basepath + 'list.txt', 'utf-8', function(err, data) {
14 | if(err)
15 | {
16 |
17 | }
18 | else
19 | {
20 | let text = data.toString();
21 |
22 | let imgs = text.split('\r\n');
23 | imgs.forEach(img => {
24 |
25 | let side = img.split('#');
26 | let orgfile = path.basename(side[0]);
27 | let newfile = side[1];
28 | console.info(basepath + orgfile + ' : ' + basepath + newfile);
29 | if(orgfile && newfile)
30 | {
31 | //console.info(basepath + orgfile + ' : ' + basepath + newfile);
32 | //if(fs.existsSync(basepath + orgfile) )
33 | {
34 | fs.rename( basepath + orgfile, basepath + newfile );
35 | }
36 | }
37 | });
38 |
39 | //if(fs.existsSync(basepath + 'file.osgjs.gz') )
40 | {
41 | fs.rename( basepath + 'file.osgjs.gz', basepath + 'model.osgjs' );
42 | fs.rename( basepath + 'model_file.bin.gz', basepath + 'model.osgjs.bin' );
43 | }
44 |
45 | }
46 | });
47 |
48 |
49 | t.equal(1, 1);
50 | });
--------------------------------------------------------------------------------