WebGL is implemented by GPUs (graphics processors) in a highly parallel system. It is programmed initially in Javascipt, based on an HTML5 canvas element. But it requires "shaders"; fragments of code to be distributed with data onto those processors. I think WebGL handles all this very well, but it can get complicated. Here is a TOC for this page:
- File Structure
- User Files
- Objects and types
- Data Properties
- Colors and Appearance
- Active features - tags
- Triangle nodes and edges
- Multiple Data
- Global Parameters
- Gadget control and operations
- Altering and entering data
- Data and Code
- Index of keywords
BackgroundThe MoyGL system seeks to automate all this on a program called MoyGLV2.js. All the user has to do is supply problem data and some control parameters on a user file. I described early versions of the system here, early 2014 and here (simplified). Three years later, I described an update here, which I called V2, and gave a number of applications.
<div id="PxBody" /></div>
The ID is recognized by MoyGL, which builds a tree of HTML elements based on it. Then there are the
- script calls. Here is an example from a recent post:
The first is a small library file, which I use very little so far, but expect to use more. I'll write more about it. The second is data for adding a map, if wanted. The third is the user file for the app (see next section), and that is what I will expand on here. The fourth is the executable JS, which must therefore be placed last. And that's it.
p is the handle of a set of objects, corresponding to WebGL objects, and U is an object defining some global variables. The body of the function defines user objects and properties.
Objects and TypesDefining an object, say Mesh (which I'll use as an arbitrary user object name), is simple:
Typical objects might be a triangle mesh, a set of points for nodes, or a line object for a map. You will be able to see the objects you declare in a checkbox list top right. You can toggle them on/off with the boxes.
Then you can add object properties, which are mainly data. The first essential attribute is a type, corresponding to WebGL types. The syntax is:
p.Mesh.type=U.TRIANGLES // note the U.
The basic types are POINTS, LINES and TRIANGLES. The type determines how the node data that you supply will be connected. Other types, which are alternative ways of linking the data, are LINE_STRIP, TRIANGLE_STRIP, and more rarely, LINE_LOOP and TRIANGLE_FAN.
I have added two extra types:
- U.MAP, which crates a LINE_STRIP object from a file called "Map.js" (see above). With this type, you don't need to supply extra data (but you can).
- U.GRID - see next section. It makes a triangle type with a lat/lon grid.
Objects have properties, which can be prescribed or inherited. Prescribed have priority; defaults are inherited. There is an explicit inheritance
But with the multi and edge facilities below, I don't use this now.
You may see reference to an object discM. This is a disc placed across the mid-plane of a sphere (if U.sphere>0, see below) to make it opaque for maps etc. You can make it disappear with a checkbox.
Data PropertiesThe standard data supplied are:
Between the brackets (JS for arrays) are a string of floats separated by commas. The numbers are generally the cartesian x,y,z components of successive nodes. But if .sphere is enabled, as it is by default (see below), you can supply lat/lon in degrees, or xyz on the unit sphere.
These are needed to determine colors for color shading (triangle elements). The values, one float per node, are again a flat comma-separated list. They will be converted into integer pointers into the palette, usually 256 colors. A color key will be generated. Alternatively you can give the integers directly:
Monochrome points and lines do not generally need vals or cols specified.
This set of integer pointers into nodes says how they will be connected, and depends on type. Remember, JS always numbers from zero. Sometimes this can be omitted, as with POINTs (no connections) or LINE_STRIP, where if no links are specified, it will just connect in the given order (use NaN pairs to break). But for TRIANGLES, give pointers in groups of 3, and generally for LINES, in pairs. For more complex types like TRIANGLE_STRIP, follow the WebGL sequence.
Even for POINTS, you might want to give links to specify a subset. I should note here that where two objects have common data, you don't have to supply twice. You can just write a.nodes=b.nodes, if b.nodes has been supplied. in JS, a.nodes is then a pointer to b.nodes, not separately stored data. You need to be aware of this if b.nodes data is later changed, but it probably won't be. It is for such reassigned data that selecting a subset by pointers can be useful.
- GRID type
As mentioned above, you can declare this when you want to shade a lat/lon grid with square cells. You supply only .vals (or .cols); the system will work out the nodes and links, you can have a wide variety of sizes, from 1/4° up, as long as it is a divisor of 180. The order is longitude varying first, then latitude. In latitude, with 5x5° say, you could give 35, 36 or 37 levels. 36 would be interpreted as mid values (-87.5, -82,5 etc), 37 as bottom corner (-90, -85 etc), and 35 the same, but omitting the poles.
With GRID, you can't ask for edges or nodes to be marked, though you can make an extra object to do it.
Colors and appearanceThe basic color palette statement is
where the palette is a set of typically 256 RGB triples, in the GL style, ie each between 0 (no color) and 1 (full). I described here an abbreviated form for continuous color shading. There are defaults for triangles (rainbow) and points/lines (grey). For monochrome the palette can be just one RGB triple, and no vals or cols are needed. Otherwise the palette is used by the .cols property (pointers into palette), which may be deribed from .vals.
Each triangle is shaded RGB interpolation from the colors assigned to the corner nodes. If you want a node to have different colors in different triangles, give multiple copies of the coords, with corresponding pointers (and vals/cols). The colors of the first shaded object will be used to make the color key, if you have supplied .vals. You can comtrol the heading by
The colors are made from .vals, if supplied, by a non-linear function from all reals to the range (0,1), which is then scaled to the palette range. The function is usually tanh((v-m)/s), where v is value, m is mean, and s is standard deviation. The sd has no statistical intent; it is just a scaling. One effect of this is that the color mapping will vary with every plot. You might want to make it consistent. There is an object property:
where m, s are floats; if this is supplied, it will take precedence. You can make this multi-valued.
You can't control linewidth (a WebGL issue) but you can control point size p.Mesh.size=..
Default is 3; this is point size in pixels. You can attach this to a triangle object, and if you ask for nodes (see .edge below), that will be applied.
You can control headings that are displayed. This involves adding properties to U:
The long heading appears top left; the short is only useful with Multiple Data, when it gives the headings for the radio button table.
There is a parameter .alt which you can set to raise one object above others; it is 1 for the surface (r=1). The object parameter .alpha, between 0 and 1, governs transparency (1 is full color, 0 fully transparent.)
Active features - tagsI'll describe below how you can rotate the globe and zoom. But if you click at any point on it, you'll see a number pop up under the object list. That has the .vals value for the triangle object, if this has been supplied. Usually there is only one such object. The number is the .val at the nearest node.
But you can improve on this by supplying a list of tags (eg place names). There are just a vector of strings, one for each node. They will be displayed with the data.
Triangle nodes and edgesI often want to show the edge lines and nodes for each triangle. For that you need a new object (different type). However, the system will make those automatically if you set
(for triangles). The values here are 0 default, 1 add points only, 2 add edge lines only, and 3 add both. You'll see the new objects in the checkbox list, as Mesh_P and Mesh_L respectively. You can toggle them on/off. The _P object inherits size and tag from its parent Mesh.
Multiple DataThis allows you to combine several data sets with common features to give alternative displays. You can do it by taking any data item, such as .vals or .palette, and offering an array of values. Vectors can be nested, eg
You will usually have some properties multiple and some not. It is best to ensure that any multiple vectors have the same number of components, else confusion. A table of radio buttons with labels will appear lower right. The buttons let you choose which group to show. It is best to use the U.short parameter above to label these, also supplying an array of strings.
Global ParametersI have been introducing the U object, which supplies data (type numbers) and to which you can attach more. Some useful ones are:
U.sphere = -1|0|1|2
This determines what assumptions will be made about whether you are using a unit sphere. 0 makes no assumption; 1, the default, means you can supply lat/lon which will be mapped to the sphere, and also makes sense of the clicking to show values qv
Value 2 is more ambitious, and ensures that triangles and lines will follow surface curves, if they span more that 5° for lines or 10 for triangles. That is, the sections get divided, with extra nodes projected onto the sphere. These extras don't count for edge showing or value clicking. It involves quite a lot of extra calculation, and tend to make bits of lines disappear, so use only when needed.
Value -1 has the functionality of setting U.flat=1 in the previous account. It maps the sphere onto a flat lat/lon plot (in degrees), still using WebGL shading, but you can't rotate any more, though you can zoom. You can still enter coords as lat/lon or 3D cartesian, and set .edge so show lines and points.
Gadget control and operationsI have described these many times. The Earth is a trackball, drag with the mouse. The Orient button rotates the facing disc so that the longitude through the center is vertical. Dragging the right button vertically zooms or shrinks. I have explained the radio buttons and checkboxes above.
Even if you aren't using sphere, the dragging and zooming is as if you were dragging a surrounding unit sphere with fixed centre.
There is an inheritance property for objects:
Properties from Mesh0 then become defaults for Mesh. Mesh0 needs to come first. The main use for this was creating line and point objects for triangle edges, but that inheritance is now automatic with .edge.
governs whether p.Mesh is drawn - it is what the checkboxes toggle. Mostly used to make objects initially invisible (=0).
Altering and entering dataYou can modify/enter data with the program running. Using the boxes top right, there are two ways:
- You can select a property in the top box, and enter its value as if the RHS of something in the user file, in the text box below. That is, just a comma separated list of reals or strings. If you refer to a multi-value property, it will go into the level curently selected with rdio buttons.
- You can also enter an entire line that could have gone into the user file (with p. and U., but don't define new objects). Or even multiple items separated by ;.
ExamplesI have posted many examples of use of this facility during its development. In roughly reverse order (newest first)
- Global average, integration and webgl. This used most of the features of that latest version. I'll show it again below for reference.
- Temperature residuals and coverage uncertainty.
- Making an even SST mesh on the globe.
- Moyhu WebGL interactive graphics facility, V2. This describes my beta version of a few weeks ago, with code examples. I think most code will still work, though U.flat=1 has been replaced with U.sphere=-1.
- Playing with palettes in WebGL earth plotting. The first use of multiple data.
- Spatial distribution of flutter in GHCN adjustments
- Spherical Harmonics Displayed I mentioned this above as a case where the display is not of a sphere surface, although the SH surfaces are within a unit sphere.
- and many other examples uusing V1, including the following maintained pages:
- WebGL map of past GHCN/SST station temperatures. This shows monthly TempLS temperature residuals. It's the best place for detailed recent information.
- WebGL map of GHCN/SST station temperature trends
- HiRes NOAA OI SST with WebGL and Movie This actually isn't done with the system, but is the most detailed WebGL (1/4°) that I have done.
- WebGL code - shaded grids and maps. This was one of my posts from 3 years ago on V1. It had an early textbox input.
- Generic code for WebGL Earth data V1 described, with code
- Using WebGL for Earth data mapping. Setting out the ideas, and some description of WebGL.
Ade here is an even simpler user file, just using the GRID type, with vals being the data for shading listed from (-90,-180), longitude first.
And here is the actual output from the picwts.js file, same as here: