-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpost.html
859 lines (824 loc) · 49 KB
/
post.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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="MapStuff - Example Personal Blog">
<title>Blog | MapStuff</title>
<link rel="icon" href="icon.ico">
<link rel="shortcut icon" href="icon.ico">
<meta property="og:title" content="Mapstuff">
<meta property="og:type" content="article">
<meta property="og:url" content="https://alexaac.github.io/mapstuff/">
<meta property="og:description" content="Mapstuff example blog">
<meta property="article:publisher" content="https://alexaac.github.io">
<meta property="article:section" content="Article Tag">
<meta property="article:tag" content="Article Tag">
<meta property="og:image" content="https://alexaac.github.io/mapstuff/img/og_image_1200_630.png">
<meta property="og:image:type" content="image/png">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="twitter:card" content="summary_large_image">
<meta property="twitter:image" content="https://alexaac.github.io/mapstuff/img/og_image_1200_630.png">
<meta property="twitter:site" content="@maptheclouds">
<link rel="stylesheet" href="css/main.css">
<link rel="stylesheet" href="css/ft-syntax-highlight.min.css">
</head>
<body>
<div class="mps-wrap-flex">
<header class="header">
<div class="nav-flex">
<div class="nav-brand">
<a class="nav-brand-link" href="https://alexaac.github.io/mapstuff">
<img
src="img/logo_text_black.svg"
alt="MapStuff brand logo"
class="nav-brand"
/></a>
</div>
<div class="nav-mobile-button">
<span></span> <span></span> <span></span> <span></span>
</div>
<nav role="navigation" class="nav-menu-flex">
<div class="nav-menu-wrap">
<div role="list" class="nav-menu-list-flex">
<div role="listitem" class="nav-menu-item">
<a href="#" aria-label="blank link Latest" class="nav-link mps-link">Latest</a>
</div>
<div role="listitem" class="nav-menu-item">
<a href="#" aria-label="blank link Maps" class="nav-link mps-link">Maps</a>
</div>
<div role="listitem" class="nav-menu-item">
<a href="#" aria-label="blank link Dataviz" class="nav-link mps-link">Dataviz</a>
</div>
<div role="listitem" class="nav-menu-item">
<a href="#" aria-label="blank link Learning" class="nav-link mps-link">Learning</a>
</div>
<div role="listitem" class="nav-menu-item">
<a href="design_system.html" aria-label="Design link 1" class="nav-link mps-link"
>Design</a
>
</div>
</div>
</div>
</nav>
<div class="nav-menu-wrap nav-right">
<div role="list" class="nav-menu-list-flex">
<div role="listitem" class="nav-menu-item">
<a href="#" aria-label="blank link Login" class="nav-link mps-link">Login</a>
</div>
<div role="listitem" class="nav-menu-item mps-subscribe">
<a href="#" aria-label="blank link Subscribe" class="mps-btn mps-btn-primary">Subscribe</a>
</div>
</div>
</div>
</div>
<div class="article-hero">
<div class="mps-overlay">
<div class="mps-overlay-info-flex">
<div class="mps-overlay-info-container">
<div class="mps-overlay-info-in">
<span class="mps-article-category">Maps</span>
<h1 class="mps-overlay-title">Procedural GL JS</h1>
<p>
3D map experiences on the web, written in JavaScript and WebGL.
</p>
<div class="mps-author-info-flex">
<img class="mps-author-image" src="https://mps-ph.s3.us-east-2.amazonaws.com/author.png" alt="Alexa Cristina">
<p>
<a href="#" aria-label="blank link 7">Alexa Cristina</a>
• <time datetime="2021-06-07T09:00:00+00:00" itemprop="datePublished">June 7, 2021</time> • 4 min read
</p>
</div>
<div role="list" class="article-tags">
<div role="listitem" class="article-tag">
<a href="#" aria-label="blank link 8" class="article-tag-link" rel="noopener noreferrer" target="_blank">3D</a>
</div>
<div role="listitem" class="article-tag">
<a href="#" aria-label="blank link 9" class="article-tag-link" rel="noopener noreferrer" target="_blank">Maps</a>
</div>
<div role="listitem" class="article-tag">
<a href="#" aria-label="blank link 10" class="article-tag-link" rel="noopener noreferrer" target="_blank">LiDAR</a>
</div>
<div role="listitem" class="article-tag">
<a href="#" aria-label="blank link 11" class="article-tag-link" rel="noopener noreferrer" target="_blank">DEM</a>
</div>
<div role="listitem" class="article-tag">
<a href="#" aria-label="blank link 12" class="article-tag-link" rel="noopener noreferrer" target="_blank">WebGL</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</header>
<main class="main">
<a href="#top" aria-label="Top of the page">
<button id="top-btn"> ˄ </button>
</a>
<div class="section first">
<article class="article-container container">
<div class="article-text">
<p>During <a href="https://twitter.com/hashtag/30DayMapChallenge" aria-label="30DayMapChallenge link">#30DayMapChallenge</a> I was hunting for 3D maps, and there it was: a post showing a flight over a mountain, made using an recently open-sourced library, <a href="https://www.procedural.eu/" aria-label="Procedural GL link">Procedural GL JS</a>! Not Google, not Mapbox.. not MapLibre GL 🙂
</p>
<p>
I will show some details about the library, and a few examples of my implementation. But first, a few words about 3D maps on the web.
</p>
<p>
This will be a somewhat technical post, if you are interested bear with me, if not, you can go directly to the <a href="#Showcase" aria-label="Showcase link">Showcase</a> section and look at the beautiful pictures in the article, or enjoy the videos.
</p>
<p>
Also, this article is an example article, and must be further documented, sorry for possible mistakes.
</p>
<h2>
Let's start with 3D maps
</h2>
<p>
They have been in the digital realm for a while, and on paper since ages. Even from the oldest times people have tried to represent the terrain in a 3D perspective, using different techniques, transposed into beautiful mountains profiles. Raised-relief maps have existed since the <a href="https://en.wikipedia.org/wiki/Raised-relief_map" aria-label="Wikipedia raised relief">Qin dynasty</a> (221–206 BCE) of China, and a Bronze Age slab found in France is the oldest 3D map in Europe, and is believed to date from the early <a href="https://www.bbc.com/news/world-europe-56648055" aria-label="bbc">Bronze Age</a>, between 1900 BC and 1650 BC. Also, old topographical maps represented various forms of relief.
</p>
<div class="mps-container lg">
<div class="article-img-flex">
<div class="article-img-block sm">
<div class="article-img">
<a href="img/post/_117856764_rockthisone.jpg" aria-label="img 1">
<img src="https://mps-ph.s3.us-east-2.amazonaws.com/_117856764_rockthisone.jpg" alt="3D map in Europe">
</a>
<div class="article-img-desc">
<a href="https://www.bbc.com/news/world-europe-56648055" aria-label="img 2">bbc.com</a>
</div>
<div class="article-img-text">
Oldest bronze 3D map in Europe, 1900 BC - 1650 BC
</div>
</div>
</div>
<div class="article-img-block sm">
<div class="article-img">
<a href="img/post/carte.png" aria-label="img 3">
<img src="https://mps-ph.s3.us-east-2.amazonaws.com/carte.png" alt="Carte des Indes Orientales">
</a>
<div class="article-img-desc">
<a href="https://www.davidrumsey.com/luna/servlet/detail/RUMSEY~8~1~326565~90095122:Carte-des-Indes-Orientales-?sort=Pub_List_No_InitialSort%2CPub_Date%2CPub_List_No%2CSeries_No&qvq=q:moon%20atlas;sort:Pub_List_No_InitialSort%2CPub_Date%2CPub_List_No%2CSeries_No;lc:RUMSEY~8~1&mi=17&trs=1069#" aria-label="img 4">davidrumsey.com</a>
</div>
<div class="article-img-text">
Carte des Indes Orientales, 1665.
</div>
</div>
</div>
<div class="article-img-block sm">
<div class="article-img">
<a href="img/post/_117860407_rock5.jpg" aria-label="img 5">
<img src="https://mps-ph.s3.us-east-2.amazonaws.com/topo.png" alt="Topographical Map of Ancient Rome">
</a>
<div class="article-img-desc">
<a href="https://www.nga.gov/collection/art-object-page.112707.html" aria-label="img 6">nga.gov</a>
</div>
<div class="article-img-text">
Topographical Map of Ancient Rome, 1557.
</div>
</div>
</div>
</div>
</div>
<p>
If we refer only to digital Cartography, there are many proprietary as well as open-source applications that can create a 3D map view starting from the terrain elevation, most reknowned being ESRI's ArcGIS and QGIS.
</p>
<p>
Modern 3D cartography maps are created using 3D models from local measurements of the terrain, high resolution photography, or from satellite immagery and aerial photography. Below you can see beautiful images of <a href="https://washingtonstategeology.wordpress.com/2021/06/02/high-resolution-lidar-images-of-washingtons-geology-now-freely-available/" aria-label="article 1">Washington state geology</a>, derived from LiDAR cloud point data. And a 3D model of <a href="https://www.nytimes.com/interactive/2015/01/09/sports/the-dawn-wall-el-capitan.html?ref=sports" aria-label="article 2">El Capitan</a>, from a LiDAR scan consisting of over <a href="https://www.nytimes.com/times-insider/2015/01/20/scaling-el-capitan-for-your-browser/" aria-label="article 3">36 million points</a>.
</p>
<div class="mps-container lg">
<div class="article-img-block lg">
<div class="article-img orig">
<a href="img/posts/wash_hires.png" aria-label="img 7">
<img src="img/wash_hires.png" alt="Washington High Resolution Images">
</a>
</div>
<div class="article-img-desc">
<a href="https://washingtonstategeology.wordpress.com/2021/06/02/high-resolution-lidar-images-of-washingtons-geology-now-freely-available/" aria-label="img 8">washingtonstategeology</a>
</div>
<div class="article-img-text">
High-resolution lidar images of Washington’s geology.
</div>
</div>
</div>
<div class="mps-container md">
<div class="article-img-block lg">
<div class="article-img orig">
<a href="img/post/elcap4-blog480.png" aria-label="img 9">
<img src="https://mps-ph.s3.us-east-2.amazonaws.com/elcap4-blog480.png" alt="El Capitan 3D model">
</a>
</div>
<div class="article-img-desc">
<a href="https://www.nytimes.com/times-insider/2015/01/20/scaling-el-capitan-for-your-browser/" aria-label="img 10">nytimes.com</a>
</div>
<div class="article-img-text">
El Capitan’s most challenging pitch, the Dawn Wall, 3D.
</div>
</div>
</div>
<p>
Below are some examples of 3D visualizations of <a href="https://en.wikipedia.org/wiki/Lidar" aria-label="Wikipedia LiDAR">LiDAR</a> data using <a href="https://pdal.io/index.html" aria-label="PDAL">PDAL</a> for point cloud processing and <a href="https://entwine.io/quickstart.html" aria-label="Entwine">Entwine</a> (a webGL based library) and <a href="http://potree.org/getting_started.html" aria-label="Potree">Potree</a> to render the models in the browser.
</p>
<div class="mps-container lg">
<div class="article-img-flex gallery">
<div class="article-img-block sm">
<div class="article-img">
<a href="img/post/l1.png" aria-label="img Yosemite 1">
<img src="https://mps-ph.s3.us-east-2.amazonaws.com/l1.png" alt="Yosemite Valley 3D">
</a>
</div>
</div>
<div class="article-img-block sm">
<div class="article-img">
<a href="img/post/l2.png" aria-label="img Yosemite 2">
<img src="https://mps-ph.s3.us-east-2.amazonaws.com/l2.png" alt="Yosemite Valley 3D">
</a>
</div>
</div>
<div class="article-img-block sm">
<div class="article-img">
<a href="img/post/l3.png" aria-label="img Yosemite 3">
<img src="https://mps-ph.s3.us-east-2.amazonaws.com/l3.png" alt="Yosemite Valley 3D">
</a>
</div>
</div>
<div class="article-img-block sm">
<div class="article-img">
<a href="img/post/l4.png" aria-label="img Yosemite 4">
<img src="https://mps-ph.s3.us-east-2.amazonaws.com/l4.png" alt="Yosemite Valley 3D">
</a>
</div>
</div>
<div class="article-img-block sm">
<div class="article-img">
<a href="img/post/l5.png" aria-label="img Yosemite 5">
<img src="https://mps-ph.s3.us-east-2.amazonaws.com/l5.png" alt="Yosemite Valley 3D">
</a>
</div>
</div>
<div class="article-img-block sm">
<div class="article-img">
<a href="img/post/l6.png" aria-label="img Dublin 1">
<img src="https://mps-ph.s3.us-east-2.amazonaws.com/l6.png" alt="Dublin 3D">
</a>
</div>
</div>
<div class="article-img-block sm">
<div class="article-img">
<a href="img/post/l7.png" aria-label="img Dublin 2">
<img src="https://mps-ph.s3.us-east-2.amazonaws.com/l7.png" alt="Dublin 3D">
</a>
</div>
</div>
<div class="article-img-block sm">
<div class="article-img">
<a href="img/post/l8.png" aria-label="img Dublin 3">
<img src="https://mps-ph.s3.us-east-2.amazonaws.com/l8.png" alt="Dublin 3D">
</a>
</div>
</div>
<div class="article-img-block sm">
<div class="article-img">
<a href="img/post/l9.png" aria-label="img Dublin 4">
<img src="https://mps-ph.s3.us-east-2.amazonaws.com/l9.png" alt="Dublin 3D">
</a>
</div>
</div>
<div class="article-img-block sm">
<div class="article-img">
<a href="img/post/l10.png" aria-label="img Dublin 5">
<img src="https://mps-ph.s3.us-east-2.amazonaws.com/l10.png" alt="Dublin 3D">
</a>
</div>
</div>
</div>
</div>
<h3>Triangulation</h3>
<p>
Usually, a 3D map is created from a series of points that contain the terrain elevation in metres, which are processed into a <em>triangulated irregular network (TIN)</em> using specific algorithms based on the <a href="http://wiki.gis.com/wiki/index.php/Delaunay_triangulation" aria-label="Wiki triangulation">Delaunay criterion</a> and the <a href="http://vulnerablevancouver.ca/wp/?p=152" aria-label="Wiki Voronoi">Voronoi tesselation</a>. Further, this model can be smoothed, and an aerial image can be drapped over it, and this is the 3D terrain view from Google or Here!
</p>
<p>
Many sensors used in GIS applications (for example LIDAR), generate dense point clouds. Such applications often take advantage of more advanced data structures: for example, Triangulated Irregular Networks (TIN) that can be the base for Digital Evelation Models (DEM) and in particular for the generation of Digital Terrain Models (DTM). Point clouds can also be enriched by classification information that segments the points into ground, vegetation and building points (or other user-defined labels). [ <a href="https://doc.cgal.org/latest/Manual/tuto_gis.html" aria-label="digital models">src</a> ]
</p>
<p>
The specific data structures used for obtaining 3D models are:
</p>
<ul>
<li>
TIN: Triangulated Irregular Network, a 2D triangulation structure that connects 3D points based on their projections on the horizontal plane.
</li>
<li>
DSM: Digital Surface Model, a model of the whole scanned surface including buildings and vegetation. We use a TIN to store the DSM.
</li>
<li>
DTM: Digital Terrain Model, a model of the bare ground surface without objects like buildings or vegetation. We both use a TIN and a raster to store a DTM.
</li>
<li>
DEM: Digital Elevation Model, a more general term that includes both DSM and DTM.
</li>
</ul>
</p>
<div class="mps-container lg">
<div class="article-img-flex">
<div class="article-img-block sm">
<div class="article-img">
<img src="https://mps-ph.s3.us-east-2.amazonaws.com/220px-Delaunay-Triangulation.png" alt="Delaunay Triangulation">
</div>
<div class="article-img-desc">
<a href="https://en.wikipedia.org/wiki/Triangulated_irregular_network" aria-label="wikipedia">wikipedia.org</a>
</div>
<div class="article-img-text">
Triangulated irregular network.
</div>
</div>
<div class="article-img-block sm">
<div class="article-img">
<img src="https://mps-ph.s3.us-east-2.amazonaws.com/220px-Digitale_modell.png" alt="Digital Model">
</div>
<div class="article-img-desc">
<a href="https://en.wikipedia.org/wiki/Triangulated_irregular_network" aria-label="wikipedia 1">wikipedia.org</a>
</div>
<div class="article-img-text">
TIN overlaid with contour lines.
</div>
</div>
<div class="article-img-block sm">
<div class="article-img">
<img src="https://mps-ph.s3.us-east-2.amazonaws.com/220px-Maps-for-free_Sierra_Nevada.png" alt="Digital Model">
</div>
<div class="article-img-desc">
<a href="https://en.wikipedia.org/wiki/Digital_elevation_model" aria-label="wikipedia 2">wikipedia.org</a>
</div>
<div class="article-img-text">
Relief map of Spain's Sierra Nevada, shading and false color indicate elevation.
</div>
</div>
</div>
</div>
<h3>WebGL</h3>
<p>
If we go further, ArcGIS Online, CesiumJS, VTS Geospatial, iTowns, MapBox can render 3D maps in the browser. And the gaming applications. We will see a lot of 3D mapping for the web revolves around the WebGL API.
</p>
<p>
<a href="https://www.khronos.org/webgl/wiki" aria-label="WebGL">WebGL</a> is a web based OpenGL API written in JavaScript. It can render 3D models of a terrain transposing the real world coordinates into screen coordinates (projecting the polygons - like any mapping software).
</p>
<figure class="mps-article">
<blockquote cite="https://en.wikipedia.org/wiki/WebGL">
<p>
WebGL (Short for Web Graphics Library) is a JavaScript API for rendering interactive 2D and 3D graphics within any compatible web browser without the use of plug-ins. WebGL is fully integrated with other web standards, allowing GPU-accelerated usage of physics and image processing and effects as part of the web page canvas. WebGL elements can be mixed with other HTML elements and composited with other parts of the page or page background.
</p>
<p>
WebGL programs consist of control code written in JavaScript and shader code that is written in OpenGL ES Shading Language (GLSL ES), a language similar to C or C++, and is executed on a computer's graphics processing unit (GPU). WebGL is designed and maintained by the non-profit Khronos Group.
</p>
</blockquote>
<figcaption>—Wikipedia, <cite>WebGL</cite>
</figure>
<p>
In WebGL, you can cover a polygon 3D model with real-life imagery using the UV mapping technique.
</p>
<figure class="mps-article">
<blockquote cite="https://en.wikipedia.org/wiki/UV_mapping">
<p>
UV mapping is the 3D modeling process of projecting a 2D image to a 3D model's surface for texture mapping. The letters "U" and "V" denote the axis of the 2D texture because "X", "Y", and "Z" are already used to denote the axis of the 3D object in model space, while "W" (in addition to XYZ) is used in calculating quaternion rotations, a common operation in computer graphics.
</p>
</blockquote>
<figcaption>—Wikipedia, <cite>UV mapping</cite>
</figure>
<div class="mps-container md">
<div class="article-img-block md">
<div class="article-img orig">
<a href="img/post/400px-UVMapping.png" aria-label="UV Mapping">
<img src="https://mps-ph.s3.us-east-2.amazonaws.com/400px-UVMapping.png" alt="UV Mapping">
</a>
</div>
<div class="article-img-desc">
<a href="https://en.wikipedia.org/wiki/UV_mapping" aria-label="UV Mapping 1">wikipedia.org</a>
</div>
<div class="article-img-text">
The application of a texture in the UV space related to the effect in 3D.
</div>
</div>
</div>
<p>
There are several <a href="https://en.wikipedia.org/wiki/List_of_WebGL_frameworks" aria-label="WebGL frameworks">frameworks</a> that make working with WebGL easier, most of them written in JavaScript, like <a href="https://en.wikipedia.org/wiki/Three.js" aria-label="Three.js">Three.js</a>, <a href="https://en.wikipedia.org/wiki/Babylon.js" aria-label="Babylon.js">Babylon.js</a>, <a href="https://docs.mapbox.com/mapbox-gl-js/api/" aria-label="MapBox">MapBox GL</a>, <a href="https://cesium.com/platform/cesiumjs/" aria-label="Cesium">CesiumJS</a>, <a href="https://www.npmjs.com/package/maplibre-gl" aria-label="MapLibre">MapLibre GL</a>, and <a href="https://en.wikipedia.org/wiki/Unity_(game_engine)" aria-label="Unity">Unity game engine</a>(C#).
</p>
<p>
Here is a comprehensive <a href="https://www.libhunt.com/t/webgl" aria-label="library list">list of open-source projects</a> categorized as Webgl. There are many open-source projects, but we must be aware that at any moment they could go closed-source, or you may need to pay for specific services to use the library at its full potential.
</p>
<p>
Now, that you have seen some of the alternatives for rendering 3D maps on the web, let's get back to the new (open-source) kid in town, Procedural GL JS.
</p>
<h2>Procedural GL JS</h2>
<p>
Felix Palmer, the creator of <a href="https://www.procedural.eu/" aria-label="Procedural GL">Procedural GL JS</a>, came with this surprise near the end on #30DayMapChallenge on Twitter, when the challenge was to make a map with a new tool. Right in time!
</p>
<figure class="mps-article">
<blockquote cite="https://twitter.com/pheeelicks/status/1329806806034558978">
<p>
After 7 years of closed-source, I've changed direction and just launched: Procedural GL JS, an #opensource #webgl #javascript #threejs #dataviz library, for rendering 3D terrains.
</p>
</blockquote>
<figcaption>—Felix Palmer, <cite>#30DayMapChallenge on Twitter</cite>
</figure>
<p>
Below, you can find some details about the library, from the <a href="https://reposhub.com/javascript/maps/felixpalmer-procedural-gl-js.html" aria-label="Procedural GL documentation">documentation</a>. And here is the <a href="https://github.com/felixpalmer/procedural-gl-js" aria-label="Procedural GL repo">GitHub repository</a>.
</p>
<p>Procedural GL JS is a library for creating 3D map experiences on the web, written in JavaScript and WebGL. It is built on top THREE.js.
It provides an easy-to-use, but powerful framework to allow 3D maps to be embedded into web pages. Super-fast loading and optimized for mobile devices.
</p>
<p>
<a href="">Demo</a> | <a href="">Docs</a> | <a href="">Overlay playground</a> | <a href="">Elevation data</a>
</p>
</div>
<div class="article-text">
<h3>Key features</h3>
<p>
<ul>
<li>Stream in standard raster imagery tiles. Supports map tiles from a variety of providers</li>
<li>Batteries included elevation data. Global 3D data coverage courtesy of <a href="https://www.nasadem.xyz" rel="nofollow">nasadem.XYZ</a></li>
<li>Powerful overlay capabilities. Draw crisp markers and lines</li>
<li>Well-thought-out API, complex applications can be built without needing to deal with 3D concepts</li>
<li>Great UX and intuitive controls, mouse-based on desktop & touch-based on mobile</li>
<li>Tiny filesize means library is parsed fast. Package size is less than THREE.js thanks to code stripping</li>
<li>Novel GPU powered level-of-detail system. Off-loading to the GPU frees up the main JavaScript UI thread</li>
</ul>
</p>
<h3>Install</h3>
<p>
<code class="mps-code">npm install procedural-gl</code>
</p>
<h3>Usage</h3>
<code class="mps-code" tabindex="0">
<span class="keyword">import</span> <span class="identifier-class">Procedural</span> <span class="keyword">from</span> 'procedural-gl';
<span class="comment">// Choose a DOM element into which the library should render</span>
<span class="keyword">const</span> <span class="identifier">container</span> = document.<span class="identifier-native">getElementById</span>( <span class="unit">'container'</span> );
<span class="comment">// Configure datasources (see documentation for details)</span>
<span class="keyword">const</span> <span class="identifier">datasource</span> = { ... };
<span class="comment">// Initialize library and optionally add UI controls</span>
<span class="identifier-class">Procedural</span>.<span class="identifier-udf">init</span>( { <span class="unit">container</span>, <span class="unit">datasource</span> } );
<span class="identifier-class">Procedural</span>.<span class="identifier-udf">setRotationControlVisible</span>( true );
<span class="comment">// Load real-world location</span>
<span class="keyword">const</span> <span class="identifier">montBlanc</span> = { latitude: <span class="unit">45.8326364</span>, longitude: <span class="unit">6.8564201</span> };
<span class="identifier-class">Procedural</span>.<span class="identifier-udf">displayLocation</span>( <span class="unit">montBlanc</span> );
</code>
<h3>Screenshots</h3>
<p>
<div class="mps-container lg">
<div class="article-img-flex">
<div class="article-img-block sm">
<div class="article-img">
<a href="https://raw.githubusercontent.com/felixpalmer/procedural-gl-js/main/screenshots/1.jpg" aria-label="screenshot link 1">
<img src="https://raw.githubusercontent.com/felixpalmer/procedural-gl-js/main/screenshots/1.jpg" alt="3D mountain screenshot">
</a>
</div>
</div>
<div class="article-img-block sm">
<div class="article-img">
<a href="https://raw.githubusercontent.com/felixpalmer/procedural-gl-js/main/screenshots/2.jpg" aria-label="screenshot link 2">
<img src="https://raw.githubusercontent.com/felixpalmer/procedural-gl-js/main/screenshots/2.jpg" alt="3D mountain screenshot">
</a>
</div>
</div>
<div class="article-img-block sm">
<div class="article-img">
<a href="https://raw.githubusercontent.com/felixpalmer/procedural-gl-js/main/screenshots/3.jpg" aria-label="screenshot link 3">
<img src="https://raw.githubusercontent.com/felixpalmer/procedural-gl-js/main/screenshots/3.jpg" alt="3D mountain screenshot">
</a>
</div>
</div>
<div class="article-img-block sm">
<div class="article-img">
<a href="https://raw.githubusercontent.com/felixpalmer/procedural-gl-js/main/screenshots/4.jpg" aria-label="screenshot link 4">
<img src="https://raw.githubusercontent.com/felixpalmer/procedural-gl-js/main/screenshots/4.jpg" alt="3D mountain screenshot">
</a>
</div>
</div>
<div class="article-img-block sm">
<div class="article-img">
<a href="https://raw.githubusercontent.com/felixpalmer/procedural-gl-js/main/screenshots/5.jpg" aria-label="screenshot link 5">
<img src="https://raw.githubusercontent.com/felixpalmer/procedural-gl-js/main/screenshots/5.jpg" alt="3D mountain screenshot">
</a>
</div>
</div>
</div>
</div>
</p>
<h3>License</h3>
<p>Procedural GL JS is licensed under the <a href="https://www.mozilla.org/en-US/MPL/2.0/" rel="nofollow">Mozilla Public License Version 2.0</a>.
</p>
<h2 id="Showcase">Showcase</h2>
<p>
I have used Procedural GL JS only for the <a href="https://twitter.com/hashtag/30DayMapChallenge">#30DayMapChallenge</a> task, and below you can see some pictures and two videos. I only had to add my points and lines data, setup the data source for elevation and imagery, and pick the center of the map.
</p>
<p>
It is very easy to kick up a project because of the helpful <a href="https://www.procedural.eu/">detailed documentation</a>. I intend to explore more features of this cool library and add my own elevation data some time soon. You should give it a try, too!
</p>
<p>
I hope you have enjoyed the 3D maps on the web journey. You can find out more about 3D and LiDAR in the related articles, at the bottom of this page.
</p>
<p>
Until the next article, stay well and don't forget to admire the beauty of real 3D mountains from time to time. 😄
</p>
<div class="mps-container lg">
<div class="article-img-flex gallery">
<div class="article-img-block sm">
<div class="article-img">
<a href="img/post/p1.png" aria-label="Cheile Aiudului link 1">
<img src="https://mps-ph.s3.us-east-2.amazonaws.com/p1.png" alt="Cheile Aiudului 3D">
</a>
</div>
</div>
<div class="article-img-block sm">
<div class="article-img">
<a href="img/post/p2.png" aria-label="Cheile Aiudului link 2">
<img src="https://mps-ph.s3.us-east-2.amazonaws.com/p2.png" alt="Cheile Aiudului 3D">
</a>
</div>
</div>
<div class="article-img-block sm">
<div class="article-img">
<a href="img/post/p3.png" aria-label="Cheile Aiudului link 3">
<img src="https://mps-ph.s3.us-east-2.amazonaws.com/p3.png" alt="Cheile Aiudului 3D">
</a>
</div>
</div>
<div class="article-img-block sm">
<div class="article-img">
<a href="img/post/p4.png" aria-label="Cheile Aiudului link 4">
<img src="https://mps-ph.s3.us-east-2.amazonaws.com/p4.png" alt="Cheile Aiudului 3D">
</a>
</div>
</div>
<div class="article-img-block sm">
<div class="article-img">
<a href="img/post/p5.png" aria-label="Cheile Aiudului link 5">
<img src="https://mps-ph.s3.us-east-2.amazonaws.com/p5.png" alt="Cheile Aiudului 3D">
</a>
</div>
</div>
<div class="article-img-block sm">
<div class="article-img">
<a href="img/post/p6.png" aria-label="Cheile Aiudului link 6">
<img src="https://mps-ph.s3.us-east-2.amazonaws.com/p6.png" alt="Cheile Aiudului 3D">
</a>
</div>
</div>
<div class="article-img-block sm">
<div class="article-img">
<a href="img/post/p7.png" aria-label="Cheile Aiudului link 7">
<img src="https://mps-ph.s3.us-east-2.amazonaws.com/p7.png" alt="Cheile Aiudului 3D">
</a>
</div>
</div>
<div class="article-img-block sm">
<div class="article-img">
<a href="img/post/p8.png" aria-label="Cheile Aiudului link 8">
<img src="https://mps-ph.s3.us-east-2.amazonaws.com/p8.png" alt="Cheile Aiudului 3D">
</a>
</div>
</div>
</div>
</div>
<div class="mps-video">
<div class="mps-iframe-wrap">
<label for="3D_mountain_video_1">
Cheile Aiudului 3D map
</label>
<iframe id="3D_mountain_video_1" class="mps-iframe" width="560" height="315" src="https://www.youtube.com/embed/7ySclCJQAVU?autoplay=1&mute=1" title="YouTube video player 1" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
</div>
<div class="mps-video">
<div class="mps-iframe-wrap">
<label for="3D_mountain_video_2">
Rimetea 3D map
</label>
<iframe id="3D_mountain_video_2" class="mps-iframe" width="560" height="315" src="https://www.youtube.com/embed/ZCaCEj1D7rA" title="YouTube video player 2" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
</div>
</div>
</div>
</article>
<div class="article-footer-container container">
<p class="color-primary">Don't forget to share this post!</p>
<div class="mps-social-grid-wrap">
<div class="mps-social-grid post">
<a
href="https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Falexaac.github.io%2Fmapstuff%2Fpost.html"
target="_blank" rel="noopener noreferrer"
class="mps-social"
aria-label="Facebook share link"
>
<img src="img/facebook.svg" alt="Facebook" />
</a>
<a
href="https://twitter.com/intent/tweet?source=https%3A%2F%2Falexaac.github.io%2Fmapstuff%2Fpost.html&text=Procedural GL JS:%20https%3A%2F%2Falexaac.github.io%2Fmapstuff%2Fpost.html"
target="_blank" rel="noopener noreferrer"
class="mps-social"
aria-label="Twitter share link"
>
<img src="img/twitter.svg" alt="Twitter" />
</a>
<a
href="https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Falexaac.github.io%2Fmapstuff%2Fpost.html"
target="_blank" rel="noopener noreferrer"
class="mps-social"
aria-label="Linkedin share link"
>
<img src="img/linkedin.svg" alt="Linkedin" />
</a>
</div>
</div>
</div>
<div class="article-container container">
<div class="mps-page-divider"></div>
</div>
<div class="article-footer-container flex container">
<div class="mps-author-info-flex">
<img class="mps-author-image post" src="https://mps-ph.s3.us-east-2.amazonaws.com/author.png" alt="Alexa Cristina">
<p>
<div class="article-footer-author-info">
<a href="#" aria-label="blank link 1">
<span class="title">Alexa Cristina</span>
</a>
<p>Data Wizard at AlexaC</p>
<div class="article-social-icon">
<a
href="https://twitter.com/maptheclouds"
target="_blank" rel="noopener noreferrer"
rel="noreferrer noopener"
class="mps-social"
aria-label="Twitter link author"
>
<img src="img/twitter.svg" alt="Twitter" />
</a>
</div>
</div>
</p>
</div>
</div>
<div class="page-navigation">
<div class="previous">
<p> Previous Post</p>
<a class="title" href="post.html">Loud Numbers Sonification Festival</a>
</div>
<div class="next grid-cell--col6 grid-cell--col12--tablet u-mt48--tablet">
<p class="text f12 is-txtBaseGrey">Next Post </p>
<a class="title" href="post.html">Roumanie - Carte Statistique Agricole - 1900</a>
</div>
</div>
<div class="article-container container">
<div class="mps-page-divider"></div>
</div>
<!-- Related Posts - smaller -->
<div class="section">
<div class="container">
<div class="mps-post-list">
<h2>Related Posts</h2>
<div role="list" class="mps-post-recent-grid">
<div role="listitem">
<a href="post.html" aria-label="post link 1" class="img-link mps-inline-block">
<div class="post-img-wrap pointer-events-none">
<div class="post-img-wrap-in">
<img src="https://mps-ph.s3.us-east-2.amazonaws.com/munich_leica.png" alt="Munich 3D Map from LiDAR" class="post-img">
</div>
</div>
</a>
<div class="mps-post-info-flex">
<span class="mps-post-category">LiDAR</span>
<a href="post.html" aria-label="post link 2" class="mps-inline-block mps-post-link">
<h3>Leica CityMapper-2</h3>
<p>
Munich - Leica CityMapper 2: DSM, 3D Mesh and GIS Layers.
</p>
</a>
<div class="mps-author-info-flex">
<img class="mps-author-image" src="https://mps-ph.s3.us-east-2.amazonaws.com/author.png" alt="Alexa Cristina">
<p>
<a href="#" aria-label="blank link 2">Alexa Cristina</a>
• <time datetime="2021-06-07T09:00:00+00:00" itemprop="datePublished">April 12, 2021</time> • 6 min read
</p>
</div>
</div>
</div>
<div role="listitem">
<a href="post.html" aria-label="post link 3" class="img-link mps-inline-block">
<div class="post-img-wrap pointer-events-none">
<div class="post-img-wrap-in">
<img src="https://mps-ph.s3.us-east-2.amazonaws.com/yose_li.png" alt="Yosemite Valley 3D Map from LiDAR" class="post-img">
</div>
</div>
</a>
<div class="mps-post-info-flex">
<span class="mps-post-category">LiDAR</span>
<a href="post.html" aria-label="post link 4" class="mps-inline-block mps-post-link">
<h3>Yosemite Climbing Walls</h3>
<p>
Yosemite climbing walls from LiDAR, using PDAL and ArcGIS.
</p>
</a>
<div class="mps-author-info-flex">
<img class="mps-author-image" src="https://mps-ph.s3.us-east-2.amazonaws.com/author.png" alt="Alexa Cristina">
<p>
<a href="#" aria-label="blank link 3">Alexa Cristina</a>
• <time datetime="2021-06-07T09:00:00+00:00" itemprop="datePublished">May 20, 2020</time> • 5 min read
</p>
</div>
</div>
</div>
<div role="listitem">
<a href="post.html" aria-label="post link 5" class="img-link mps-inline-block">
<div class="post-img-wrap pointer-events-none">
<div class="post-img-wrap-in">
<img src="https://mps-ph.s3.us-east-2.amazonaws.com/dublin.png" alt="Dublin 3D Map from LiDAR" class="post-img">
</div>
</div>
</a>
<div class="mps-post-info-flex">
<span class="mps-post-category">LiDAR</span>
<a href="post.html" aria-label="post link 6" class="mps-inline-block mps-post-link">
<h3>LiDAR Experiments – Dublin</h3>
<p>
Playing with LiDAR point clouds - PDAL, Entwine and QGIS.
</p>
</a>
<div class="mps-author-info-flex">
<img class="mps-author-image" src="https://mps-ph.s3.us-east-2.amazonaws.com/author.png" alt="Alexa Cristina">
<p>
<a href="#" aria-label="blank link 4">Alexa Cristina</a>
• <time datetime="2021-06-07T09:00:00+00:00" itemprop="datePublished">June 7, 2021</time> • 4 min read
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="section first">
<div class="container">
<div class="mps-wide">
<img src="img/gerard-lazaro-NHYCDJ0ovVg-unsplash.jpg" loading="lazy" alt="" class="mps-wide-bg">
<div class="mps-form-info-flex">
<h2 class="bold">Stay informed</h2>
<div class="color-neutral-200">
<p>Subscribe to be notified about new posts!</p>
</div>
<form id="email-form" name="email-form" data-name="Email Form" class="mps-wide-form">
<label for="email" class="mps-wide-label">Your Email</label>
<input type="email" class="mps-wide-input" maxlength="256" name="email" data-name="Email" placeholder="Your email" id="email" required="">
<br>
<input type="submit" value="Submit" data-wait="Please wait..." class="mps-wide-submit mps-btn mps-btn-primary">
</form>
</div>
</div>
</div>
</div>
</main>
<footer class="footer">
<div class="container">
<div class="footer-inner-flex">
<div class="footer-inner-flex-2">
<div>© MapStuff 2021</div>
<a href="#" aria-label="blank link 5" class="footer-link mps-link">Terms</a>
<a href="#" aria-label="blank link 6" class="footer-link mps-link">Privacy</a>
<a href="design_system.html" aria-label="Design link" class="footer-link mps-link"
>Design</a
>
</div>
<div class="mps-social-grid">
<a
href="https://www.github.com/mapstuff"
target="_blank" rel="noopener noreferrer"
class="mps-social"
>
<img src="img/github.svg" alt="GitHub" />
</a>
<a
href="https://www.facebook.com/mapstuff"
target="_blank" rel="noopener noreferrer"
class="mps-social"
>
<img src="img/facebook.svg" alt="Facebook" />
</a>
<a
href="https://twitter.com/mapstuff"
target="_blank" rel="noopener noreferrer"
class="mps-social"
>
<img src="img/twitter.svg" alt="Twitter" />
</a>
<a
href="https://www.linkedin.com/mapstuff"
target="_blank" rel="noopener noreferrer"
class="mps-social"
>
<img src="img/linkedin.svg" alt="Linkedin" />
</a>
</div>
</div>
</div>
</footer>
</div>
</body>
</html>