Gleo: Reinventing WebGL maps
This is a modal window.
The media could not be loaded, either because the server or network failed or because the format is not supported.
Formal Metadata
Title |
| |
Title of Series | ||
Number of Parts | 351 | |
Author | ||
License | CC Attribution 3.0 Unported: You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal purpose as long as the work is attributed to the author in the manner specified by the author or licensor. | |
Identifiers | 10.5446/69111 (DOI) | |
Publisher | ||
Release Date | ||
Language | ||
Production Year | 2022 |
Content Metadata
Subject Area | ||
Genre | ||
Abstract |
| |
Keywords |
00:00
Software maintenanceArchitectureLimit (category theory)Hacker (term)Point (geometry)Element (mathematics)Web browserScale (map)Absolute valueData structureRun time (program lifecycle phase)Array data structureSymbol tableLine (geometry)CircleShader <Informatik>Computer-generated imageryCurvatureSurfaceVideo projectorScripting languageComputer reservations systemDiagonalMaß <Mathematik>Default (computer science)Object (grammar)Pointer (computer programming)Event horizonObject-oriented programmingLogarithmDemo (music)Inheritance (object-oriented programming)Utility softwareGeometryConstructor (object-oriented programming)LogicElectronic visual displayDegree (graph theory)Vertical directionUnified threat managementCalculationDistanceBoundary value problemInfinityConstraint (mathematics)AreaFunction (mathematics)Proxy serverService (economics)Compact spaceRectangleGUI widgetInformationTessellationLink (knot theory)Attribute grammarCoordinate systemFloating pointLevel (video gaming)Projective planeZoom lensState of matterDifferent (Kate Ryan album)Entire functionTessellationPointer (computer programming)Library (computing)Computer architecturePoint (geometry)Event horizonDivisorPosition operatorWordUniverse (mathematics)PixelAnalytic continuationSlide ruleArray data structureSymbol tableSocial classCodeDiagramGenetic programmingGeometryTexture mappingFunctional (mathematics)Object (grammar)Standard deviationPolygonGraph coloringTerm (mathematics)Flow separationShader <Informatik>Inheritance (object-oriented programming)AlgorithmDefault (computer science)Execution unitComputer reservations systemOpen setSet (mathematics)BitNumberOpen sourceWeb browserScaling (geometry)Web 2.0Software frameworkLimit (category theory)TesselationMultiplication signData structureDemo (music)File viewerModule (mathematics)NP-hardBuffer solutionComputer scienceSemiconductor memoryComputer configurationTraverse (surveying)RotationLine (geometry)Insertion lossThread (computing)SpreadsheetBoundary value problemView (database)String (computer science)Medical imagingRaster graphicsGroup actionPolyederVideo projectorLatent heatSource codeImage resolutionFilm editingGame controllerGeneric programmingLaptopSurfaceMereologyBound stateImplementationRow (database)Coordinate systemMultilaterationComputer programmingSoftware bugElektronisches MarketingMetreCollisionWeightBootingSinc functionDampingCodeDemosceneEquivalence relationSoftware maintenanceCuboidComplex (psychology)Plug-in (computing)Ring (mathematics)System callCASE <Informatik>1 (number)ReliefSoftwareQuantum stateStorage area networkAttribute grammarWindowService (economics)Type theoryAlgorithmic information theoryComputer animation
Transcript: English(auto-generated)
00:00
So hi, I am Ivan and I am reinventing WebGL maps, which is kind of a big thing to do, I guess. Tiny, tiny, tiny bit of me, I have been a long timer, I'm a long timer in FOSS and FOSS4G and OpenStreetMap. I became a legal maintainer, I started doing some WebGL things
00:20
and then four years ago I kind of burnt out because of things that I was asked and I also, because I implemented a WebGL leaflet plugin, a set of WebGL leaflet plugins, I tried to implement the same thing in open layers and I failed miserably. So that kind of hit me a bit
00:40
and that's why I sort of started doing this. I haven't seen a lot of, I know about the JavaScript state of the art when it comes to map viewers. I know most of this, I have at least checked the documentation for them, I have attended the talks on how they work internally.
01:02
I have strong opinions on each of them. In leaflet we have reached completely the limits of what HTML can do. We have squeezed every inch of features that can port, that a browser has that we can use on a map. Most of REST, I haven't really checked them in depth
01:24
or I cannot understand their architecture. This is horrible. I don't think that open source of work can really be open source if you cannot open it up and see how it works. And this is the case, especially with Mapbox GL and Map delivery GL. I don't know what a bucket is.
01:40
I want to know what a bucket is in Map delivery and I don't know it and it takes a lot of time to learn how it works. I don't want to learn CSUM and that GL, I don't want to use it because apparently it needs a back on the background so it's not really a map rendering library, it's a map data resolution library on top which also uses some data structures that I don't particularly like.
02:02
We have a couple of bugs in leaflet that also appear from time to time and as I said, we cannot fix this in leaflet. There's no way to fix this in HTML so this is why people go to all the libraries. I hate WebGL profoundly. It's not WebGL, it's OpenGL for JavaScript. I hate it.
02:20
You cannot debug it, you cannot set a break point. You don't have record structures in JavaScript so the thing that works perfectly for OpenGL which is a C struct, you don't have in JavaScript so you have to create these complicated data structures and data workflows to make it work and floating point position I hate absolutely. So I want like a unicorn in the sky.
02:43
I want to do something that doesn't use the word layer, more on this later. I want something with the leaflet API because everybody loves the leaflet API and being able to extend it. I want to handle projections as open layer does because that's lovely. I want to do the performance that map lever has because that's lovely and I want to not burn out while doing this
03:01
so more on that later. I hate layers. I absolutely hate layers. Depending on who you ask and what you're doing, a layer is something different and I can and I have layered the layer for layer for layer for layer for layer for layer. So I will not ever use the word layer.
03:20
I started by renaming everything and by creating my concepts from scratch. I don't have layers. I have symbols. I have cartographic symbols, not features, symbols. A feature might be more than one symbol. Each kind of symbol is going to be drawn in acetate. The acetate is going to handle
03:40
the WebGL data structures and once I have all the acetates, I will flatten them all together in a platina. What's a platina? A platina is a glass surface of a photocopier or this old-timey slide projector. I'm old enough to have seen this in university within my classes. Okay, you can call me old, it's fine,
04:01
but that's the concepts I'm going to use. I render things on different acetates and when I'm doing the composition, it's being done in a platina. That also has some implications on how the map state is handled. So one of my design goals was to make an API which looks like leaflet and this is minimal.
04:21
This is how it should look like. I don't have to worry about the latitude, longitude thing because it's implicit in the coordinate array. I am doing some fancy things such as the span instead of the scale. I am running away from zoom level. I don't use the term zoom level whatsoever
04:41
and when it comes to tile layers, I want to have some same defaults for the default or the de facto standard of the Mercado tile pyramid. So this is nice because it looks like leaflet so people should like things that look like leaflet or don't go away very much from what leaflet does.
05:03
Also, I am an old guy who likes object oriented programming. I depend on making UML diagrams for my code. It helps me a lot and it helps me to check that what I'm doing has a sane architecture. So I'm doing this. I am encapsulating WebGL shaders in the acetates
05:23
and I'm deduplicating as much code as possible. I don't like other WebGL frameworks that do duplication of some names internally so I have worked hard to abstract that and to hide that complexity. A insanely cool thing that I have been doing with GLAO
05:41
is symbol inheritance. In the same way that one can do a leaflet plug-in to take a leaflet layer and create a different, more complex or more restricted leaflet layer, I can take a symbol and extend it or I can take an acetate, extend it and create it in rendering which is absolutely awesome. This has a small counterpart or downside,
06:06
small downside which is a very high coupling between the symbols and the acetates. My computer science teachers would kill me for making something with this kind of coupling but it cannot be avoided unfortunately. The way this works is that a symbol
06:22
is a JavaScript object that is agnostic from the GPU memory. An acetate handles all the GPU memory. This way I can instantiate a symbol, get it out of the map, get it in a different map, attach some events, get it out of the map again, attach some more events and then attach it
06:42
to a different map and it will work. Also because it's object oriented, all symbols are DOM event targets. Since we are now in 2022, we can have some browser-wide, some event handlers and event targets that work in all browsers which is nice.
07:01
This is more than JavaScript but for a thing that is not usually targeted with more than JavaScript so to speak. So I can have a sprite which is the equivalent of a marker and attach click events and pointer events and it works out of the box. It's nice, it's so cool.
07:21
Now since we have some problems with the live demos at this event because of how the slides are handled, if you are on Venueless and if you have your laptop ready, you can check that URL and go into your laptop and check how this works. This is a small example and you can check the source code because it's really readable
07:41
for this example. I'm creating a few markers, the one from Madrid from him and Buenos Aires. I'm attaching some events, some click and pointer events to it and then I'm spawning, I don't know if it's 10,000 sprites and each of those 10,000 sprites has an event handler attached to it and it's absolutely wonderful.
08:01
When you're doing JavaScript and try to do this thing, I haven't seen a clean way of doing it with all the libraries. You have to do some kind of generic event handler for all the symbols of the same kind and then filter, et cetera. With this way, I can just pick out some of my symbols
08:20
and attach specific event handlers to them which is nice and I like it. Those are the most you can just, I have been leaving this for a minute. I hope you have taken note of it and are trying it out. One of the other things I work very hard is to get rid of the need of Web Mercator. Glo is agnostic when it comes to coordinate systems.
08:44
So whenever you are going to do a symbol, you need to provide that symbol with a geometry. This is a geometry more like, very like, very much like the simple geometries OTC specification. So the points, lines and polygons and so on. But you can have some short hands
09:04
because hey, this is object in programming. I can subclass some kind of geometry and do something specific. If you don't provide a standard, it will, if you don't provide a CRS, it will take some default that you can also configure.
09:21
One of the big problems when you are dealing with geometries and CRS is the anti-meridian. I am handling this by not assuming that a geometry will be fitting within the bounds of what you believe that the CRS. In Glo, geometries can hang out. If you need to forget that logic
09:42
and provide the fast path, you can do that. But usually what you will want to do is provide these things and let Glo do all the messing around. So for example, if we have some geometry that is going to wrap from 170 longitude to minus 170 longitude, Glo internally will wrap the geometry around
10:01
and change that from 170 to 190. And then that geometry will be drawn twice, once with a zero offset and one with a minus 36 offset or whatever offset it needs to be done, et cetera, et cetera. This works, it's magic. It's kind of out of the ordinary or out of what we are used to doing GIS,
10:22
but it works for rendering. So I can change the entire CRS of the entire map. This is the leveraging approach, the approach library, which all love, we all love. And that's how I can just define a new projection and make the map use that projection.
10:43
Glo will use a scale in CRS units per pixel. So whenever you're using this coding net system, you can think of quote meters quote per pixel. That's the scale factor I'm using here. So if you have your laptop ready and you are checking the demos,
11:01
you will be checking this insanely cool demo, which is changing the entire map projection on the fly with several different more or less common projections. This is absolutely cool. Takes like half a second to re-project everything and redraw it.
11:20
Since I'm doing some magic with the WebGL data structures, what I'm doing is for every symbol, I will have a coordinate attribute, but the rest of the data for that symbol will not get changed if it's not needed. So this is providing the least amount of updates to the WebGL data structures needed for this. You don't need to change the color of a polygon
11:42
whenever you are re-projecting that polygon. So I don't do it, that's it. Do check this demo because it's absolutely nice to, if you have worked with projections before in web maps, you will love how this works. Now I made this slide mainly for Luis de Sousa, who is going to, is there
12:01
and is going to give a lightning talk on this subject. Since I am doing a web map, I realized that I need a bit more data for the projection than just the name or just the project string. I need some way to know how it tessellates. Does it tessellates horizontally like the default web market though? Does it tessellate vertical like Traverse market though?
12:23
Does it tessellate all the way? Does it tessellate triangularly maybe? Also, I need some data to be able to operate with the OGC APIs because there's no one standard way of referring to a coordinate system
12:40
whenever you're dealing with OGC services, and fortunately, there's no automatable way of doing this cleanly. And if you have worked ever with WMS 1.3, you know why I have a flip access option there, unfortunately. Also, something that is missing from the coordinate system definitions is some informative values for the user experience.
13:02
If I don't provide these values, I will allow users to just zoom all the way out and lose control of what they were looking at. And you can also zoom in all the way to the micrometer scale and the user will also be lost. So there is a need for some informative,
13:21
non-strict limits on what part of the map the user should be allowed to look at by default. I am interested to know what is also missing from this. For example, one of the things I want to do is do a warmerdome butterfly projection.
13:41
And for that kind of polyhedral projection, I need to cut down the data so there's these big splits whenever the butterfly is opening and one of the polyhedra is being flattened. So somehow, I would need to have the boundary for those cuts in some of the projection to be able to cut the geometries accordingly.
14:02
So some food for thought there. One of the things I haven't worked hard to get and I am extremely happy about is that you can extend the symbols on the acetates. I kid you not. I have a normal marker symbol, the sprite, which is an image.
14:21
And this is half the code you need to make a tinted sprite, which is the same thing but whenever you're doing a sprite, whenever you are instantiating a tinted sprite, you have to provide a tint color and whenever you're rendering it, the tint color will multiply the color of the image. And I kid the complete implementation of this
14:42
is like 100 lines of code and it is readable. People can design and implement their own symbols. It is awesome. You have to check the code for this. I really, really, really want to bring together people from the shader and demo scene into GIS.
15:02
Whenever you talk to somebody out of GIS about coordinates, they go crazy. Whenever you talk to GIS people about shaders, they don't understand them. We need to bring them together. I hope I will do this at least a tiny bit. Something that I implemented in the last few weeks is vector stylesheets for MapboxGL style vector tiles.
15:26
Everybody expects it to happen. It is absolutely horrible to implement but I have been able to provide a kind of a compact way to load these base map stylesheets.
15:40
Also, since in GLEO, every symbol is a JavaScript object, I can do the leaflet thing for the GeoJSON loader which is on its feature. Whenever a tile is being loaded and it has been converted to symbols, I can run a callback, attach whatever kind of events I want or filter them or do something to the symbols, change them before they're rendered
16:02
and I can do that for each tile, no problem. Also, all the symbols are interactive and we'll be able to respond to pointer events. If you have the demos, you will be able to check out this one which is still a bit baggy, unfortunately
16:20
but it does work on several of MapTiler stylesheets and some other vendors but hey, MapTiler is a sponsor of Fosuji so try this out with the MapTiler styles. It does work, I'm happy. I have some problems deallocating symbols, unfortunately but it works and people expect
16:40
this kind of thing to happen. I don't have text rendering yet because text rendering collisions is hard, especially when you're doing it with continuous levels but it's getting there and I was really happy to implement this in a few weeks. A couple of words about floating point.
17:02
WebGL does 24-bit floating point position. We are used to handle in JavaScript 64-bits or 32 whenever we're working with typed arrays and people get really confused and surprised whenever they're going to look at some data point very far away from the original coordinates
17:22
and things get kind of jaggy on the edges and whenever you look very closely to it, there's like an invisible grid which is snapping all the points and that's where this, that's why this happens because the numbers are getting clamped into 24-bit floating point numbers.
17:44
There's two ways of handling this. One way is the mapbox, map-liver way which is you don't handle absolute coordinates to a CRS. You only handle coordinates relative to a tile but because I want to get away from Webmercato, I cannot depend on that specific pyramid
18:02
so I have to do it the other way which is creating interim CRSs. Since I have the ability to re-project all the data, I also have the ability to offset all the data. So by offsetting the data whenever I'm moving far away from the original coordinates,
18:20
I will lower the numbers of all the coordinates in my WebGL buffers and everything will fit and no artifacts will be shown. This is completely invisible but it's a lot of hard work to get this architecture in place. A contentious point that I think or I think it will be a contentious point is that I am licensing this with a GPL library.
18:43
Why? Because I want to avoid a schism like the mapbox-gl-map-liver. I think that GPL was the way that should have saved us from that schism before. We are kind of scared in the JavaScript world about GPL but I think we shouldn't be
19:00
because we have JavaScript modules now and with JavaScript modules, you just publish the source code so you don't have to compile it so the GPL doesn't really apply to whatever you're not compiling. This should work. I want it to work so I hope it works. Some very quick, more features that I don't really have time for showing up.
19:22
The tiles have a sliding window algorithm. I'm dumping tile data into textures so I can guarantee that complex shaders will always be able to query neighboring pixels whenever I'm doing some elevation data. I forgot the name of the thing.
19:45
The... And that's my time. So I do conformal rasters. I do, whenever I'm changing the center of the map, there's a smooth transition because the platina has a instant view of the map state but the map doesn't
20:00
so the map handles the animations of the platina. The platina can work as a leaflet renderer. I have jaw rotation which is the rotating the map. I do have spreadsheet support for the sprites built in and I have, it's very similar to the vector style sheets, I have symbolizer for the geoJSON. So you open a geoJSON, you give it a function
20:22
that returns symbol and it works. I have a lot of work to do. Most importantly, web workers. I'm doing all the work in the main thread and it sucks on performance when I'm doing vector tiles. It's not good. But that's all the time I have. Here's the code for my little thing.
20:42
Thank you for being here. Thank you very much.