UNPKG

40.6 kBJavaScriptView Raw
1import { Shader, TextureTable } from "./Render";
2// import { m2_rotation, TAU, toRad } from "./Vector";
3import { m2_rotation, TAU, toRad } from "@croquet/worldcore-kernel";
4
5// Standard Universals
6//
7// * uMeshMatrix Transform mesh vertices into world space
8// * uNormalMatrix Transform mesh normals into world space
9//
10// * uViewMatrix Transform vertices from world to view space
11// * uViewNormalMatrix Transform normals from world to view space
12// * uProjectionMatrix Transform vertices from view to screen space
13// * uCameraMatrix Transform vertices from world to screen space (combines uViewMatrix & uProjectionMatrix)
14
15// * uMeshToViewMatrix Transform mesh vertices into view space (combines uMeshMatrix & uViewMatrix)
16// * uNormalToViewMatrix Transfrom mesh normals into view space (combines uNormalMatrix & uViewNormalMatrix)
17// * uMeshToScreenMatrix Transform mesh vertices into screen space (combines uMeshMatrix & uViewMatrix & uProjectionMatrix)
18
19//------------------------------------------------------------------------------------------
20//-- BasicShader ---------------------------------------------------------------------------
21//------------------------------------------------------------------------------------------
22
23// Forward rendering using textures + ambient and one directional light. This is the same
24// as the ambient output of the GeometryShader.
25
26export class BasicShader extends Shader {
27 constructor() {
28 super();
29
30 // -- WebGL2 Source --
31
32 const vSource2 = `#version 300 es
33 in vec3 aVertex;
34 in vec3 aNormal;
35 in vec4 aColor;
36 in vec2 aCoordinate;
37
38 uniform mat4 uMeshToScreenMatrix;
39 uniform mat4 uNormalMatrix;
40
41 uniform vec3 uAmbientColor;
42 uniform vec3 uDirectionalColor;
43 uniform vec3 uDirectionalAim;
44
45 out lowp vec2 vCoordinate;
46 out lowp vec3 vLighting;
47
48 void main() {
49 lowp vec4 position = uMeshToScreenMatrix * vec4(aVertex,1);
50 lowp vec3 normal = normalize((uNormalMatrix * vec4(aNormal,1)).xyz);
51 vCoordinate = aCoordinate;
52 vLighting = aColor.rgb * (uAmbientColor + uDirectionalColor * dot(normal, uDirectionalAim));
53 gl_Position = position;
54 }
55 `;
56
57 const fSource2 = `#version 300 es
58 in lowp vec3 vLighting;
59 in lowp vec2 vCoordinate;
60
61 uniform sampler2D uSampler0;
62
63 out lowp vec4 color;
64
65 void main() {
66 color = vec4(texture(uSampler0, vCoordinate).rgb * vLighting,1);
67 }
68 `;
69
70 // -- WebGL Source --
71
72 const vSource = `
73 attribute vec3 aVertex;
74 attribute vec3 aNormal;
75 attribute vec4 aColor;
76 attribute vec2 aCoordinate;
77
78 uniform mat4 uMeshToScreenMatrix;
79 uniform mat4 uNormalMatrix;
80
81 uniform vec3 uAmbientColor;
82 uniform vec3 uDirectionalColor;
83 uniform vec3 uDirectionalAim;
84
85 varying lowp vec2 vCoordinate;
86 varying lowp vec3 vLighting;
87
88 void main() {
89 lowp vec4 position = uMeshToScreenMatrix * vec4(aVertex,1);
90 lowp vec3 normal = normalize((uNormalMatrix * vec4(aNormal,1)).xyz);
91 vCoordinate = aCoordinate;
92 vLighting = aColor.rgb * (uAmbientColor + uDirectionalColor * dot(normal, uDirectionalAim));
93 gl_Position = position;
94 }
95 `;
96
97 const fSource = `
98 varying lowp vec3 vLighting;
99 varying lowp vec2 vCoordinate;
100
101 uniform sampler2D uSampler0;
102
103 void main() {
104 gl_FragColor = vec4(texture2D(uSampler0, vCoordinate).rgb * vLighting,1);
105 }
106 `;
107
108 this.build(vSource, fSource, vSource2, fSource2);
109 }
110
111}
112
113//------------------------------------------------------------------------------------------
114//-- InstancedShader ---------------------------------------------------------------------------
115//------------------------------------------------------------------------------------------
116
117// Forward rendering using textures + ambient and one directional light. This is the same
118// as the ambient output of the GeometryShader.
119
120export class InstancedShader extends Shader {
121 constructor() {
122 super();
123
124 // -- WebGL2 Source --
125
126 const vSource2 = `#version 300 es
127 in vec3 aVertex;
128 in vec3 aNormal;
129 in vec4 aColor;
130 in vec2 aCoordinate;
131 in mat4 aMeshMatrix;
132 in mat4 aNormalMatrix;
133
134 uniform mat4 uCameraMatrix;
135
136 uniform vec3 uAmbientColor;
137 uniform vec3 uDirectionalColor;
138 uniform vec3 uDirectionalAim;
139
140 out lowp vec2 vCoordinate;
141 out lowp vec3 vLighting;
142
143 void main() {
144 lowp vec4 position = uCameraMatrix * aMeshMatrix * vec4(aVertex,1);
145 lowp vec3 normal = normalize((aNormalMatrix * vec4(aNormal,1)).xyz);
146 vCoordinate = aCoordinate;
147 vLighting = aColor.rgb * (uAmbientColor + uDirectionalColor * dot(normal, uDirectionalAim));
148 gl_Position = position;
149 }
150 `;
151
152 const fSource2 = `#version 300 es
153 in lowp vec3 vLighting;
154 in lowp vec2 vCoordinate;
155
156 uniform sampler2D uSampler0;
157
158 out lowp vec4 color;
159
160 void main() {
161 color = vec4(texture(uSampler0, vCoordinate).rgb * vLighting,1);
162 }
163 `;
164
165 // -- WebGL Source --
166
167 const vSource = `
168 attribute vec3 aVertex;
169 attribute vec3 aNormal;
170 attribute vec4 aColor;
171 attribute vec2 aCoordinate;
172 attribute mat4 aMeshMatrix;
173 attribute mat4 aNormalMatrix;
174
175 uniform mat4 uCameraMatrix;
176
177 uniform vec3 uAmbientColor;
178 uniform vec3 uDirectionalColor;
179 uniform vec3 uDirectionalAim;
180
181 varying lowp vec2 vCoordinate;
182 varying lowp vec3 vLighting;
183
184 void main() {
185 lowp vec4 position = uCameraMatrix * aMeshMatrix * vec4(aVertex,1);
186 lowp vec3 normal = normalize((aNormalMatrix * vec4(aNormal,1)).xyz);
187 vCoordinate = aCoordinate;
188 vLighting = aColor.rgb * (uAmbientColor + uDirectionalColor * dot(normal, uDirectionalAim));
189 gl_Position = position;
190 }
191 `;
192
193 const fSource = `
194 varying lowp vec3 vLighting;
195 varying lowp vec2 vCoordinate;
196
197 uniform sampler2D uSampler0;
198
199 void main() {
200 gl_FragColor = vec4(texture2D(uSampler0, vCoordinate).rgb * vLighting,1);
201 }
202 `;
203
204 this.build(vSource, fSource, vSource2, fSource2);
205 }
206
207}
208
209//------------------------------------------------------------------------------------------
210//-- TranslucentShader ---------------------------------------------------------------------
211//------------------------------------------------------------------------------------------
212
213// No lighting, just application of the color of the triangles with appropriate blend set.
214
215export class TranslucentShader extends Shader {
216 constructor() {
217 super();
218
219 // -- WebGL2 Source --
220
221 const vSource2 = `#version 300 es
222 in vec3 aVertex;
223 in vec4 aColor;
224 in vec2 aCoordinate;
225
226 uniform mat4 uMeshToScreenMatrix;
227
228 out lowp vec4 vColor;
229 out lowp vec2 vCoordinate;
230
231 void main() {
232 vColor = aColor;
233 vCoordinate = aCoordinate;
234 gl_Position = uMeshToScreenMatrix * vec4(aVertex,1);
235 }
236 `;
237
238 const fSource2 = `#version 300 es
239 in lowp vec4 vColor;
240 in lowp vec2 vCoordinate;
241
242 uniform sampler2D uSampler0;
243
244 out lowp vec4 color;
245
246 void main() {
247 color = texture(uSampler0, vCoordinate) * vColor;
248 }
249 `;
250
251 // -- WebGL Source --
252
253 const vSource = `
254 attribute vec3 aVertex;
255 attribute vec4 aColor;
256 attribute vec2 aCoordinate;
257
258 uniform mat4 uMeshToScreenMatrix;
259
260 varying lowp vec2 vCoordinate;
261 varying lowp vec4 vColor;
262
263 void main() {
264 vColor = aColor;
265 vCoordinate = aCoordinate;
266 gl_Position = uMeshToScreenMatrix * vec4(aVertex,1);
267 }
268 `;
269
270 const fSource = `
271
272 varying lowp vec4 vColor;
273 varying lowp vec2 vCoordinate;
274
275 uniform sampler2D uSampler0;
276
277 void main() {
278 gl_FragColor = texture2D(uSampler0, vCoordinate) * vColor;
279 }
280 `;
281
282 this.build(vSource, fSource, vSource2, fSource2);
283 }
284
285 apply() {
286 super.apply();
287 this.gl.enable(this.gl.BLEND);
288 this.gl.blendFunc(this.gl.ONE, this.gl.ONE_MINUS_SRC_ALPHA);
289 this.gl.depthMask(false);
290 this.gl.polygonOffset(-1, 0);
291 }
292
293}
294
295
296//------------------------------------------------------------------------------------------
297//-- DecalShader ---------------------------------------------------------------------------
298//------------------------------------------------------------------------------------------
299
300// Like the basic shader, but it also includes an optional decal texture.
301
302export class DecalShader extends Shader {
303 constructor() {
304 super();
305
306 // -- WebGL2 Source --
307
308 const vSource2 = `#version 300 es
309 in vec3 aVertex;
310 in vec3 aNormal;
311 in vec4 aColor;
312 in vec2 aCoordinate;
313
314 uniform mat4 uMeshToScreenMatrix;
315 uniform mat4 uNormalMatrix;
316
317 uniform vec3 uAmbientColor;
318 uniform vec3 uDirectionalColor;
319 uniform vec3 uDirectionalAim;
320
321 out lowp vec3 vColor;
322 out lowp vec2 vCoordinate;
323 out lowp vec3 vLighting;
324
325 void main() {
326 lowp vec4 position = uMeshToScreenMatrix * vec4(aVertex,1);
327 lowp vec3 normal = normalize((uNormalMatrix * vec4(aNormal,1)).xyz);
328 vColor = aColor.rgb;
329 vCoordinate = aCoordinate;
330 vLighting = uAmbientColor + uDirectionalColor * dot(normal, uDirectionalAim);
331 gl_Position = position;
332 }
333 `;
334
335 const fSource2 = `#version 300 es
336 in lowp vec3 vColor;
337 in lowp vec3 vLighting;
338 in lowp vec2 vCoordinate;
339
340 uniform sampler2D uSampler0;
341 uniform sampler2D uSampler1;
342
343 out lowp vec4 color;
344
345 void main() {
346 lowp vec3 t0 = texture(uSampler0, vCoordinate).rgb * vColor;
347 lowp vec4 t1 = texture(uSampler1, vCoordinate);
348 lowp vec3 tt = ((1.0-t1.a)*t0) + (t1.a*t1.rgb);
349 color = vec4(tt * vLighting,1);
350 }
351 `;
352
353 // -- WebGL Source --
354
355 const vSource = `
356 attribute vec3 aVertex;
357 attribute vec3 aNormal;
358 attribute vec4 aColor;
359 attribute vec2 aCoordinate;
360
361 uniform mat4 uNormalMatrix;
362 uniform mat4 uMeshToScreenMatrix;
363
364 uniform vec3 uAmbientColor;
365 uniform vec3 uDirectionalColor;
366 uniform vec3 uDirectionalAim;
367
368 varying lowp vec3 vColor;
369 varying lowp vec2 vCoordinate;
370 varying lowp vec3 vLighting;
371
372 void main() {
373 lowp vec4 position = uMeshToScreenMatrix * vec4(aVertex,1);
374 lowp vec3 normal = normalize((uNormalMatrix * vec4(aNormal,1)).xyz);
375 vColor = aColor.rgb;
376 vCoordinate = aCoordinate;
377 vLighting = uAmbientColor + uDirectionalColor * dot(normal, uDirectionalAim);
378 gl_Position = position;
379 }
380 `;
381
382 const fSource = `
383 varying lowp vec3 vColor;
384 varying lowp vec3 vLighting;
385 varying lowp vec2 vCoordinate;
386
387 uniform sampler2D uSampler0;
388 uniform sampler2D uSampler1;
389
390 void main() {
391 lowp vec3 t0 = texture2D(uSampler0, vCoordinate).rgb * vColor;
392 lowp vec4 t1 = texture2D(uSampler1, vCoordinate);
393 lowp vec3 tt = ((1.0-t1.a)*t0) + (t1.a*t1.rgb);
394 gl_FragColor = vec4(tt*vLighting,1);
395 }
396 `;
397
398 this.build(vSource, fSource, vSource2, fSource2);
399 }
400
401}
402
403//------------------------------------------------------------------------------------------
404//-- InstancedDecalShader ------------------------------------------------------------------
405//------------------------------------------------------------------------------------------
406
407// Like the basic shader, but it also includes an optional decal texture.
408
409export class InstancedDecalShader extends Shader {
410 constructor() {
411 super();
412
413 // -- WebGL2 Source --
414
415 const vSource2 = `#version 300 es
416 in vec3 aVertex;
417 in vec3 aNormal;
418 in vec4 aColor;
419 in vec2 aCoordinate;
420 in mat4 aMeshMatrix;
421 in mat4 aNormalMatrix;
422
423 uniform mat4 uCameraMatrix;
424
425 uniform vec3 uAmbientColor;
426 uniform vec3 uDirectionalColor;
427 uniform vec3 uDirectionalAim;
428
429 out lowp vec3 vColor;
430 out lowp vec2 vCoordinate;
431 out lowp vec3 vLighting;
432
433 void main() {
434 lowp vec4 position = uCameraMatrix * aMeshMatrix * vec4(aVertex,1);
435 lowp vec3 normal = normalize((aNormalMatrix * vec4(aNormal,1)).xyz);
436 vColor = aColor.rgb;
437 vCoordinate = aCoordinate;
438 vLighting = uAmbientColor + uDirectionalColor * dot(normal, uDirectionalAim);
439 gl_Position = position;
440 }
441 `;
442
443 const fSource2 = `#version 300 es
444 in lowp vec3 vColor;
445 in lowp vec3 vLighting;
446 in lowp vec2 vCoordinate;
447
448 uniform sampler2D uSampler0;
449 uniform sampler2D uSampler1;
450
451 out lowp vec4 color;
452
453 void main() {
454 lowp vec3 t0 = texture(uSampler0, vCoordinate).rgb * vColor;
455 lowp vec4 t1 = texture(uSampler1, vCoordinate);
456 lowp vec3 tt = ((1.0-t1.a)*t0) + (t1.a*t1.rgb);
457 color = vec4(tt * vLighting,1);
458 }
459 `;
460
461 // -- WebGL Source --
462
463 const vSource = `
464 attribute vec3 aVertex;
465 attribute vec3 aNormal;
466 attribute vec4 aColor;
467 attribute vec2 aCoordinate;
468 attribute mat4 aMeshMatrix;
469 attribute mat4 aNormalMatrix;
470
471 uniform mat4 uCameraMatrix;
472
473 uniform vec3 uAmbientColor;
474 uniform vec3 uDirectionalColor;
475 uniform vec3 uDirectionalAim;
476
477 varying lowp vec3 vColor;
478 varying lowp vec2 vCoordinate;
479 varying lowp vec3 vLighting;
480
481 void main() {
482 lowp vec4 position = uCameraMatrix * aMeshMatrix * vec4(aVertex,1);
483 lowp vec3 normal = normalize((aNormalMatrix * vec4(aNormal,1)).xyz);
484 vColor = aColor.rgb;
485 vCoordinate = aCoordinate;
486 vLighting = uAmbientColor + uDirectionalColor * dot(normal, uDirectionalAim);
487 gl_Position = position;
488 }
489 `;
490
491 const fSource = `
492 varying lowp vec3 vColor;
493 varying lowp vec3 vLighting;
494 varying lowp vec2 vCoordinate;
495
496 uniform sampler2D uSampler0;
497 uniform sampler2D uSampler1;
498
499 void main() {
500 lowp vec3 t0 = texture2D(uSampler0, vCoordinate).rgb * vColor;
501 lowp vec4 t1 = texture2D(uSampler1, vCoordinate);
502 lowp vec3 tt = ((1.0-t1.a)*t0) + (t1.a*t1.rgb);
503 gl_FragColor = vec4(tt*vLighting,1);
504 }
505 `;
506
507 this.build(vSource, fSource, vSource2, fSource2);
508 }
509
510}
511
512
513//------------------------------------------------------------------------------------------
514//-- GeometryShader ------------------------------------------------------------------------
515//------------------------------------------------------------------------------------------
516
517// First pass in deferred lighting pipeline. Renders the diffuse scene, plus buffers containing
518// normal and position data. Only use this if you're rendering into a GeometryBuffer.
519
520export class GeometryShader extends Shader {
521 constructor() {
522 super();
523
524 // -- WebGL2 Source --
525
526 const vSource2 = `#version 300 es
527 in vec3 aVertex;
528 in vec3 aNormal;
529 in vec4 aColor;
530 in vec2 aCoordinate;
531
532 uniform mat4 uMeshToViewMatrix;
533 uniform mat4 uNormalMatrix;
534 uniform mat4 uViewNormalMatrix;
535 uniform mat4 uProjectionMatrix;
536
537 uniform vec3 uAmbientColor;
538 uniform vec3 uDirectionalColor;
539 uniform vec3 uDirectionalAim;
540
541 out lowp vec3 vColor;
542 out lowp vec2 vCoordinate;
543 out lowp vec3 vLighting;
544 out lowp vec3 vNormal;
545 out lowp vec3 vPosition;
546
547 void main() {
548
549 lowp vec4 position = uMeshToViewMatrix * vec4(aVertex,1);
550 lowp vec3 normal = normalize((uNormalMatrix * vec4(aNormal,1)).xyz);
551
552 vColor = aColor.rgb;
553 vCoordinate = aCoordinate;
554 vNormal = (uViewNormalMatrix * vec4(normal,1)).xyz;
555 vLighting = (uAmbientColor + uDirectionalColor * dot(normal, uDirectionalAim));
556 vPosition = position.xyz / position.w;
557
558 gl_Position = uProjectionMatrix * position;
559 }
560 `;
561
562 const fSource2 = `#version 300 es
563
564 in lowp vec3 vColor;
565 in lowp vec2 vCoordinate;
566 in lowp vec3 vLighting;
567 in lowp vec3 vNormal;
568 in lowp vec3 vPosition;
569
570 uniform sampler2D uSampler0;
571 uniform sampler2D uSampler1;
572
573 layout(location = 0) out lowp vec4 color0;
574 layout(location = 1) out lowp vec4 color1;
575 layout(location = 2) out lowp vec4 color2;
576
577 void main() {
578 lowp vec3 t0 = texture(uSampler0, vCoordinate).rgb * vColor;
579 lowp vec4 t1 = texture(uSampler1, vCoordinate);
580 lowp vec3 tt = ((1.0-t1.a)*t0) + (t1.a*t1.rgb);
581 color0 = vec4(tt * vLighting,1);
582 color1 = vec4(vNormal,1.0);
583 color2 = vec4(vPosition,1.0);
584 }
585 `;
586
587 // -- WebGL Source --
588
589 const vSource = `
590 attribute vec3 aVertex;
591 attribute vec3 aNormal;
592 attribute vec4 aColor;
593 attribute vec2 aCoordinate;
594
595 uniform mat4 uMeshToViewMatrix;
596 uniform mat4 uNormalMatrix;
597 uniform mat4 uViewNormalMatrix;
598 uniform mat4 uProjectionMatrix;
599
600 uniform vec3 uAmbientColor;
601 uniform vec3 uDirectionalColor;
602 uniform vec3 uDirectionalAim;
603
604 varying lowp vec3 vColor;
605 varying lowp vec2 vCoordinate;
606 varying lowp vec3 vLighting;
607 varying lowp vec3 vNormal;
608 varying lowp vec3 vPosition;
609
610 void main() {
611 lowp vec4 position = uMeshToViewMatrix * vec4(aVertex,1);
612 lowp vec3 normal = normalize((uNormalMatrix * vec4(aNormal,1)).xyz);
613
614 vColor = aColor.rgb;
615 vCoordinate = aCoordinate;
616 vNormal = (uViewNormalMatrix * vec4(normal,1)).xyz;
617 vLighting = (uAmbientColor + uDirectionalColor * dot(normal, uDirectionalAim));
618 vPosition = position.xyz / position.w;
619
620 gl_Position = uProjectionMatrix * position;
621 }
622 `;
623
624 const fSource = `
625 #extension GL_EXT_draw_buffers : require
626
627 varying lowp vec3 vColor;
628 varying lowp vec2 vCoordinate;
629 varying lowp vec3 vLighting;
630 varying lowp vec3 vNormal;
631 varying lowp vec3 vPosition;
632
633 uniform sampler2D uSampler0;
634 uniform sampler2D uSampler1;
635
636 void main() {
637 lowp vec3 t0 = texture2D(uSampler0, vCoordinate).rgb * vColor;
638 lowp vec4 t1 = texture2D(uSampler1, vCoordinate);
639 lowp vec3 tt = ((1.0-t1.a)*t0) + (t1.a*t1.rgb);
640 gl_FragData[0] = vec4(tt * vLighting,1);
641 gl_FragData[1] = vec4(vNormal,1.0);
642 gl_FragData[2] = vec4(vPosition,1.0);
643 }
644 `;
645
646 this.build(vSource, fSource, vSource2, fSource2);
647 }
648
649}
650
651//------------------------------------------------------------------------------------------
652//-- InstancedGeometryShader ---------------------------------------------------------------
653//------------------------------------------------------------------------------------------
654
655// First pass in deferred lighting pipeline. Renders the diffuse scene, plus buffers containing
656// normal and position data. Only use this if you're rendering into a GeometryBuffer.
657
658export class InstancedGeometryShader extends Shader {
659 constructor() {
660 super();
661
662 // -- WebGL2 Source --
663
664 const vSource2 = `#version 300 es
665 in vec3 aVertex;
666 in vec3 aNormal;
667 in vec4 aColor;
668 in vec2 aCoordinate;
669 in mat4 aMeshMatrix;
670 in mat4 aNormalMatrix;
671
672 uniform mat4 uViewMatrix;
673 uniform mat4 uViewNormalMatrix;
674 uniform mat4 uProjectionMatrix;
675
676 uniform vec3 uAmbientColor;
677 uniform vec3 uDirectionalColor;
678 uniform vec3 uDirectionalAim;
679
680 out lowp vec3 vColor;
681 out lowp vec2 vCoordinate;
682 out lowp vec3 vLighting;
683 out lowp vec3 vNormal;
684 out lowp vec3 vPosition;
685
686 void main() {
687
688 lowp vec4 position = uViewMatrix * aMeshMatrix * vec4(aVertex,1);
689 lowp vec3 normal = normalize((aNormalMatrix * vec4(aNormal,1)).xyz);
690
691 vColor = aColor.rgb;
692 vCoordinate = aCoordinate;
693 vNormal = (uViewNormalMatrix * vec4(normal,1)).xyz;
694 vLighting = (uAmbientColor + uDirectionalColor * dot(normal, uDirectionalAim));
695 vPosition = position.xyz / position.w;
696
697 gl_Position = uProjectionMatrix * position;
698 }
699 `;
700
701 const fSource2 = `#version 300 es
702
703 in lowp vec3 vColor;
704 in lowp vec2 vCoordinate;
705 in lowp vec3 vLighting;
706 in lowp vec3 vNormal;
707 in lowp vec3 vPosition;
708
709 uniform sampler2D uSampler0;
710 uniform sampler2D uSampler1;
711
712 layout(location = 0) out lowp vec4 color0;
713 layout(location = 1) out lowp vec4 color1;
714 layout(location = 2) out lowp vec4 color2;
715
716 void main() {
717 lowp vec3 t0 = texture(uSampler0, vCoordinate).rgb * vColor;
718 lowp vec4 t1 = texture(uSampler1, vCoordinate);
719 lowp vec3 tt = ((1.0-t1.a)*t0) + (t1.a*t1.rgb);
720 color0 = vec4(tt * vLighting,1);
721 color1 = vec4(vNormal,1.0);
722 color2 = vec4(vPosition,1.0);
723 }
724 `;
725
726 // -- WebGL Source --
727
728 const vSource = `
729 attribute vec3 aVertex;
730 attribute vec3 aNormal;
731 attribute vec4 aColor;
732 attribute vec2 aCoordinate;
733 attribute mat4 aMeshMatrix;
734 attribute mat4 aNormalMatrix;
735
736 uniform mat4 uViewMatrix;
737 uniform mat4 uViewNormalMatrix;
738 uniform mat4 uProjectionMatrix;
739
740 uniform vec3 uAmbientColor;
741 uniform vec3 uDirectionalColor;
742 uniform vec3 uDirectionalAim;
743
744 varying lowp vec3 vColor;
745 varying lowp vec2 vCoordinate;
746 varying lowp vec3 vLighting;
747 varying lowp vec3 vNormal;
748 varying lowp vec3 vPosition;
749
750 void main() {
751 lowp vec4 position = uViewMatrix * aMeshMatrix * vec4(aVertex,1);
752 lowp vec3 normal = normalize((aNormalMatrix * vec4(aNormal,1)).xyz);
753
754 vColor = aColor.rgb;
755 vCoordinate = aCoordinate;
756 vNormal = (uViewNormalMatrix * vec4(normal,1)).xyz;
757 vLighting = (uAmbientColor + uDirectionalColor * dot(normal, uDirectionalAim));
758 vPosition = position.xyz / position.w;
759
760 gl_Position = uProjectionMatrix * position;
761 }
762 `;
763
764 const fSource = `
765 #extension GL_EXT_draw_buffers : require
766
767 varying lowp vec3 vColor;
768 varying lowp vec2 vCoordinate;
769 varying lowp vec3 vLighting;
770 varying lowp vec3 vNormal;
771 varying lowp vec3 vPosition;
772
773 uniform sampler2D uSampler0;
774 uniform sampler2D uSampler1;
775
776 void main() {
777 lowp vec3 t0 = texture2D(uSampler0, vCoordinate).rgb * vColor;
778 lowp vec4 t1 = texture2D(uSampler1, vCoordinate);
779 lowp vec3 tt = ((1.0-t1.a)*t0) + (t1.a*t1.rgb);
780 gl_FragData[0] = vec4(tt * vLighting,1);
781 gl_FragData[1] = vec4(vNormal,1.0);
782 gl_FragData[2] = vec4(vPosition,1.0);
783 }
784 `;
785
786 this.build(vSource, fSource, vSource2, fSource2);
787 }
788
789}
790
791//------------------------------------------------------------------------------------------
792//-- TranslucentGeometryShader -------------------------------------------------------------
793//------------------------------------------------------------------------------------------
794
795// No lighting, just application of the color of the triangles with appropriate blend set.
796// Leaves the other parts of the geometry buffer unchanged.
797
798export class TranslucentGeometryShader extends Shader {
799 constructor() {
800 super();
801
802 // -- WebGL2 Source --
803
804 const vSource2 = `#version 300 es
805 in vec3 aVertex;
806 in vec4 aColor;
807 in vec2 aCoordinate;
808
809 uniform mat4 uMeshToScreenMatrix;
810
811 out lowp vec4 vColor;
812 out lowp vec2 vCoordinate;
813
814 void main() {
815 vColor = aColor;
816 vCoordinate = aCoordinate;
817 gl_Position = uMeshToScreenMatrix * vec4(aVertex,1);
818 }
819 `;
820
821 const fSource2 = `#version 300 es
822 in lowp vec4 vColor;
823 in lowp vec2 vCoordinate;
824
825 uniform sampler2D uSampler0;
826
827 layout(location = 0) out lowp vec4 color0;
828 layout(location = 1) out lowp vec4 color1;
829 layout(location = 2) out lowp vec4 color2;
830
831 void main() {
832 color0 = texture(uSampler0, vCoordinate) * vColor;
833 color1 = color1;
834 color2 = color2;
835 }
836 `;
837
838 // -- WebGL Source --
839
840 const vSource = `
841 attribute vec3 aVertex;
842 attribute vec4 aColor;
843 attribute vec2 aCoordinate;
844
845 uniform mat4 uMeshToScreenMatrix;
846
847 varying lowp vec2 vCoordinate;
848 varying lowp vec4 vColor;
849
850 void main() {
851 vColor = aColor;
852 vCoordinate = aCoordinate;
853 gl_Position = uMeshToScreenMatrix * vec4(aVertex,1);
854 }
855 `;
856
857 const fSource = `
858 #extension GL_EXT_draw_buffers : require
859 varying lowp vec4 vColor;
860 varying lowp vec2 vCoordinate;
861
862 uniform sampler2D uSampler0;
863
864 void main() {
865 gl_FragData[0] = texture2D(uSampler0, vCoordinate) * vColor;
866 gl_FragData[1] = gl_FragData[1];
867 gl_FragData[2] = gl_FragData[2];
868 }
869 `;
870
871 this.build(vSource, fSource, vSource2, fSource2);
872 }
873
874 apply() {
875 super.apply();
876 this.gl.enable(this.gl.BLEND);
877 //this.gl.blendFunc(this.gl.ONE, this.gl.SRC_ALPHA);
878 this.gl.blendFunc(this.gl.ONE, this.gl.ONE_MINUS_SRC_ALPHA);
879 //this.gl.blendFunc(this.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA);
880 //this.gl.blendFunc(this.DEST_ALPHA, this.gl.ONE_MINUS_DEST_ALPHA);
881 this.gl.depthMask(false);
882 this.gl.polygonOffset(-1, 0);
883 }
884
885}
886
887//------------------------------------------------------------------------------------------
888//-- PassthruShader ------------------------------------------------------------------------
889//------------------------------------------------------------------------------------------
890
891// Passes the input texture unchanged to the framebuffer.
892
893export class PassthruShader extends Shader {
894 constructor() {
895 super();
896
897 // -- WebGL2 Source --
898
899 const vSource2 = `#version 300 es
900 in vec3 aVertex;
901
902 out lowp vec2 vCoordinate;
903
904 void main() {
905 gl_Position = vec4(aVertex.xy, 0.0, 1.0);
906 vCoordinate = (aVertex.xy + vec2(1.0)) / 2.0;
907 }
908 `;
909
910 const fSource2 = `#version 300 es
911 in lowp vec2 vCoordinate;
912
913 uniform sampler2D uSampler0;
914
915 out lowp vec4 color;
916
917 void main() {
918 color = texture(uSampler0, vCoordinate);
919 }
920 `;
921
922 // -- WebGL Source --
923
924 const vSource = `
925 attribute vec3 aVertex;
926
927 varying lowp vec2 vCoordinate;
928
929 void main() {
930 gl_Position = vec4(aVertex.xy, 0.0, 1.0);
931 vCoordinate = (aVertex.xy + vec2(1.0)) / 2.0;
932 }
933 `;
934
935 const fSource = `
936 varying lowp vec2 vCoordinate;
937
938 uniform sampler2D uSampler0;
939
940 void main() {
941 gl_FragColor = texture2D(uSampler0, vCoordinate);
942 }
943 `;
944
945 this.build(vSource, fSource, vSource2, fSource2);
946 }
947
948}
949
950
951//------------------------------------------------------------------------------------------
952//-- AOShader ------------------------------------------------------------------------------
953//------------------------------------------------------------------------------------------
954
955// Given a set of geometry buffers, produces a lighting buffer with screen-space ambient
956// occlusion. This uses the Alchemy AO algorithm.
957//
958// There are four parameters that affect the look of the ambient occusion:
959//
960// * Radius - Size of the sampling circle in world units.
961// * Sample Count - Number of points to sample inside the circle.
962// * Density - Darkness of the shadows.
963// * Falloff - Exponential decrease of shadows with distance.
964//
965// Radius and Sample Count are set using generateKernel. Higher sample counts will yield smoother
966// results but will add to compute time.
967
968export class AOShader extends Shader {
969 constructor() {
970 super();
971
972 this.radius = 1.0;
973 this.count = 16;
974 this.fov = toRad(60);
975 this.density = 1.0; // Darkness of shadow
976 this.falloff = 1.0; // How fast shadow fades from corner
977 this.bias = 0.001; // Distance correction factor for points perpendicular to normal
978 this.epsilon = 0.0001; // Prevents 0 divide for tiny sample vectors
979
980 this.generateNoise();
981
982 // -- WebGL2 Source --
983
984 const vSource2 = `#version 300 es
985
986 in vec3 aVertex;
987
988 out lowp vec2 vCoordinate;
989
990 void main() {
991 gl_Position = vec4(aVertex.xy, 0.0, 1.0);
992 vCoordinate = (aVertex.xy + vec2(1.0, 1.0)) / 2.0;
993 }
994 `;
995
996 const fSource2 = `#version 300 es
997
998 in lowp vec2 vCoordinate;
999
1000 uniform sampler2D uSampler0; // Normal
1001 uniform sampler2D uSampler1; // Position
1002 uniform sampler2D uSampler2; // Noise
1003
1004 uniform highp vec2 uKernel[64];
1005 uniform int uKernelSize;
1006 uniform highp float uDensity;
1007 uniform highp float uFalloff;
1008 uniform highp float uBias;
1009 uniform highp float uEpsilon;
1010 uniform highp float uTextureWidth0;
1011 uniform highp float uTextureHeight0;
1012 uniform highp float uTextureWidth2;
1013 uniform highp float uTextureHeight2;
1014
1015 out highp vec4 color;
1016
1017 void main() {
1018
1019 highp vec3 normal = texture(uSampler0, vCoordinate).xyz;
1020 highp vec3 centerXYZ = texture(uSampler1, vCoordinate).xyz;
1021
1022 highp vec2 lookup = vec2(vCoordinate.x*(uTextureWidth0-1.0)/uTextureWidth2, vCoordinate.y*(uTextureHeight0-1.0)/uTextureHeight2);
1023 highp vec4 raw = texture(uSampler2, lookup);
1024 highp mat2 noise = mat2(raw.r, raw.g, raw.b, raw.a);
1025
1026 highp float sum = 0.0;
1027 for (int i = 0; i < 64; i++) {
1028 if (i == uKernelSize) break;
1029 highp vec2 s = vCoordinate + ((uKernel[i]*noise) / -centerXYZ.z);
1030 highp vec3 sampleXYZ = texture(uSampler1, s).xyz;
1031 highp vec3 sampleVector = centerXYZ - sampleXYZ;
1032 highp float normalDot = max(0.0, dot(sampleVector, normal) + centerXYZ.z * uBias);
1033 highp float vectorDot = dot(sampleVector, sampleVector) + uEpsilon;
1034 sum += (normalDot / vectorDot);
1035 }
1036
1037 highp float occlusion = uDensity * sum / float(uKernelSize);
1038 highp float ao = pow(max(0.0, 1.0-occlusion), uFalloff);
1039 color = vec4(ao, ao, ao, 1);
1040 }
1041 `;
1042
1043 // -- WebGL Source --
1044
1045 const vSource = `
1046 attribute vec3 aVertex;
1047
1048 varying highp vec2 vCoordinate;
1049
1050 void main() {
1051 gl_Position = vec4(aVertex.xy, 0.0, 1.0);
1052 vCoordinate = (aVertex.xy + vec2(1.0)) / 2.0;
1053 }
1054 `;
1055
1056 const fSource = `
1057 varying highp vec2 vCoordinate;
1058
1059 uniform sampler2D uSampler0; // Normal
1060 uniform sampler2D uSampler1; // Position
1061 uniform sampler2D uSampler2; // Noise
1062
1063 uniform lowp vec2 uKernel[64];
1064 uniform int uKernelSize;
1065 uniform lowp float uDensity;
1066 uniform lowp float uFalloff;
1067 uniform lowp float uBias;
1068 uniform lowp float uEpsilon;
1069 uniform lowp float uTextureWidth0;
1070 uniform lowp float uTextureHeight0;
1071 uniform lowp float uTextureWidth2;
1072 uniform lowp float uTextureHeight2;
1073
1074 void main() {
1075 lowp vec3 normal = texture2D(uSampler0, vCoordinate).xyz;
1076 lowp vec3 centerXYZ = texture2D(uSampler1, vCoordinate).xyz;
1077
1078 lowp vec2 lookup = vec2(vCoordinate.x*(uTextureWidth0-1.0)/uTextureWidth2, vCoordinate.y*(uTextureHeight0-1.0)/uTextureHeight2);
1079 lowp vec4 raw = texture2D(uSampler2, lookup);
1080 lowp mat2 noise = mat2(raw.r, raw.g, raw.b, raw.a);
1081
1082 lowp float sum = 0.0;
1083 for (int i = 0; i < 64; i++) {
1084 if (i == uKernelSize) break;
1085 lowp vec2 sample = vCoordinate + (uKernel[i]*noise) / -centerXYZ.z;
1086 lowp vec3 sampleXYZ = texture2D(uSampler1, sample).xyz;
1087 lowp vec3 sampleVector = centerXYZ - sampleXYZ;
1088 lowp float normalDot = max(0.0, dot(sampleVector, normal) + centerXYZ.z * uBias);
1089 lowp float vectorDot = dot(sampleVector, sampleVector) + uEpsilon;
1090 sum += normalDot / vectorDot;
1091 }
1092 lowp float occlusion = uDensity * sum / float(uKernelSize);
1093 lowp float ao = pow(max(0.0, 1.0-occlusion), uFalloff);
1094
1095 gl_FragColor = vec4(ao, ao, ao, 1);
1096
1097 }
1098 `;
1099
1100 this.build(vSource, fSource, vSource2, fSource2);
1101 }
1102
1103 destroy() {
1104 super.destroy();
1105 if (this.noise) this.noise.destroy();
1106 }
1107
1108 apply() {
1109 super.apply();
1110 if (this.noise) this.noise.apply(2);
1111 if (!this.kernel) this.generateKernel();
1112 this.setUniform("uKernel", this.kernel);
1113 this.setUniform("uKernelSize", this.kernel.length);
1114 this.setUniform("uDensity", this.density);
1115 this.setUniform("uFalloff", this.falloff);
1116 this.setUniform("uBias", this.bias);
1117 this.setUniform("uEpsilon", this.epsilon);
1118 }
1119
1120 // This creates the sampling kernel used by the ao algorithm.
1121 // The radius is the distance in world space coordinates to check for occluders
1122 // The count is the number of samples taken for each pixel. Max is 64. Big numbers will slow rendering.
1123
1124 setRadius(radius = 1) {
1125 this.radius = radius;
1126 this.kernel = null;
1127 }
1128
1129 setCount(count = 16) {
1130 this.count = count;
1131 this.kernel = null;
1132 }
1133
1134 setFOV(fov = 60) {
1135 this.fov = fov;
1136 this.kernel = null;
1137 }
1138
1139 generateKernel() {
1140 this.kernel = [];
1141 const r = this.radius / Math.sin(this.fov/2);
1142 for (let i = 0; i < this.count; i++) { // Spiral sample points using golden angle.
1143 const rho = r*Math.sqrt((i+1)/this.count);
1144 const phi = i * 2.39996322972865332;
1145 this.kernel.push([rho * Math.cos(phi), rho * Math.sin(phi)]);
1146 }
1147 }
1148
1149 // Noise is a dithered rotation matrix that is used to perturb the sample kernel so we can get away with using
1150 // fewer samples.
1151
1152 generateNoise() {
1153 const noise = [];
1154
1155 noise.push(m2_rotation(0 * TAU / 15));
1156 noise.push(m2_rotation(8 * TAU / 15));
1157 noise.push(m2_rotation(2 * TAU / 15));
1158 noise.push(m2_rotation(10 * TAU / 15));
1159
1160 noise.push(m2_rotation(12 * TAU / 15));
1161 noise.push(m2_rotation(4 * TAU / 15));
1162 noise.push(m2_rotation(14 * TAU / 15));
1163 noise.push(m2_rotation(6 * TAU / 15));
1164
1165 noise.push(m2_rotation(3 * TAU / 15));
1166 noise.push(m2_rotation(11 * TAU / 15));
1167 noise.push(m2_rotation(1 * TAU / 15));
1168 noise.push(m2_rotation(9 * TAU / 15));
1169
1170 noise.push(m2_rotation(15 * TAU / 15));
1171 noise.push(m2_rotation(7 * TAU / 15));
1172 noise.push(m2_rotation(13 * TAU / 15));
1173 noise.push(m2_rotation(5 * TAU / 15));
1174
1175 this.noise = new TextureTable(4, 4, noise);
1176 }
1177
1178}
1179
1180//------------------------------------------------------------------------------------------
1181//-- BlendShader -------------------------------------------------------------------------
1182//------------------------------------------------------------------------------------------
1183
1184// Combines two images.
1185
1186export class BlendShader extends Shader {
1187 constructor() {
1188 super();
1189
1190 // -- WebGL2 Source --
1191
1192 const vSource2 = `#version 300 es
1193
1194 in vec3 aVertex;
1195
1196 out lowp vec2 vCoordinate;
1197
1198 void main() {
1199 gl_Position = vec4(aVertex.xy, 0.0, 1.0);
1200 vCoordinate = (aVertex.xy + vec2(1.0)) / 2.0;
1201 }
1202 `;
1203
1204 const fSource2 = `#version 300 es
1205
1206 in lowp vec2 vCoordinate;
1207
1208 uniform sampler2D uSampler0;
1209 uniform sampler2D uSampler1;
1210
1211 out lowp vec4 color;
1212
1213 void main() {
1214 color = texture(uSampler0, vCoordinate) * texture(uSampler1, vCoordinate);
1215 }
1216 `;
1217
1218 // -- WebGL Source --
1219
1220 const vSource = `
1221 attribute vec3 aVertex;
1222
1223 varying lowp vec2 vCoordinate;
1224
1225 void main() {
1226 gl_Position = vec4(aVertex.xy, 0.0, 1.0);
1227 vCoordinate = (aVertex.xy + vec2(1.0)) / 2.0;
1228 }
1229 `;
1230
1231 const fSource = `
1232 varying highp vec2 vCoordinate;
1233
1234 uniform sampler2D uSampler0;
1235 uniform sampler2D uSampler1;
1236
1237 void main() {
1238 gl_FragColor = texture2D(uSampler0, vCoordinate) * texture2D(uSampler1, vCoordinate);
1239 }
1240 `;
1241
1242 this.build(vSource, fSource, vSource2, fSource2);
1243 }
1244
1245}