├── .gitignore ├── LICENSE ├── README.md ├── package-lock.json ├── package.json └── src ├── equirectangular.js ├── index.js ├── mercator.js ├── naturalEarth1.js └── orthographic.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | dst -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 carbonplan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | --- 24 | 25 | This license applies to d3-geo, verisons 3.0.1 and later 26 | 27 | --- 28 | 29 | Copyright 2010-2021 Mike Bostock 30 | 31 | Permission to use, copy, modify, and/or distribute this software for any purpose 32 | with or without fee is hereby granted, provided that the above copyright notice 33 | and this permission notice appear in all copies. 34 | 35 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 36 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 37 | FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 38 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 39 | OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 40 | TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 41 | THIS SOFTWARE. 42 | 43 | This license applies to GeographicLib, versions 1.12 and later. 44 | 45 | Copyright 2008-2012 Charles Karney 46 | 47 | Permission is hereby granted, free of charge, to any person obtaining a copy of 48 | this software and associated documentation files (the "Software"), to deal in 49 | the Software without restriction, including without limitation the rights to 50 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 51 | the Software, and to permit persons to whom the Software is furnished to do so, 52 | subject to the following conditions: 53 | 54 | The above copyright notice and this permission notice shall be included in all 55 | copies or substantial portions of the Software. 56 | 57 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 58 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 59 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 60 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 61 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 62 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 63 | 64 | --- 65 | 66 | This license applies to d3-geo-projection, verisons 4.0.0 and later 67 | 68 | --- 69 | 70 | Copyright 2013-2021 Mike Bostock 71 | 72 | Permission to use, copy, modify, and/or distribute this software for any purpose 73 | with or without fee is hereby granted, provided that the above copyright notice 74 | and this permission notice appear in all copies. 75 | 76 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 77 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 78 | FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 79 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 80 | OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 81 | TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 82 | THIS SOFTWARE. 83 | 84 | MIT License for https://github.com/scijs/integrate-adaptive-simpson 85 | 86 | The MIT License (MIT) 87 | 88 | Copyright 2015 Ricky Reusser 89 | 90 | Permission is hereby granted, free of charge, to any person obtaining a copy 91 | of this software and associated documentation files (the "Software"), to deal 92 | in the Software without restriction, including without limitation the rights 93 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 94 | copies of the Software, and to permit persons to whom the Software is 95 | furnished to do so, subject to the following conditions: 96 | 97 | The above copyright notice and this permission notice shall be included in 98 | all copies or substantial portions of the Software. 99 | 100 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 101 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 102 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 103 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 104 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 105 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 106 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | CarbonPlan monogram. 6 | 7 | 8 |

9 | 10 | # carbonplan / glsl-geo-projection 11 | 12 | **shader math for geographic projections** 13 | 14 | ![NPM Version](https://img.shields.io/npm/v/glsl-geo-projection) 15 | [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT) 16 | 17 | ## why 18 | 19 | The libraries [`d3-geo`](https://github.com/d3/d3-geo) and [`d3-geo-projection`](https://github.com/d3/d3-geo-projection) expose a wide diversity of [geographic map projections](https://en.wikipedia.org/wiki/Map_projection). While they are a perfect solution in JavaScript, for WebGL applications we need the same math available in GLSL. A specific use case is using the inverse equations to render raster data with arbitrary map projections, as shown in this [neat demo](http://bl.ocks.org/mbostock/raw/5446416/e46a4985e7a851f10bc231d1e78681c457d94aad/). This library exposes snippets of shader code with forward and inverse functions for a variety of projections. 20 | 21 | _Note: Work in progress. We're making our way through the projections, largely motivated by our needs to use them. If you want to add one, please open an [Issue](https://github.com/carbonplan/glsl-geo-projection/issues)._ 22 | 23 | ## use 24 | 25 | Install the package. 26 | 27 | ``` 28 | npm i glsl-geo-projection 29 | ``` 30 | 31 | Then import the functions you want and insert them into your shader. 32 | 33 | ```js 34 | import { orthographicInvert } from "glsl-geo-projection"; 35 | 36 | const frag = ` 37 | ${orthographicInvert} 38 | 39 | void main() 40 | { 41 | vec2 coordinates = orthographicInvert(x, y); 42 | // ... remaining shader code... 43 | } 44 | `; 45 | ``` 46 | 47 | Names are identical to those in `d3-geo` and `d3-geo-projection`. The naming convention is that each projection has a forward function with its name and an inverse function with its name followed by `Invert`. For example, `orthographic` and `orthographicInvert`, or `mercator` and `mercatorInvert`. 48 | 49 | ## license 50 | 51 | All the original code in this repository is [MIT](https://choosealicense.com/licenses/mit/)-licensed. The library is based closely on [d3-geo](https://github.com/d3/d3-geo/blob/main/LICENSE) and [d3-geo-projection](https://github.com/d3/d3-geo-projection/blob/main/LICENSE). We request that you please provide attribution if reusing any of our digital content (graphics, logo, copy, etc.). 52 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "glsl-geo-projection", 3 | "version": "1.1.1", 4 | "description": "shader math for geographic projections", 5 | "main": "dst/index.js", 6 | "module": "dst/index.esm.js", 7 | "scripts": { 8 | "build": "rimraf dst && microbundle --jsx React.createElement -f modern,es,cjs --jsxFragment React.Fragment", 9 | "watch": "microbundle watch src/index.js -o dst/index.js --no-compress --jsx React.createElement -f modern,es,cjs --jsxFragment React.Fragment", 10 | "format": "prettier --write README.md 'src/**/*.js'" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/carbonplan/glsl-geo-projection.git" 15 | }, 16 | "keywords": [ 17 | "glsl", 18 | "shader", 19 | "geo", 20 | "projection", 21 | "map", 22 | "webgl" 23 | ], 24 | "files": [ 25 | "dst" 26 | ], 27 | "author": "freeman-lab", 28 | "license": "MIT", 29 | "bugs": { 30 | "url": "https://github.com/carbonplan/glsl-geo-projection/issues" 31 | }, 32 | "homepage": "https://github.com/carbonplan/glsl-geo-projection#readme", 33 | "devDependencies": { 34 | "microbundle": "^0.13.0", 35 | "prettier": "2.2.1", 36 | "rimraf": "2.6.3" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/equirectangular.js: -------------------------------------------------------------------------------- 1 | export const equirectangular = ` 2 | vec2 equirectangular(float lon, float lat) 3 | { 4 | float lambda = radians(lon); 5 | float phi = radians(lat); 6 | return vec2(lambda, phi); 7 | } 8 | `; 9 | 10 | export const equirectangularInvert = ` 11 | vec2 equirectangularInvert(float x, float y) 12 | { 13 | return vec2(degrees(x), degrees(y)); 14 | } 15 | `; 16 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | export { naturalEarth1 } from "./naturalEarth1"; 2 | export { naturalEarth1Invert } from "./naturalEarth1"; 3 | export { orthographic } from "./orthographic"; 4 | export { orthographicInvert } from "./orthographic"; 5 | export { equirectangular } from "./equirectangular"; 6 | export { equirectangularInvert } from "./equirectangular"; 7 | export { mercator } from "./mercator"; 8 | export { mercatorInvert } from "./mercator"; 9 | -------------------------------------------------------------------------------- /src/mercator.js: -------------------------------------------------------------------------------- 1 | export const mercator = ` 2 | vec2 mercator(float lon, float lat) 3 | { 4 | float lambda = radians(lon); 5 | float phi = radians(lat); 6 | return vec2(lambda, log(tan((1.5707963267948966 + phi) / 2.0))); 7 | } 8 | `; 9 | 10 | export const mercatorInvert = ` 11 | vec2 mercatorInvert(float x, float y) 12 | { 13 | float lambda = x; 14 | float phi = 2.0 * atan(exp(y)) - 1.5707963267948966; 15 | return vec2(degrees(lambda), degrees(phi)); 16 | } 17 | `; 18 | -------------------------------------------------------------------------------- /src/naturalEarth1.js: -------------------------------------------------------------------------------- 1 | export const naturalEarth1 = ` 2 | vec2 naturalEarth1(float lon, float lat) 3 | { 4 | float lambda = radians(lon); 5 | float phi = radians(lat); 6 | float phi2 = phi * phi; 7 | float phi4 = phi2 * phi2; 8 | float x = lambda * (0.8707 - 0.131979 * phi2 + phi4 * (-0.013791 + phi4 * (0.003971 * phi2 - 0.001529 * phi4))); 9 | float y = phi * (1.007226 + phi2 * (0.015085 + phi4 * (-0.044475 + 0.028874 * phi2 - 0.005916 * phi4))); 10 | return vec2(x, y); 11 | } 12 | `; 13 | 14 | export const naturalEarth1Invert = ` 15 | vec2 naturalEarth1Invert(float x, float y) 16 | { 17 | float phi = y; 18 | float delta; 19 | float phi2 = phi * phi; 20 | float phi4 = phi2 * phi2; 21 | for (int i = 0; i < 25; i++) { 22 | phi2 = phi * phi; 23 | phi4 = phi2 * phi2; 24 | delta = (phi * (1.007226 + phi2 * (0.015085 + phi4 * (-0.044475 + 0.028874 * phi2 - 0.005916 * phi4))) - y) / (1.007226 + phi2 * (0.015085 * 3.0 + phi4 * (-0.044475 * 7.0 + 0.028874 * 9.0 * phi2 - 0.005916 * 11.0 * phi4))); 25 | phi = phi - delta; 26 | if (abs(delta) < 1e-6) { 27 | break; 28 | } 29 | } 30 | phi2 = phi * phi; 31 | float lambda = x / (0.8707 + phi2 * (-0.131979 + phi2 * (-0.013791 + phi2 * phi2 * phi2 * (0.003971 - 0.001529 * phi2)))); 32 | return vec2(degrees(lambda), degrees(phi)); 33 | } 34 | `; 35 | -------------------------------------------------------------------------------- /src/orthographic.js: -------------------------------------------------------------------------------- 1 | export const orthographic = ` 2 | vec2 orthographic(float lon, float lat) 3 | { 4 | float lambda = radians(lon); 5 | float phi = radians(lat); 6 | return vec2(cos(phi) * sin(lambda), sin(phi)); 7 | } 8 | `; 9 | 10 | export const orthographicInvert = ` 11 | vec2 orthographicInvert(float x, float y) 12 | { 13 | float z = sqrt(x * x + y * y); 14 | float c = asin(z); 15 | float sc = sin(c); 16 | float cc = cos(c); 17 | float lambda = atan(x * sc, z * cc); 18 | float phi = asin(y * sc / z); 19 | return vec2(degrees(lambda), degrees(phi)); 20 | } 21 | `; 22 | --------------------------------------------------------------------------------