Visual effects with fragment shaders
Last active
April 18, 2017 16:08
Tangram Firefly Map
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<head> | |
<meta charset="utf-8"> | |
<!-- leaflet --> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.0.0-rc.1/leaflet.js"></script> | |
<!-- Main tangram library --> | |
<script src="https://mapzen.com/tangram/tangram.min.js"></script> | |
<script src="https://cdn.jsdelivr.net/quicksettings/latest/quicksettings.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script> | |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.0.0-rc.1/leaflet.css" /> | |
<style> | |
body { | |
margin:0; | |
position:fixed; | |
top:0; | |
right:0; | |
bottom:0; | |
left:0; | |
} | |
#map { | |
height: 100%; | |
width: 100%; | |
position: absolute; | |
z-index: 0; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="map"></div> | |
<script> | |
var mapContainer = document.querySelector('#map'); | |
var map = L.map('map'); | |
map.setView([36.2453813,-100.7281112], 5); | |
var layer = Tangram.leafletLayer({ | |
scene: 'scene.yaml', | |
attribution: '<a href="https://mapzen.com/tangram" target="_blank">Tangram</a> | © OSM contributors | <a href="https://mapzen.com/" target="_blank">Mapzen</a>' | |
}); | |
layer.addTo(map); | |
var scene = layer.scene; | |
var requestRedraw = function() { | |
window.requestAnimationFrame(function() { | |
scene.requestRedraw(); | |
}); | |
} | |
// Interaction callbacks | |
layer.setSelectionEvents({ | |
hover: function(selection) { | |
if (selection.pixel && selection.leaflet_event.target) { | |
var node = selection.leaflet_event.target._container; | |
var x = selection.pixel.x; | |
var y = selection.pixel.y; | |
scene.styles.citydot.shaders.uniforms.u_mouse_x = x; | |
scene.styles.citydot.shaders.uniforms.u_mouse_y = y; | |
requestRedraw(); | |
} | |
} | |
}); | |
// Scene warnings & errors. | |
scene.subscribe({ | |
error: function (e) { | |
console.log('scene error:', e); | |
}, | |
warning: function (e) { | |
console.log('scene warning:', e); | |
}, | |
load: function () { | |
console.log('scene load complete'); | |
} | |
}); | |
</script> | |
</body> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
cameras: | |
camera1: | |
type: perspective | |
lights: | |
global_light: | |
visible: true | |
type: ambient | |
ambient: 1.0 | |
diffuse: 1.0 | |
specular: 1.0 | |
sources: | |
stamen-terrain: | |
type: Raster | |
url: http://a.tile.stamen.com/terrain-background/{z}/{x}/{y}.jpg | |
osm: | |
type: TopoJSON | |
url: https://vector.mapzen.com/osm/all/{z}/{x}/{y}.topojson?api_key=vector-tiles-jvpqPNW | |
countryPolygons: | |
type: GeoJSON | |
url: world.json | |
import: | |
- https://tangrams.github.io/blocks/color/tools-full.yaml | |
styles: | |
citydot: | |
base: points | |
blend: inlay | |
shaders: | |
uniforms: | |
u_mouse_x: 0 | |
u_mouse_y: 0 | |
blocks: | |
color: | | |
// We are going to use texture coordinates to color our dots. | |
// What does texcoord look like? | |
// | |
// (0,1)----(1,1) | |
// |--------| | |
// |--------| | |
// |--------| | |
// (0,0)----(1,0) | |
// | |
// v_texcoord is varying set by tangram. | |
// see https://github.com/tangrams/tangram/blob/master/src/styles/points/points_fragment.glsl | |
// Some coordinate checking debug code. | |
// vec2 uv = v_texcoord; | |
// if(uv.x > 0.9 && uv.y > 0.9) { | |
// color.r = 1.0; | |
// color.g = 1.0; | |
// color.b = 1.0; | |
// } | |
// Check if the mouse if near this fragment | |
// | |
// We need to convert mouse position from css pixels to device pixels | |
// for the calculations to work on 'retina' screens as gl_FragCoord is in | |
// device pixels. | |
vec2 mousePos = vec2(u_mouse_x, u_mouse_y) / u_resolution * u_device_pixel_ratio; | |
mousePos.y = 1. - mousePos.y; | |
vec2 fragmentPos = gl_FragCoord.xy / u_resolution; | |
float mouseDistance = abs(distance(mousePos, fragmentPos)); | |
float pulse = 0.0; | |
if (mouseDistance < 0.045) { | |
color.rgb = vec3(1.00,0.39,0.28); // orange | |
pulse = sin(u_time * 1.45) * 0.5 + 0.5; | |
pulse = clamp(pulse, 0., 0.3); | |
} | |
// Distance to center of point. | |
vec2 uvd = v_texcoord * 2. - 1.; | |
float point_dist = length(uvd); | |
float centerRingRadius = 0.15; | |
// Set color and alpha | |
if (point_dist < centerRingRadius - (pulse * .1)) { | |
color.rgba = vec4(1., 1., 1., 1.); | |
} else { | |
color.a = (1. - point_dist - pulse); | |
} | |
terrain: | |
animated: true | |
base: raster | |
shaders: | |
blocks: | |
color: | | |
// Desaturate | |
float luma = dot(color.rgb, vec3(0.299, 0.587, 0.114)); | |
color.rgb = mix(color.rgb, vec3(luma), vec3(0.97)); | |
// Adjust brightness and contrast. | |
float contrast = 1.8; | |
//float brightness = -0.4 * luma; | |
float brightness = -0.8 * luma; | |
color.rgb = contrast * (color.rgb - .5) + .5 + brightness; | |
polygonOverlay: | |
base: polygons | |
blend: inlay | |
global: | |
remap: | | |
function(value, inLow, inHigh, outLow, outHigh) { | |
var newVal = ((value - inLow) * ((outHigh - outLow) / (inHigh - inLow))) + outLow; | |
if (newVal < outLow) { | |
newVal = outLow; | |
} else if (newVal > outHigh) { | |
newVal = outHigh; | |
} | |
return Math.floor(newVal); | |
} | |
layers: | |
# Terrain base map | |
terrain: | |
data: { source: stamen-terrain } | |
draw: | |
terrain: | |
order: 0 # draw on bottom | |
# Country polygons | |
FeatureCollection: | |
visible: true | |
data: | |
source: countryPolygons | |
draw: | |
polygonOverlay: | |
order: 10 | |
color: | | |
function() { | |
if (feature.iso_a3 === 'USA') { | |
return undefined | |
} else { | |
return [.0, .0, .0, .7]; | |
} | |
} | |
# Water layer | |
water: | |
data: { source: stamen-terrain } | |
draw: | |
polygons: | |
order: function() { return feature.sort_key; } | |
color: '#030418' | |
# Populated places | |
places: | |
data: {source : osm} | |
cities: | |
filter: | | |
function () { | |
return feature.kind === 'Populated place' && feature.population > 1000; | |
} | |
draw: | |
citydot: | |
size: | | |
function() { | |
// scale roughly by population | |
var size = global.remap(feature.population, 1000, 10000000, 25, 55); | |
return size; | |
} | |
color: '#0E8CC1' | |
order: 3 |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment