kmdreko's

A SIMPLE BLOG

A Simple Globe

SEPTEMBER 16, 2019 | JAVASCRIPT, PYTHON, GRAPHICS, GIS

I was recently inspired to explore WebGL for the first time; I've used OpenGL fairly extensively but I wanted to know how it all went together on the web. I decided to make a globe so I could also take the opportunity to learn some other stuff I've been interested in. This was a really fun project.

Anyways, here it is:

WebGL

The WebGL part was unfortunately pretty uneventful. As you would expect, it works pretty much identically to OpenGL (the good and the bad). It does have some limitations though (a few less functions, less control over sampling) but it certainly has all the stuff needed to make beautiful graphics.

I was pleasantly surprised to find out that the core rendering loop uses the function requestAnimationFrame() instead of glSwapBuffers(), it actually describes the intuitive meaning of the call. I of course still had trouble with matrices; damn column-major order kept messing me up.

Anyways, all that I'm doing here is drawing a bunch of line strips. I'm slightly annoyed that some platforms render the lines without antialiasing, but it still turns out ok I guess. I do the work of transforming the lattitude and longitude into xyz-points in the vertex shader as well as calculating all the view transforms. The depth effect is actually done in the fragment shader, and not with a transparent plane; I figure out the depth that the sphere edge would be and draw those fragments beyond that in a lighter color.

The Globe

I chose to draw a globe because, one: I'm not an artist, I needed something simple yet interesting, and two: I've been curious about working with GIS data just to see what was out there. I came across Natural Earth, which has publicly available datasets for maps. I ended up just using the physical land at the medium resolution, but they have all kinds of stuff for countries, states, cities, rivers, and more.

The Natural Earth datasets I tested with are shapefiles which are a common method for storing geographic information. However, I didn't want to use the files directly on the webpage because the data is spread across a few different files, some of that is metadata I didn't need, the data is in a precision I didn't need, and I wanted to put it in a format that would be easy for me to load.

Briefly, a shapefile has a set of "shapes" where each shape can have "parts" and each part will be a set of points. I ended up just flattening those parts and shoving them into file length-prefixed in binary. I did this in python by parsing the data with the pyshp library and creating the file with help from the array library. I then loaded up the file via fetch() and parsed it using typed arrays (first time doing that) and it all worked out well since that's how WebGL wanted the data anyway.

Controls

First of all, I apologize, I did not add touch support: the globe is static on a phone or tablet. However, with a mouse you can spin the globe around and scroll to zoom in and out.

It may interest you to know that I took care to ensure that the globe is only rendered when it needs to; if it isn't moving, then it doesn't redraw. Simple as that. I also designed the mouse dragging to only listen for move events if the canvas is being dragged. Just a little attention to performance can go a long way.