Skip to content

Instantly share code, notes, and snippets.

@tafsiri
Last active Nov 2, 2016
Embed
What would you like to do?

Tangram Lights

A small example to experiment with tangram lights. Double click on control sections to expand them and experiment with different lights. Docs are https://mapzen.com/documentation/tangram/Lights-Overview/ and https://mapzen.com/documentation/tangram/lights/

Notes

Updating the scene config takes ~30-40ms.

UPDATE: Turns out that instead of updateConfig, i could be using requestRedraw() after changing existing params in some cases. My hunch is that updateConfig is only needed to add or remove something to the config, but not necessarily change a value.

Update config is also needed when switching cameras and certain light properties. Look to this example for demonstration. https://github.com/tangrams/lights-cameras-demo

Ambient colors

Every light type can have an ambient color, this will generally behave like an ambient light casting in all directions. Easy to lose the effect of the other components to this one.

Materials

The material of the surface reflecting the light probably has a big influence on the resulting colors in the scene, but this block doesn't experiment with that at all.

<!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');
var layer = Tangram.leafletLayer({
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);
// Set location to boston
map.setView([42.364506, -71.038887], 15);
var updateConfig = function() {
window.requestAnimationFrame(function() {
scene.updateConfig();
});
}
function createControls() {
var directional = QuickSettings.create(50, 70, 'Directional Light');
var spotlight = QuickSettings.create(50, 40, 'Spotlight');
var pointlight = QuickSettings.create(50, 10, 'Point Light');
directional.setCollapsible(true);
spotlight.setCollapsible(true);
pointlight.setCollapsible(true);
// directional.collapse();
spotlight.collapse();
pointlight.collapse();
// Directional
directional.addBoolean('D.visible', true);
directional.addColor('D.diffuse', '#313131');
directional.addColor('D.ambient', '#313131');
directional.addColor('D.specular', '#313131');
directional.addRange('D.direction.x', -1, 1, 0, 0.05);
directional.addRange('D.direction.y', -1, 1, 0, 0.05);
directional.addRange('D.direction.z', -1, 1, -0.5, 0.05);
// Point
pointlight.addBoolean('P.visible', false);
pointlight.addColor('P.diffuse', '#313131');
pointlight.addColor('P.ambient', '#313131');
pointlight.addColor('P.specular', '#313131');
pointlight.addRange('P.position.x', -1000, 1000, 0, 10);
pointlight.addRange('P.position.y', -1000, 1000, 0, 10);
pointlight.addRange('P.position.z', 0, 500, 100, 5);
pointlight.addRange('P.radius.inner', 0, 500, 300, 5);
pointlight.addRange('P.radius.outer', 0, 1000, 500, 5);
// spotlight
spotlight.addBoolean('S.visible', false);
spotlight.addColor('S.diffuse', '#313131');
spotlight.addColor('S.ambient', '#313131');
spotlight.addColor('S.specular', '#313131');
spotlight.addRange('S.position.x', -1000, 1000, 0, 10);
spotlight.addRange('S.position.y', -1000, 1000, 0, 10);
spotlight.addRange('S.position.z', 0, 500, 100, 5);
spotlight.addRange('S.direction.x', -1, 1, 0.3, 0.05);
spotlight.addRange('S.direction.y', -1, 1, 0.3, 0.05);
spotlight.addRange('S.direction.z', -1, 1, 0, 0.1);
spotlight.addRange('S.angle', 0, 360, 20, 1);
spotlight.addRange('S.exponent', 0, 1, 0.2, 0.05);
function handleChange() {
var dl = {
visible: directional.getBoolean('D.visible'),
diffuse: directional.getColor('D.diffuse'),
ambient: directional.getColor('D.ambient'),
specular: directional.getColor('D.specular'),
direction: [
directional.getRangeValue('D.direction.x'),
directional.getRangeValue('D.direction.y'),
directional.getRangeValue('D.direction.z')
]
};
var pl = {
visible: pointlight.getBoolean('P.visible'),
diffuse: pointlight.getColor('P.diffuse'),
ambient: pointlight.getColor('P.ambient'),
specular: pointlight.getColor('P.specular'),
position: [
pointlight.getRangeValue('P.position.x'),
pointlight.getRangeValue('P.position.y'),
pointlight.getRangeValue('P.position.z')
],
radius: [
pointlight.getRangeValue('P.radius.inner'),
pointlight.getRangeValue('P.radius.outer')
]
};
var sl = {
visible: spotlight.getBoolean('S.visible'),
diffuse: spotlight.getColor('S.diffuse'),
ambient: spotlight.getColor('S.ambient'),
specular: spotlight.getColor('S.specular'),
direction: [
spotlight.getRangeValue('S.direction.x'),
spotlight.getRangeValue('S.direction.y'),
spotlight.getRangeValue('S.direction.z')
],
position: [
spotlight.getRangeValue('S.position.x'),
spotlight.getRangeValue('S.position.y'),
spotlight.getRangeValue('S.position.z')
],
angle: spotlight.getRangeValue('S.angle'),
exponent: spotlight.getRangeValue('S.exponent')
};
var config = scene.config;
_.merge(config.lights.directional, dl);
_.merge(config.lights.point, pl);
_.merge(config.lights.spot, sl);
updateConfig();
}
directional.setGlobalChangeHandler(handleChange);
pointlight.setGlobalChangeHandler(handleChange);
spotlight.setGlobalChangeHandler(handleChange);
}
// Grab a reference to the scene and watch for errors.
var scene = layer.scene;
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');
createControls();
}
});
</script>
</body>
cameras:
camera1:
type: perspective
lights:
directional:
visible: true
type: directional
direction: [0, 1, -.5]
diffuse: .1
ambient: .3
point:
visible: false
type: point
position: [0, 0, 100]
origin: ground
ambient: .3
diffuse: 1
specular: .2
spot:
visible: false
type: spotlight
position: [0, 0, 100]
direction: [0, 1, -.5]
origin: ground
ambient: .3
diffuse: 1
specular: .2
angle: 0.2
sources:
osm:
type: TopoJSON
url: https://vector.mapzen.com/osm/all/{z}/{x}/{y}.topojson?api_key=vector-tiles-jvpqPNW
max_zoom: 16
layers:
earth:
data: { source: osm }
draw:
polygons:
order: function() { return feature.sort_key; }
color: '#ffffff'
landuse:
visible: true
data: { source: osm }
draw:
polygons:
order: function() { return feature.sort_key; }
color: '#ffffff'
water:
data: { source: osm }
draw:
polygons:
order: function() { return feature.sort_key; }
color: '#96acba'
roads:
data: { source: osm }
filter:
not: { kind: ["path", "rail"] }
draw:
lines:
order: function() { return feature.sort_key; }
color: '#6e6e6e'
width: 8
cap: round
minor_road:
filter:
kind: minor_road
draw:
lines:
order: function() { return feature.sort_key; }
color: '#cfcfcf'
width: 5
buildings:
data: { source: osm }
draw:
polygons:
order: function() { return feature.sort_key; }
color: grey
3d-buildings:
filter: { $zoom: { min: 15 } }
draw:
polygons:
extrude: function () { return feature.height > 20 || $zoom >= 16; }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment