├── .gitignore
├── .npmignore
├── LICENSE.md
├── README.md
├── dist
├── css
│ └── normalise.css
├── index.html
└── js
│ └── bundle.js
├── index.html
├── package.json
└── src
├── App.js
├── glsl
├── basic_frag.glsl
└── basic_vert.glsl
├── index.js
└── post-processing
├── EffectComposer.js
└── glsl
├── fxaa.glsl
├── gamma.glsl
├── screen_frag.glsl
└── screen_vert.glsl
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | npm-debug.log
3 | .DS_Store
4 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | npm-debug.log
3 | .DS_Store
4 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (c) 2002-2016 Silvio Paganini
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ### Rapid Prototyping boilerplate
2 |
3 | Using ES6 and babelify transform
4 |
5 | #### Dependencies
6 | * babelify
7 | * budo
8 | * dat-gui
9 | * garnish
10 | * stats-js
11 | * three
12 | * three-orbit-controls
13 | * watchify
14 |
15 | ## Rapid proto command line tool
16 |
17 | [![NPM version][npm-image]][npm-url]
18 | [![Downloads][downloads-image]][npm-url]
19 | [![js-standard-style][standard-image]][standard-url]
20 |
21 | #### Install
22 |
23 | Need to install globally in order to have the command available everywhere.
24 |
25 | ```bash
26 | [sudo] npm -g install rapid-proto
27 | ```
28 |
29 | ##### Full Documentation
30 | [https://github.com/silviopaganini/rapid-proto](https://github.com/silviopaganini/rapid-proto)
31 |
32 | ## Usage:
33 | ```bash
34 | rp nameOfThePrototype
35 | ```
36 |
37 | Or just checkout the repo and start the server
38 |
39 | ```
40 | git clone
41 | npm install
42 | npm start
43 | ```
44 |
45 | ### credits
46 | [@mattdesl](https://github.com/mattdesl)
47 |
48 | [npm-image]: https://img.shields.io/npm/v/rapid-proto.svg?style=flat-square
49 | [npm-url]: https://npmjs.org/package/rapid-proto
50 | [downloads-image]: http://img.shields.io/npm/dm/rapid-proto.svg?style=flat-square
51 | [standard-image]: https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square
52 | [standard-url]: https://github.com/feross/standard
--------------------------------------------------------------------------------
/dist/css/normalise.css:
--------------------------------------------------------------------------------
1 | /*! normalize.css v3.0.2 | MIT License | git.io/normalize */
2 |
3 | /**
4 | * 1. Set default font family to sans-serif.
5 | * 2. Prevent iOS text size adjust after orientation change, without disabling
6 | * user zoom.
7 | */
8 |
9 | html {
10 | font-family: sans-serif; /* 1 */
11 | -ms-text-size-adjust: 100%; /* 2 */
12 | -webkit-text-size-adjust: 100%; /* 2 */
13 | }
14 |
15 | /**
16 | * Remove default margin.
17 | */
18 |
19 | body {
20 | margin: 0;
21 | }
22 |
23 | /* HTML5 display definitions
24 | ========================================================================== */
25 |
26 | /**
27 | * Correct `block` display not defined for any HTML5 element in IE 8/9.
28 | * Correct `block` display not defined for `details` or `summary` in IE 10/11
29 | * and Firefox.
30 | * Correct `block` display not defined for `main` in IE 11.
31 | */
32 |
33 | article,
34 | aside,
35 | details,
36 | figcaption,
37 | figure,
38 | footer,
39 | header,
40 | hgroup,
41 | main,
42 | menu,
43 | nav,
44 | section,
45 | summary {
46 | display: block;
47 | }
48 |
49 | /**
50 | * 1. Correct `inline-block` display not defined in IE 8/9.
51 | * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
52 | */
53 |
54 | audio,
55 | canvas,
56 | progress,
57 | video {
58 | display: inline-block; /* 1 */
59 | vertical-align: baseline; /* 2 */
60 | }
61 |
62 | /**
63 | * Prevent modern browsers from displaying `audio` without controls.
64 | * Remove excess height in iOS 5 devices.
65 | */
66 |
67 | audio:not([controls]) {
68 | display: none;
69 | height: 0;
70 | }
71 |
72 | /**
73 | * Address `[hidden]` styling not present in IE 8/9/10.
74 | * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.
75 | */
76 |
77 | [hidden],
78 | template {
79 | display: none;
80 | }
81 |
82 | /* Links
83 | ========================================================================== */
84 |
85 | /**
86 | * Remove the gray background color from active links in IE 10.
87 | */
88 |
89 | a {
90 | background-color: transparent;
91 | }
92 |
93 | /**
94 | * Improve readability when focused and also mouse hovered in all browsers.
95 | */
96 |
97 | a:active,
98 | a:hover {
99 | outline: 0;
100 | }
101 |
102 | /* Text-level semantics
103 | ========================================================================== */
104 |
105 | /**
106 | * Address styling not present in IE 8/9/10/11, Safari, and Chrome.
107 | */
108 |
109 | abbr[title] {
110 | border-bottom: 1px dotted;
111 | }
112 |
113 | /**
114 | * Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
115 | */
116 |
117 | b,
118 | strong {
119 | font-weight: bold;
120 | }
121 |
122 | /**
123 | * Address styling not present in Safari and Chrome.
124 | */
125 |
126 | dfn {
127 | font-style: italic;
128 | }
129 |
130 | /**
131 | * Address variable `h1` font-size and margin within `section` and `article`
132 | * contexts in Firefox 4+, Safari, and Chrome.
133 | */
134 |
135 | h1 {
136 | font-size: 2em;
137 | margin: 0.67em 0;
138 | }
139 |
140 | /**
141 | * Address styling not present in IE 8/9.
142 | */
143 |
144 | mark {
145 | background: #ff0;
146 | color: #000;
147 | }
148 |
149 | /**
150 | * Address inconsistent and variable font size in all browsers.
151 | */
152 |
153 | small {
154 | font-size: 80%;
155 | }
156 |
157 | /**
158 | * Prevent `sub` and `sup` affecting `line-height` in all browsers.
159 | */
160 |
161 | sub,
162 | sup {
163 | font-size: 75%;
164 | line-height: 0;
165 | position: relative;
166 | vertical-align: baseline;
167 | }
168 |
169 | sup {
170 | top: -0.5em;
171 | }
172 |
173 | sub {
174 | bottom: -0.25em;
175 | }
176 |
177 | /* Embedded content
178 | ========================================================================== */
179 |
180 | /**
181 | * Remove border when inside `a` element in IE 8/9/10.
182 | */
183 |
184 | img {
185 | border: 0;
186 | }
187 |
188 | /**
189 | * Correct overflow not hidden in IE 9/10/11.
190 | */
191 |
192 | svg:not(:root) {
193 | overflow: hidden;
194 | }
195 |
196 | /* Grouping content
197 | ========================================================================== */
198 |
199 | /**
200 | * Address margin not present in IE 8/9 and Safari.
201 | */
202 |
203 | figure {
204 | margin: 1em 40px;
205 | }
206 |
207 | /**
208 | * Address differences between Firefox and other browsers.
209 | */
210 |
211 | hr {
212 | -moz-box-sizing: content-box;
213 | box-sizing: content-box;
214 | height: 0;
215 | }
216 |
217 | /**
218 | * Contain overflow in all browsers.
219 | */
220 |
221 | pre {
222 | overflow: auto;
223 | }
224 |
225 | /**
226 | * Address odd `em`-unit font size rendering in all browsers.
227 | */
228 |
229 | code,
230 | kbd,
231 | pre,
232 | samp {
233 | font-family: monospace, monospace;
234 | font-size: 1em;
235 | }
236 |
237 | /* Forms
238 | ========================================================================== */
239 |
240 | /**
241 | * Known limitation: by default, Chrome and Safari on OS X allow very limited
242 | * styling of `select`, unless a `border` property is set.
243 | */
244 |
245 | /**
246 | * 1. Correct color not being inherited.
247 | * Known issue: affects color of disabled elements.
248 | * 2. Correct font properties not being inherited.
249 | * 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
250 | */
251 |
252 | button,
253 | input,
254 | optgroup,
255 | select,
256 | textarea {
257 | color: inherit; /* 1 */
258 | font: inherit; /* 2 */
259 | margin: 0; /* 3 */
260 | }
261 |
262 | /**
263 | * Address `overflow` set to `hidden` in IE 8/9/10/11.
264 | */
265 |
266 | button {
267 | overflow: visible;
268 | }
269 |
270 | /**
271 | * Address inconsistent `text-transform` inheritance for `button` and `select`.
272 | * All other form control elements do not inherit `text-transform` values.
273 | * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
274 | * Correct `select` style inheritance in Firefox.
275 | */
276 |
277 | button,
278 | select {
279 | text-transform: none;
280 | }
281 |
282 | /**
283 | * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
284 | * and `video` controls.
285 | * 2. Correct inability to style clickable `input` types in iOS.
286 | * 3. Improve usability and consistency of cursor style between image-type
287 | * `input` and others.
288 | */
289 |
290 | button,
291 | html input[type="button"], /* 1 */
292 | input[type="reset"],
293 | input[type="submit"] {
294 | -webkit-appearance: button; /* 2 */
295 | cursor: pointer; /* 3 */
296 | }
297 |
298 | /**
299 | * Re-set default cursor for disabled elements.
300 | */
301 |
302 | button[disabled],
303 | html input[disabled] {
304 | cursor: default;
305 | }
306 |
307 | /**
308 | * Remove inner padding and border in Firefox 4+.
309 | */
310 |
311 | button::-moz-focus-inner,
312 | input::-moz-focus-inner {
313 | border: 0;
314 | padding: 0;
315 | }
316 |
317 | /**
318 | * Address Firefox 4+ setting `line-height` on `input` using `!important` in
319 | * the UA stylesheet.
320 | */
321 |
322 | input {
323 | line-height: normal;
324 | }
325 |
326 | /**
327 | * It's recommended that you don't attempt to style these elements.
328 | * Firefox's implementation doesn't respect box-sizing, padding, or width.
329 | *
330 | * 1. Address box sizing set to `content-box` in IE 8/9/10.
331 | * 2. Remove excess padding in IE 8/9/10.
332 | */
333 |
334 | input[type="checkbox"],
335 | input[type="radio"] {
336 | box-sizing: border-box; /* 1 */
337 | padding: 0; /* 2 */
338 | }
339 |
340 | /**
341 | * Fix the cursor style for Chrome's increment/decrement buttons. For certain
342 | * `font-size` values of the `input`, it causes the cursor style of the
343 | * decrement button to change from `default` to `text`.
344 | */
345 |
346 | input[type="number"]::-webkit-inner-spin-button,
347 | input[type="number"]::-webkit-outer-spin-button {
348 | height: auto;
349 | }
350 |
351 | /**
352 | * 1. Address `appearance` set to `searchfield` in Safari and Chrome.
353 | * 2. Address `box-sizing` set to `border-box` in Safari and Chrome
354 | * (include `-moz` to future-proof).
355 | */
356 |
357 | input[type="search"] {
358 | -webkit-appearance: textfield; /* 1 */
359 | -moz-box-sizing: content-box;
360 | -webkit-box-sizing: content-box; /* 2 */
361 | box-sizing: content-box;
362 | }
363 |
364 | /**
365 | * Remove inner padding and search cancel button in Safari and Chrome on OS X.
366 | * Safari (but not Chrome) clips the cancel button when the search input has
367 | * padding (and `textfield` appearance).
368 | */
369 |
370 | input[type="search"]::-webkit-search-cancel-button,
371 | input[type="search"]::-webkit-search-decoration {
372 | -webkit-appearance: none;
373 | }
374 |
375 | /**
376 | * Define consistent border, margin, and padding.
377 | */
378 |
379 | fieldset {
380 | border: 1px solid #c0c0c0;
381 | margin: 0 2px;
382 | padding: 0.35em 0.625em 0.75em;
383 | }
384 |
385 | /**
386 | * 1. Correct `color` not being inherited in IE 8/9/10/11.
387 | * 2. Remove padding so people aren't caught out if they zero out fieldsets.
388 | */
389 |
390 | legend {
391 | border: 0; /* 1 */
392 | padding: 0; /* 2 */
393 | }
394 |
395 | /**
396 | * Remove default vertical scrollbar in IE 8/9/10/11.
397 | */
398 |
399 | textarea {
400 | overflow: auto;
401 | }
402 |
403 | /**
404 | * Don't inherit the `font-weight` (applied by a rule above).
405 | * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
406 | */
407 |
408 | optgroup {
409 | font-weight: bold;
410 | }
411 |
412 | /* Tables
413 | ========================================================================== */
414 |
415 | /**
416 | * Remove most spacing between table cells.
417 | */
418 |
419 | table {
420 | border-collapse: collapse;
421 | border-spacing: 0;
422 | }
423 |
424 | td,
425 | th {
426 | padding: 0;
427 | }
428 |
429 | /*! HTML5 Boilerplate v5.0.0 | MIT License | https://html5boilerplate.com/ */
430 |
431 | /*
432 | * What follows is the result of much research on cross-browser styling.
433 | * Credit left inline and big thanks to Nicolas Gallagher, Jonathan Neal,
434 | * Kroc Camen, and the H5BP dev community and team.
435 | */
436 |
437 | /* ==========================================================================
438 | Base styles: opinionated defaults
439 | ========================================================================== */
440 |
441 | html {
442 | color: #222;
443 | font-size: 1em;
444 | line-height: 1.4;
445 | }
446 |
447 | /*
448 | * Remove text-shadow in selection highlight:
449 | * https://twitter.com/miketaylr/status/12228805301
450 | *
451 | * These selection rule sets have to be separate.
452 | * Customize the background color to match your design.
453 | */
454 |
455 | ::-moz-selection {
456 | background: #b3d4fc;
457 | text-shadow: none;
458 | }
459 |
460 | ::selection {
461 | background: #b3d4fc;
462 | text-shadow: none;
463 | }
464 |
465 | /*
466 | * A better looking default horizontal rule
467 | */
468 |
469 | hr {
470 | display: block;
471 | height: 1px;
472 | border: 0;
473 | border-top: 1px solid #ccc;
474 | margin: 1em 0;
475 | padding: 0;
476 | }
477 |
478 | /*
479 | * Remove the gap between audio, canvas, iframes,
480 | * images, videos and the bottom of their containers:
481 | * https://github.com/h5bp/html5-boilerplate/issues/440
482 | */
483 |
484 | audio,
485 | canvas,
486 | iframe,
487 | img,
488 | svg,
489 | video {
490 | vertical-align: middle;
491 | }
492 |
493 | /*
494 | * Remove default fieldset styles.
495 | */
496 |
497 | fieldset {
498 | border: 0;
499 | margin: 0;
500 | padding: 0;
501 | }
502 |
503 | /*
504 | * Allow only vertical resizing of textareas.
505 | */
506 |
507 | textarea {
508 | resize: vertical;
509 | }
510 |
511 | /* ==========================================================================
512 | Browser Upgrade Prompt
513 | ========================================================================== */
514 |
515 | .browserupgrade {
516 | margin: 0.2em 0;
517 | background: #ccc;
518 | color: #000;
519 | padding: 0.2em 0;
520 | }
521 |
522 | /* ==========================================================================
523 | Author's custom styles
524 | ========================================================================== */
525 |
526 |
527 |
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 |
536 |
537 |
538 |
539 |
540 |
541 |
542 | /* ==========================================================================
543 | Helper classes
544 | ========================================================================== */
545 |
546 | /*
547 | * Hide visually and from screen readers:
548 | */
549 |
550 | .hidden {
551 | display: none !important;
552 | }
553 |
554 | /*
555 | * Hide only visually, but have it available for screen readers:
556 | * http://snook.ca/archives/html_and_css/hiding-content-for-accessibility
557 | */
558 |
559 | .visuallyhidden {
560 | border: 0;
561 | clip: rect(0 0 0 0);
562 | height: 1px;
563 | margin: -1px;
564 | overflow: hidden;
565 | padding: 0;
566 | position: absolute;
567 | width: 1px;
568 | }
569 |
570 | /*
571 | * Extends the .visuallyhidden class to allow the element
572 | * to be focusable when navigated to via the keyboard:
573 | * https://www.drupal.org/node/897638
574 | */
575 |
576 | .visuallyhidden.focusable:active,
577 | .visuallyhidden.focusable:focus {
578 | clip: auto;
579 | height: auto;
580 | margin: 0;
581 | overflow: visible;
582 | position: static;
583 | width: auto;
584 | }
585 |
586 | /*
587 | * Hide visually and from screen readers, but maintain layout
588 | */
589 |
590 | .invisible {
591 | visibility: hidden;
592 | }
593 |
594 | /*
595 | * Clearfix: contain floats
596 | *
597 | * For modern browsers
598 | * 1. The space content is one way to avoid an Opera bug when the
599 | * `contenteditable` attribute is included anywhere else in the document.
600 | * Otherwise it causes space to appear at the top and bottom of elements
601 | * that receive the `clearfix` class.
602 | * 2. The use of `table` rather than `block` is only necessary if using
603 | * `:before` to contain the top-margins of child elements.
604 | */
605 |
606 | .clearfix:before,
607 | .clearfix:after {
608 | content: " "; /* 1 */
609 | display: table; /* 2 */
610 | }
611 |
612 | .clearfix:after {
613 | clear: both;
614 | }
615 |
616 | /* ==========================================================================
617 | EXAMPLE Media Queries for Responsive Design.
618 | These examples override the primary ('mobile first') styles.
619 | Modify as content requires.
620 | ========================================================================== */
621 |
622 | @media only screen and (min-width: 35em) {
623 | /* Style adjustments for viewports that meet the condition */
624 | }
625 |
626 | @media print,
627 | (-o-min-device-pixel-ratio: 5/4),
628 | (-webkit-min-device-pixel-ratio: 1.25),
629 | (min-resolution: 120dpi) {
630 | /* Style adjustments for high resolution devices */
631 | }
632 |
633 | /* ==========================================================================
634 | Print styles.
635 | Inlined to avoid the additional HTTP request:
636 | http://www.phpied.com/delay-loading-your-print-css/
637 | ========================================================================== */
638 |
639 | @media print {
640 | *,
641 | *:before,
642 | *:after {
643 | background: transparent !important;
644 | color: #000 !important; /* Black prints faster:
645 | http://www.sanbeiji.com/archives/953 */
646 | box-shadow: none !important;
647 | text-shadow: none !important;
648 | }
649 |
650 | a,
651 | a:visited {
652 | text-decoration: underline;
653 | }
654 |
655 | a[href]:after {
656 | content: " (" attr(href) ")";
657 | }
658 |
659 | abbr[title]:after {
660 | content: " (" attr(title) ")";
661 | }
662 |
663 | /*
664 | * Don't show links that are fragment identifiers,
665 | * or use the `javascript:` pseudo protocol
666 | */
667 |
668 | a[href^="#"]:after,
669 | a[href^="javascript:"]:after {
670 | content: "";
671 | }
672 |
673 | pre,
674 | blockquote {
675 | border: 1px solid #999;
676 | page-break-inside: avoid;
677 | }
678 |
679 | /*
680 | * Printing Tables:
681 | * http://css-discuss.incutio.com/wiki/Printing_Tables
682 | */
683 |
684 | thead {
685 | display: table-header-group;
686 | }
687 |
688 | tr,
689 | img {
690 | page-break-inside: avoid;
691 | }
692 |
693 | img {
694 | max-width: 100% !important;
695 | }
696 |
697 | p,
698 | h2,
699 | h3 {
700 | orphans: 3;
701 | widows: 3;
702 | }
703 |
704 | h2,
705 | h3 {
706 | page-break-after: avoid;
707 | }
708 | }
--------------------------------------------------------------------------------
/dist/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
79 |
80 |
81 | Press "D" to show debug info
82 |
87 |
88 |
89 |
90 |
91 |
101 |
102 |
103 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "rapid-prototyping",
3 | "version": "1.0.6",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "budo --dir dist/ src/index.js:js/bundle.js -v --live --open -- -t [ babelify --presets [ es2015 ] ] -t glslify",
9 | "build": "browserify -t [ babelify --presets [ es2015 ] ] -t glslify src/index.js | uglifyjs -cm > dist/js/bundle.js"
10 | },
11 | "repository": {
12 | "type": "git",
13 | "url": "https://github.com/silviopaganini/rapid-prototype"
14 | },
15 | "bugs": {
16 | "url": "https://github.com/silviopaganini/rapid-prototype/issues"
17 | },
18 | "author": "silvio paganini | @silviopaganini",
19 | "license": "ISC",
20 | "dependencies": {
21 | "dat-gui": "^0.5.0",
22 | "stats-js": "^1.0.0-alpha1",
23 | "three-orbit-controls": "^72.0.0",
24 | "three": "^0.74.0",
25 | "babel-preset-es2015": "^6.3.13",
26 | "babelify": "^7.2.0",
27 | "browserify": "^13.0.0",
28 | "glslify": "^5.0.2"
29 | },
30 | "devDependencies": {
31 | "budo": "^8.0.3",
32 | "uglifyjs": "^2.4.10"
33 | },
34 | "engines": {
35 | "node": ">= 5.6.0",
36 | "npm": ">=3.6.0"
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | import dat from 'dat-gui'
2 | import Stats from 'stats-js'
3 | import THREE from 'three'
4 |
5 | const OrbitControls = require('three-orbit-controls')(THREE);
6 | const glslify = require('glslify');
7 | require('./post-processing/EffectComposer')(THREE);
8 |
9 | class App {
10 |
11 | constructor()
12 | {
13 | this.renderer = null;
14 | this.camera = null;
15 | this.scene = null;
16 | this.counter = 0;
17 | this.gui = null;
18 | this.clock = new THREE.Clock();
19 | this.DEBUG = true;
20 | this.SIZE = {
21 | w : window.innerWidth ,
22 | w2 : window.innerWidth / 2,
23 | h : window.innerHeight,
24 | h2 : window.innerHeight / 2
25 | };
26 |
27 | this.startStats();
28 | this.createRender();
29 | this.createScene();
30 | this.addComposer();
31 | this.addObjects();
32 | this.startGUI();
33 |
34 | this.onResize();
35 | this.update();
36 | }
37 |
38 | startStats()
39 | {
40 | this.stats = new Stats();
41 | this.stats.domElement.style.position = 'absolute';
42 | this.stats.domElement.style.top = 0;
43 | this.stats.domElement.style.display = this.DEBUG ? 'block' : 'none';
44 | this.stats.domElement.style.left = 0;
45 | this.stats.domElement.style.zIndex = 50;
46 | document.body.appendChild(this.stats.domElement);
47 | document.querySelector('.help').style.display = this.stats.domElement.style.display == 'block' ? "none" : "block";
48 | }
49 |
50 | createRender()
51 | {
52 | this.renderer = new THREE.WebGLRenderer( {
53 | antialias : false,
54 | depth : true,
55 | } );
56 |
57 | this.renderer.setClearColor( 0x000000 );
58 | this.renderer.setClearAlpha( 0 );
59 | // this.renderer.setPixelRatio( window.devicePixelRatio || 1 )
60 | this.renderer.setSize(window.innerWidth, window.innerHeight);
61 | this.renderer.gammaInput = true;
62 | this.renderer.gammaOuput = true;
63 | this.renderer.autoClear = false;
64 |
65 | document.body.appendChild(this.renderer.domElement)
66 | }
67 |
68 | addComposer()
69 | {
70 | this.composer = new THREE.EffectComposer(this.renderer);
71 |
72 | let scenePass = new THREE.RenderPass( this.scene, this.camera, false, 0x000000, 0 );
73 |
74 | this.gamma = {
75 | uniforms: {
76 | tDiffuse : {type: "t", value: null },
77 | resolution : {type: 'v2', value: new THREE.Vector2(
78 | window.innerWidth * (window.devicePixelRatio || 1),
79 | window.innerHeight * (window.devicePixelRatio || 1)
80 | )},
81 | },
82 | vertexShader : glslify('./post-processing/glsl/screen_vert.glsl'),
83 | fragmentShader : glslify('./post-processing/glsl/gamma.glsl'),
84 | }
85 |
86 | /*
87 | passes
88 | */
89 |
90 | this.composer.addPass(scenePass);
91 |
92 | let gamma = new THREE.ShaderPass(this.gamma);
93 | gamma.renderToScreen = true;
94 | this.composer.addPass(gamma);
95 |
96 | }
97 |
98 | createScene()
99 | {
100 | // OrthographicCamera
101 | // this.camera = new THREE.OrthographicCamera( this.SIZE.w / - 2, this.SIZE.w / 2, this.SIZE.h / 2, this.SIZE.h / - 2, 1, 1000 );
102 |
103 | this.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.01, 4000 );
104 | this.camera.position.set(0, 40, 200);
105 |
106 | this.controls = new OrbitControls(this.camera, this.renderer.domElement);
107 | this.controls.enabled = this.DEBUG;
108 | this.controls.maxDistance = 500;
109 | this.controls.minDistance = 50;
110 |
111 | this.scene = new THREE.Scene();
112 | }
113 |
114 | addObjects()
115 | {
116 | let gridHelper = new THREE.GridHelper( 100, 10 );
117 | this.scene.add( gridHelper );
118 |
119 | /*
120 | example of shader material using glslify
121 |
122 | this.shader = new THREE.ShaderMaterial({
123 | vertexShader : glslify('./glsl/basic_vert.glsl'),
124 | fragmentShader : glslify('./glsl/basic_frag.glsl'),
125 | })
126 |
127 | */
128 | }
129 |
130 | startGUI()
131 | {
132 | this.gui = new dat.GUI()
133 | this.gui.domElement.style.display = this.DEBUG ? 'block' : 'none';
134 |
135 | let cameraFolder = this.gui.addFolder('Camera');
136 | cameraFolder.add(this.camera.position, 'x', -400, 400);
137 | cameraFolder.add(this.camera.position, 'y', -400, 400);
138 | cameraFolder.add(this.camera.position, 'z', -400, 400);
139 |
140 | }
141 |
142 | update()
143 | {
144 | this.stats.begin();
145 |
146 | let el = this.clock.getElapsedTime() * .05;
147 | let d = this.clock.getDelta();
148 |
149 | this.renderer.clear();
150 |
151 | // this.renderer.render(this.scene, this.camera);
152 | this.composer.render(d);
153 |
154 | this.stats.end()
155 | requestAnimationFrame(this.update.bind(this));
156 | }
157 |
158 | /*
159 | events
160 | */
161 |
162 | onKeyUp(e)
163 | {
164 | let key = e.which || e.keyCode;
165 | switch(key)
166 | {
167 | // leter D
168 | case 68:
169 | this.DEBUG = !this.DEBUG;
170 | if(this.stats) this.stats.domElement.style.display = !this.DEBUG ? "none" : "block";
171 | if(this.gui) this.gui.domElement.style.display = !this.DEBUG ? "none" : "block";
172 | if(this.controls) this.controls.enabled = this.DEBUG;
173 | if(document.querySelector('.help')) document.querySelector('.help').style.display = this.DEBUG ? "none" : "block";
174 | break;
175 | }
176 | }
177 |
178 | onResize()
179 | {
180 | this.SIZE = {
181 | w : window.innerWidth ,
182 | w2 : window.innerWidth / 2,
183 | h : window.innerHeight,
184 | h2 : window.innerHeight / 2
185 | };
186 |
187 | // OrthographicCamera
188 | // this.camera.left = this.SIZE.w / - 2;
189 | // this.camera.right = this.SIZE.w / 2;
190 | // this.camera.top = this.SIZE.h / 2;
191 | // this.camera.bottom = this.SIZE.h / - 2;
192 |
193 | this.renderer.setSize(this.SIZE.w, this.SIZE.h);
194 | this.camera.aspect = this.SIZE.w / this.SIZE.h;
195 | this.camera.updateProjectionMatrix();
196 | }
197 | }
198 |
199 | export default App;
200 |
--------------------------------------------------------------------------------
/src/glsl/basic_frag.glsl:
--------------------------------------------------------------------------------
1 | uniform vec3 color;
2 |
3 | void main() {
4 | gl_FragColor = vec4( color , 1.0 );
5 | // gl_FragColor = gl_FragColor * texture2D( texture, vUv );
6 | }
--------------------------------------------------------------------------------
/src/glsl/basic_vert.glsl:
--------------------------------------------------------------------------------
1 | // varying vec2 vUv;
2 |
3 | void main()
4 | {
5 | // vUv = uv;
6 | vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
7 | gl_Position = projectionMatrix * mvPosition;
8 | }
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import App from './App';
2 |
3 | const app = new App();
4 | window.onresize = app.onResize.bind(app);
5 | window.onkeyup = app.onKeyUp.bind(app);
--------------------------------------------------------------------------------
/src/post-processing/EffectComposer.js:
--------------------------------------------------------------------------------
1 | module.exports = function(THREE)
2 | {
3 |
4 | /**
5 | * @author alteredq / http://alteredqualia.com/
6 | *
7 | * Full-screen textured quad shader
8 | */
9 |
10 | THREE.CopyShader = {
11 |
12 | uniforms: {
13 |
14 | "tDiffuse": { type: "t", value: null },
15 | "opacity": { type: "f", value: 1.0 }
16 |
17 | },
18 |
19 | vertexShader: [
20 |
21 | "varying vec2 vUv;",
22 |
23 | "void main() {",
24 |
25 | "vUv = uv;",
26 | "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
27 |
28 | "}"
29 |
30 | ].join( "\n" ),
31 |
32 | fragmentShader: [
33 |
34 | "uniform float opacity;",
35 |
36 | "uniform sampler2D tDiffuse;",
37 |
38 | "varying vec2 vUv;",
39 |
40 | "void main() {",
41 |
42 | "vec4 texel = texture2D( tDiffuse, vUv );",
43 | "gl_FragColor = opacity * texel;",
44 |
45 | "}"
46 |
47 | ].join( "\n" )
48 |
49 | };
50 |
51 | THREE.EffectComposer = function ( renderer, renderTarget ) {
52 |
53 | this.renderer = renderer;
54 |
55 | if ( renderTarget === undefined ) {
56 |
57 | var pixelRatio = renderer.getPixelRatio();
58 |
59 | var width = Math.floor( renderer.context.canvas.width / pixelRatio ) || 1;
60 | var height = Math.floor( renderer.context.canvas.height / pixelRatio ) || 1;
61 | var parameters = {
62 | minFilter: THREE.LinearFilter,
63 | magFilter: THREE.LinearFilter,
64 | stencilBuffer: false ,
65 | blending: THREE.CustomBlending,
66 | blendSrc: THREE.SrcAlphaFactor,
67 | blendDst: THREE.OneFactor,
68 | };
69 |
70 | renderTarget = new THREE.WebGLRenderTarget( width, height, parameters );
71 | renderTarget.texture.format = THREE.RGBAFormat;
72 | }
73 |
74 | this.renderTarget1 = renderTarget;
75 | this.renderTarget2 = renderTarget.clone();
76 |
77 | this.writeBuffer = this.renderTarget1;
78 | this.readBuffer = this.renderTarget2;
79 |
80 | this.passes = [];
81 |
82 | if ( THREE.CopyShader === undefined )
83 | console.error( "THREE.EffectComposer relies on THREE.CopyShader" );
84 |
85 | this.copyPass = new THREE.ShaderPass( THREE.CopyShader );
86 |
87 | };
88 |
89 | THREE.EffectComposer.prototype = {
90 |
91 | swapBuffers: function() {
92 |
93 | var tmp = this.readBuffer;
94 | this.readBuffer = this.writeBuffer;
95 | this.writeBuffer = tmp;
96 |
97 | },
98 |
99 | addPass: function ( pass ) {
100 |
101 | this.passes.push( pass );
102 |
103 | },
104 |
105 | insertPass: function ( pass, index ) {
106 |
107 | this.passes.splice( index, 0, pass );
108 |
109 | },
110 |
111 | render: function ( delta ) {
112 |
113 | this.writeBuffer = this.renderTarget1;
114 | this.readBuffer = this.renderTarget2;
115 |
116 | var maskActive = false;
117 |
118 | var pass, i, il = this.passes.length;
119 |
120 | for ( i = 0; i < il; i ++ ) {
121 |
122 | pass = this.passes[ i ];
123 | // console.log(pass)
124 |
125 | if ( ! pass.enabled ) continue;
126 |
127 | pass.render( this.renderer, this.writeBuffer, this.readBuffer, delta, maskActive );
128 |
129 | if ( pass.needsSwap ) {
130 |
131 | if ( maskActive ) {
132 |
133 | var context = this.renderer.context;
134 |
135 | context.stencilFunc( context.NOTEQUAL, 1, 0xffffffff );
136 |
137 | this.copyPass.render( this.renderer, this.writeBuffer, this.readBuffer, delta );
138 |
139 | context.stencilFunc( context.EQUAL, 1, 0xffffffff );
140 |
141 | }
142 |
143 | this.swapBuffers();
144 |
145 | }
146 |
147 | if ( pass instanceof THREE.MaskPass ) {
148 |
149 | maskActive = true;
150 |
151 | } else if ( pass instanceof THREE.ClearMaskPass ) {
152 |
153 | maskActive = false;
154 |
155 | }
156 |
157 | }
158 |
159 | },
160 |
161 | reset: function ( renderTarget ) {
162 |
163 | if ( renderTarget === undefined ) {
164 |
165 | renderTarget = this.renderTarget1.clone();
166 |
167 | var pixelRatio = this.renderer.getPixelRatio();
168 |
169 | renderTarget.width = Math.floor( this.renderer.context.canvas.width / pixelRatio );
170 | renderTarget.height = Math.floor( this.renderer.context.canvas.height / pixelRatio );
171 |
172 | }
173 |
174 | this.renderTarget1.dispose();
175 | this.renderTarget1 = renderTarget;
176 | this.renderTarget2.dispose();
177 | this.renderTarget2 = renderTarget.clone();
178 |
179 | this.writeBuffer = this.renderTarget1;
180 | this.readBuffer = this.renderTarget2;
181 |
182 | },
183 |
184 | setSize: function ( width, height ) {
185 |
186 | this.renderTarget1.setSize( width, height );
187 | this.renderTarget2.setSize( width, height );
188 |
189 | }
190 |
191 | };
192 |
193 |
194 | THREE.ShaderPass = function ( shader, textureID ) {
195 |
196 | this.textureID = ( textureID !== undefined ) ? textureID : "tDiffuse";
197 |
198 | this.uniforms = THREE.UniformsUtils.clone( shader.uniforms );
199 |
200 | this.material = new THREE.ShaderMaterial( {
201 |
202 | defines: shader.defines || {},
203 | uniforms: this.uniforms,
204 | vertexShader: shader.vertexShader,
205 | fragmentShader: shader.fragmentShader,
206 |
207 | } );
208 |
209 | this.renderToScreen = false;
210 |
211 | this.enabled = true;
212 | this.needsSwap = true;
213 | this.clear = false;
214 |
215 |
216 | this.camera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );
217 | this.scene = new THREE.Scene();
218 |
219 | this.quad = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), null );
220 | this.scene.add( this.quad );
221 |
222 | };
223 |
224 | THREE.ShaderPass.prototype = {
225 |
226 | render: function ( renderer, writeBuffer, readBuffer, delta ) {
227 |
228 | if ( this.uniforms[ this.textureID ] ) {
229 |
230 | this.uniforms[ this.textureID ].value = readBuffer;
231 |
232 | }
233 |
234 | this.quad.material = this.material;
235 |
236 | if ( this.renderToScreen ) {
237 |
238 | renderer.render( this.scene, this.camera );
239 |
240 | } else {
241 |
242 | renderer.render( this.scene, this.camera, writeBuffer, this.clear );
243 |
244 | }
245 |
246 | }
247 |
248 | };
249 |
250 | /**
251 | * @author alteredq / http://alteredqualia.com/
252 | */
253 |
254 | THREE.MaskPass = function ( scene, camera ) {
255 |
256 | this.scene = scene;
257 | this.camera = camera;
258 |
259 | this.enabled = true;
260 | this.clear = true;
261 | this.needsSwap = false;
262 |
263 | this.inverse = false;
264 |
265 | };
266 |
267 | THREE.MaskPass.prototype = {
268 |
269 | render: function ( renderer, writeBuffer, readBuffer, delta ) {
270 |
271 | var context = renderer.context;
272 |
273 | // don't update color or depth
274 |
275 | context.colorMask( false, false, false, false );
276 | context.depthMask( false );
277 |
278 | // set up stencil
279 |
280 | var writeValue, clearValue;
281 |
282 | if ( this.inverse ) {
283 |
284 | writeValue = 0;
285 | clearValue = 1;
286 |
287 | } else {
288 |
289 | writeValue = 1;
290 | clearValue = 0;
291 |
292 | }
293 |
294 | context.enable( context.STENCIL_TEST );
295 | context.stencilOp( context.REPLACE, context.REPLACE, context.REPLACE );
296 | context.stencilFunc( context.ALWAYS, writeValue, 0xffffffff );
297 | context.clearStencil( clearValue );
298 |
299 | // draw into the stencil buffer
300 |
301 | renderer.render( this.scene, this.camera, readBuffer, this.clear );
302 | renderer.render( this.scene, this.camera, writeBuffer, this.clear );
303 |
304 | // re-enable update of color and depth
305 |
306 | context.colorMask( true, true, true, true );
307 | context.depthMask( true );
308 |
309 | // only render where stencil is set to 1
310 |
311 | context.stencilFunc( context.EQUAL, 1, 0xffffffff ); // draw if == 1
312 | context.stencilOp( context.KEEP, context.KEEP, context.KEEP );
313 |
314 | }
315 |
316 | };
317 |
318 |
319 | THREE.ClearMaskPass = function () {
320 |
321 | this.enabled = true;
322 |
323 | };
324 |
325 | THREE.ClearMaskPass.prototype = {
326 |
327 | render: function ( renderer, writeBuffer, readBuffer, delta ) {
328 |
329 | var context = renderer.context;
330 |
331 | context.disable( context.STENCIL_TEST );
332 |
333 | }
334 |
335 | };
336 |
337 | /**
338 | * @author alteredq / http://alteredqualia.com/
339 | */
340 |
341 | THREE.RenderPass = function ( scene, camera, overrideMaterial, clearColor, clearAlpha ) {
342 |
343 | this.scene = scene;
344 | this.camera = camera;
345 |
346 | this.overrideMaterial = overrideMaterial;
347 |
348 | this.clearColor = clearColor;
349 | this.clearAlpha = ( clearAlpha !== undefined ) ? clearAlpha : 1;
350 |
351 | this.oldClearColor = new THREE.Color();
352 | this.oldClearAlpha = 1;
353 |
354 | this.enabled = true;
355 | this.clear = true;
356 | this.needsSwap = false;
357 |
358 | };
359 |
360 | THREE.RenderPass.prototype = {
361 |
362 | render: function ( renderer, writeBuffer, readBuffer, delta ) {
363 |
364 | this.scene.overrideMaterial = this.overrideMaterial;
365 |
366 | if ( this.clearColor ) {
367 |
368 | this.oldClearColor.copy( renderer.getClearColor() );
369 | this.oldClearAlpha = renderer.getClearAlpha();
370 |
371 | renderer.setClearColor( this.clearColor, this.clearAlpha );
372 | renderer.setClearAlpha(0);
373 |
374 | }
375 |
376 | renderer.render( this.scene, this.camera, readBuffer, this.clear );
377 |
378 | if ( this.clearColor ) {
379 |
380 | renderer.setClearColor( this.oldClearColor, this.oldClearAlpha );
381 | renderer.setClearAlpha(0);
382 |
383 | }
384 |
385 | this.scene.overrideMaterial = null;
386 |
387 | }
388 |
389 | };
390 |
391 |
392 | }
393 |
--------------------------------------------------------------------------------
/src/post-processing/glsl/fxaa.glsl:
--------------------------------------------------------------------------------
1 | float FXAA_REDUCE_MIN = (1.0/128.0);
2 | float FXAA_REDUCE_MUL = (1.0/8.0);
3 | float FXAA_SPAN_MAX = 8.0;
4 |
5 | vec4 fxaa(sampler2D tDiffuse, vec2 xyFragCoord, vec2 res) {
6 |
7 | vec2 resolution = vec2( 1.0/res.x, 1.0/res.y );
8 | vec4 color;
9 |
10 | vec3 rgbNW = texture2D( tDiffuse, ( xyFragCoord + vec2( -1.0, -1.0 ) ) * resolution ).xyz;
11 | vec3 rgbNE = texture2D( tDiffuse, ( xyFragCoord + vec2( 1.0, -1.0 ) ) * resolution ).xyz;
12 | vec3 rgbSW = texture2D( tDiffuse, ( xyFragCoord + vec2( -1.0, 1.0 ) ) * resolution ).xyz;
13 | vec3 rgbSE = texture2D( tDiffuse, ( xyFragCoord + vec2( 1.0, 1.0 ) ) * resolution ).xyz;
14 | vec4 rgbaM = texture2D( tDiffuse, xyFragCoord * resolution );
15 | vec3 rgbM = rgbaM.xyz;
16 | vec3 luma = vec3( 0.299, 0.587, 0.114 );
17 |
18 | float lumaNW = dot( rgbNW, luma );
19 | float lumaNE = dot( rgbNE, luma );
20 | float lumaSW = dot( rgbSW, luma );
21 | float lumaSE = dot( rgbSE, luma );
22 | float lumaM = dot( rgbM, luma );
23 | float lumaMin = min( lumaM, min( min( lumaNW, lumaNE ), min( lumaSW, lumaSE ) ) );
24 | float lumaMax = max( lumaM, max( max( lumaNW, lumaNE) , max( lumaSW, lumaSE ) ) );
25 |
26 | vec2 dir;
27 | dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));
28 | dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));
29 |
30 | float dirReduce = max( ( lumaNW + lumaNE + lumaSW + lumaSE ) * ( 0.25 * FXAA_REDUCE_MUL ), FXAA_REDUCE_MIN );
31 | float rcpDirMin = 1.0 / ( min( abs( dir.x ), abs( dir.y ) ) + dirReduce );
32 | dir = min( vec2( FXAA_SPAN_MAX, FXAA_SPAN_MAX), max( vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), dir * rcpDirMin)) * resolution;
33 | vec4 rgbA = (1.0/2.0) * (
34 | texture2D(tDiffuse, xyFragCoord * resolution + dir * (1.0/3.0 - 0.5)) +
35 | texture2D(tDiffuse, xyFragCoord * resolution + dir * (2.0/3.0 - 0.5)));
36 | vec4 rgbB = rgbA * (1.0/2.0) + (1.0/4.0) * (
37 | texture2D(tDiffuse, xyFragCoord * resolution + dir * (0.0/3.0 - 0.5)) +
38 | texture2D(tDiffuse, xyFragCoord * resolution + dir * (3.0/3.0 - 0.5)));
39 | float lumaB = dot(rgbB, vec4(luma, 0.0));
40 |
41 | if(( lumaB < lumaMin ) || ( lumaB > lumaMax ) ) {
42 | color = rgbA;
43 | }else{
44 | color = rgbB;
45 | }
46 |
47 | return color;
48 | }
49 |
50 | #pragma glslify: export(fxaa)
--------------------------------------------------------------------------------
/src/post-processing/glsl/gamma.glsl:
--------------------------------------------------------------------------------
1 | #pragma glslify: fxaa = require('./fxaa.glsl')
2 |
3 | varying vec2 vUv;
4 | uniform sampler2D tDiffuse;
5 | uniform vec2 resolution;
6 |
7 | void main() {
8 |
9 | vec2 fragCoord = vUv * resolution;
10 | vec4 texel = fxaa(tDiffuse, fragCoord, resolution);
11 |
12 | vec2 res = (gl_FragCoord.xy / resolution.xy) - vec2(0.5);
13 | res.x *= resolution.x / resolution.y;
14 |
15 | // vec4 texel = texture2D( tDiffuse, vUv );
16 |
17 | // vignette
18 | // float len = length(res);
19 | // float vignette = smoothstep(.85, .5, len);
20 | // texel = pow(texel, vec4(3.)) * vignette;
21 |
22 | gl_FragColor = texel;
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/src/post-processing/glsl/screen_frag.glsl:
--------------------------------------------------------------------------------
1 | varying vec2 vUv;
2 | uniform sampler2D tDiffuse;
3 |
4 | void main() {
5 |
6 | gl_FragColor = texture2D( tDiffuse, vUv );
7 |
8 | }
--------------------------------------------------------------------------------
/src/post-processing/glsl/screen_vert.glsl:
--------------------------------------------------------------------------------
1 | varying vec2 vUv;
2 |
3 | void main() {
4 | vUv = uv;
5 | gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
6 | }
--------------------------------------------------------------------------------