Skip to content

Instantly share code, notes, and snippets.

@tafsiri
Last active October 21, 2016 03:59
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tafsiri/edcf6bf6c5e01ebeab5d718377734ad2 to your computer and use it in GitHub Desktop.
Save tafsiri/edcf6bf6c5e01ebeab5d718377734ad2 to your computer and use it in GitHub Desktop.

Tangram Interactive Shader

Driving shaders params via mouse interaction.

Notes

Use requestRender rather than updateConfig and you can set scene properties (e.g. uniforms) directly.

To interact with uniforms, declare them in the scene file then directly manipulate them from the scene object (not the config) in the JS api.

<!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/0.8/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')
.setView([40.7201716,-74.0055515], 15);;
var layer = Tangram.leafletLayer({
maxZoom: 16,
minZoom: 14,
scene: 'scene.yaml',
attribution: '<a href="https://mapzen.com/tangram" target="_blank">Tangram</a> | &copy; 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;
// WebGl Coordinate system starts in the middle and y grows upwards
var x = selection.pixel.x - (node.clientWidth / 2);
var y = -selection.pixel.y + (node.clientHeight / 2);
scene.styles.buildings.shaders.uniforms.u_mouse_x = x;
scene.styles.buildings.shaders.uniforms.u_mouse_y = y;
requestRedraw();
}
},
// click: function(selection) {
// console.log('Click!', selection);
// }
});
// 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>
cameras:
camera1:
type: isometric
lights:
directional:
visible: true
type: directional
direction: [0, 1, -.5]
diffuse: .9
ambient: .9
specular: .9
sources:
osm:
type: TopoJSON
url: https://vector.mapzen.com/osm/all/{z}/{x}/{y}.topojson?api_key=vector-tiles-jvpqPNW
styles:
buildings:
base: polygons
animated: true
material:
diffuse:
texture: metallic-gold-texture-small.jpeg
mapping: spheremap
ambient: 0.5
specular: 0.5
shininess: 2.0
shaders:
uniforms:
u_mouse_x: 0
u_mouse_y: 0
blocks:
global: |
vec3 hsb2rgb( in float hue, in float sat, in float bri ){
vec3 rgb = clamp(abs(mod(hue*6.0+vec3(0.0,4.0,2.0),
6.0)-3.0)-1.0,
0.0,
1.0 );
rgb = rgb*rgb*(3.0-2.0*rgb);
return bri * mix(vec3(1.0), rgb, sat);
}
position: |
vec2 mousePos = vec2(u_mouse_x, u_mouse_y);
// Positions are in meters, so divide by metres per pixel.
vec2 vertexPos = position.xy / u_meters_per_pixel;
float mouseDistance = abs(distance(mousePos, vertexPos));
float threshold = 100.;
float maxHeight = 10.;
float invDistance = 1. / (mouseDistance/threshold);
if(position.z > 0.){
// there is probably a way to convert this if statement
// to a math function. probably using step.
position.z *= clamp(invDistance * maxHeight, 0., maxHeight);
}
color: |
float height = worldPosition().z / u_meters_per_pixel;
float brightness = height/10.;
color *= vec4(hsb2rgb(0., 0., brightness), .4);
layers:
earth:
data: { source: osm }
draw:
polygons:
order: function() { return feature.sort_key; }
color: '#555'
landuse:
visible: true
data: { source: osm }
draw:
polygons:
order: function() { return feature.sort_key; }
color: '#555'
water:
data: { source: osm }
draw:
polygons:
order: function() { return feature.sort_key; }
color: '#96acba'
# color: '#78a5c2'
buildings:
data: { source: osm }
draw:
buildings:
order: function() { return feature.sort_key; }
color: '#E7A431'
extrude: true
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment