Merging skybox branch

master
Robin Hawkes 2016-02-24 20:48:59 +00:00
commit 8fd4c799e1
16 zmienionych plików z 1568 dodań i 789 usunięć

1477
dist/vizicities.js vendored

Plik diff jest za duży Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Wyświetl plik

@ -1,14 +1,10 @@
var world = VIZI.World('world').setView([51.505, -0.09]);
var world = VIZI.World('world', {
skybox: true
}).setView([51.505, -0.09]);
// Add controls
VIZI.Controls.Orbit().addTo(world);
// Not sure if I want to keep this as a public API
//
// Makes sense to allow others to customise their environment so perhaps this
// could be left public but a default is set up within World to simplify things
var environmentLayer = VIZI.EnvironmentLayer().addTo(world);
// // http://{s}.tile.osm.org/{z}/{x}/{y}.png
// // http://{s}.tiles.wmflabs.org/osm-no-labels/{z}/{x}/{y}.png
var imageTileLayer = VIZI.ImageTileLayer('http://{s}.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}.png', {
@ -18,7 +14,8 @@ var imageTileLayer = VIZI.ImageTileLayer('http://{s}.basemaps.cartocdn.com/light
var topoJSONTileLayer = VIZI.TopoJSONTileLayer('https://vector.mapzen.com/osm/buildings/{z}/{x}/{y}.topojson', {
style: function(feature) {
return {
color: (feature.properties.area > 10000) ? '#ff0000' : '#0000ff'
// color: (feature.properties.area > 10000) ? '#ff0000' : '#0000ff'
color: '#cccccc'
};
},
// filter: function(feature) {

Wyświetl plik

@ -7,7 +7,7 @@ import THREE from 'three';
// http://stackoverflow.com/q/26655930/997339
export default function(container) {
var camera = new THREE.PerspectiveCamera(45, 1, 1, 40000);
var camera = new THREE.PerspectiveCamera(45, 1, 1, 200000);
camera.position.y = 400;
camera.position.z = 400;

Wyświetl plik

@ -9,7 +9,10 @@ export default function(container) {
antialias: true
});
renderer.setClearColor(Scene.fog.color, 1);
// TODO: Re-enable when this works with the skybox
// renderer.setClearColor(Scene.fog.color, 1);
renderer.setClearColor(0xffffff, 1);
// Gamma settings make things look nicer
renderer.gammaInput = true;

Wyświetl plik

@ -5,6 +5,8 @@ import THREE from 'three';
export default (function() {
var scene = new THREE.Scene();
scene.fog = new THREE.Fog(0xffffff, 1, 15000);
// TODO: Re-enable when this works with the skybox
// scene.fog = new THREE.Fog(0xffffff, 1, 15000);
return scene;
})();

Wyświetl plik

@ -1,204 +0,0 @@
import EventEmitter from 'eventemitter3';
import extend from 'lodash.assign';
import CRS from './geo/CRS/index';
import Point from './geo/Point';
import LatLon from './geo/LatLon';
import Engine from './engine/Engine';
// Pretty much any event someone using ViziCities would need will be emitted or
// proxied by World (eg. render events, etc)
class World extends EventEmitter {
constructor(domId, options) {
super();
var defaults = {
crs: CRS.EPSG3857
};
this.options = extend(defaults, options);
this._layers = [];
this._controls = [];
this._initContainer(domId);
this._initEngine();
this._initEvents();
// Kick off the update and render loop
this._update();
}
_initContainer(domId) {
this._container = document.getElementById(domId);
}
_initEngine() {
this._engine = Engine(this._container);
// Engine events
//
// Consider proxying these through events on World for public access
// this._engine.on('preRender', () => {});
// this._engine.on('postRender', () => {});
}
_initEvents() {
this.on('controlsMoveEnd', this._onControlsMoveEnd);
}
_onControlsMoveEnd(point) {
var _point = Point(point.x, point.z);
this._resetView(this.pointToLatLon(_point), _point);
}
// Reset world view
_resetView(latlon, point) {
this.emit('preResetView');
this._moveStart();
this._move(latlon, point);
this._moveEnd();
this.emit('postResetView');
}
_moveStart() {
this.emit('moveStart');
}
_move(latlon, point) {
this._lastPosition = latlon;
this.emit('move', latlon, point);
}
_moveEnd() {
this.emit('moveEnd');
}
_update() {
var delta = this._engine.clock.getDelta();
// Once _update is called it will run forever, for now
window.requestAnimationFrame(this._update.bind(this));
// Update controls
this._controls.forEach(controls => {
controls.update();
});
this.emit('preUpdate');
this._engine.update(delta);
this.emit('postUpdate');
}
// Set world view
setView(latlon) {
// Store initial geographic coordinate for the [0,0,0] world position
//
// The origin point doesn't move in three.js / 3D space so only set it once
// here instead of every time _resetView is called
//
// If it was updated every time then coorindates would shift over time and
// would be out of place / context with previously-placed points (0,0 would
// refer to a different point each time)
this._originLatlon = latlon;
this._originPoint = this.project(latlon);
this._resetView(latlon);
return this;
}
// Return world geographic position
getPosition() {
return this._lastPosition;
}
// Transform geographic coordinate to world point
//
// This doesn't take into account the origin offset
//
// For example, this takes a geographic coordinate and returns a point
// relative to the origin point of the projection (not the world)
project(latlon) {
return this.options.crs.latLonToPoint(LatLon(latlon));
}
// Transform world point to geographic coordinate
//
// This doesn't take into account the origin offset
//
// For example, this takes a point relative to the origin point of the
// projection (not the world) and returns a geographic coordinate
unproject(point) {
return this.options.crs.pointToLatLon(Point(point));
}
// Takes into account the origin offset
//
// For example, this takes a geographic coordinate and returns a point
// relative to the three.js / 3D origin (0,0)
latLonToPoint(latlon) {
var projectedPoint = this.project(LatLon(latlon));
return projectedPoint._subtract(this._originPoint);
}
// Takes into account the origin offset
//
// For example, this takes a point relative to the three.js / 3D origin (0,0)
// and returns the exact geographic coordinate at that point
pointToLatLon(point) {
var projectedPoint = Point(point).add(this._originPoint);
return this.unproject(projectedPoint);
}
// Unsure if it's a good idea to expose this here for components like
// GridLayer to use (eg. to keep track of a frustum)
getCamera() {
return this._engine._camera;
}
addLayer(layer) {
layer._addToWorld(this);
this._layers.push(layer);
// Could move this into Layer but it'll do here for now
this._engine._scene.add(layer._layer);
this.emit('layerAdded', layer);
return this;
}
// Remove layer and perform clean up operations
removeLayer(layer) {
var layerIndex = this._layers.indexOf(layer);
if (layerIndex > -1) {
// Remove from this._layers
this._layers.splice(layerIndex, 1);
};
this._engine._scene.remove(layer._layer);
layer.destroy();
this.emit('layerRemoved');
return this;
}
addControls(controls) {
controls._addToWorld(this);
this._controls.push(controls);
this.emit('controlsAdded', controls);
return this;
}
removeControls(controls) {}
}
// Initialise without requiring new keyword
export default function(domId, options) {
return new World(domId, options);
};

Wyświetl plik

@ -1,15 +1,28 @@
import Layer from '../Layer';
import extend from 'lodash.assign';
import THREE from 'three';
import Skybox from './Skybox';
class EnvironmentLayer extends Layer {
constructor() {
constructor(options) {
super();
this._initLights();
// this._initGrid();
var defaults = {
skybox: false
};
this._options = extend(defaults, options);
}
_onAdd() {}
_onAdd() {
this._initLights();
if (this._options.skybox) {
this._initSkybox();
}
// this._initGrid();
}
// Not fleshed out or thought through yet
//
@ -19,26 +32,37 @@ class EnvironmentLayer extends Layer {
// Position doesn't really matter (the angle is important), however it's
// used here so the helpers look more natural.
var directionalLight = new THREE.DirectionalLight(0x999999);
directionalLight.intesity = 0.1;
directionalLight.position.x = 100;
directionalLight.position.y = 100;
directionalLight.position.z = 100;
if (!this._options.skybox) {
var directionalLight = new THREE.DirectionalLight(0x999999);
directionalLight.intesity = 0.1;
directionalLight.position.x = 100;
directionalLight.position.y = 100;
directionalLight.position.z = 100;
var directionalLight2 = new THREE.DirectionalLight(0x999999);
directionalLight2.intesity = 0.1;
directionalLight2.position.x = -100;
directionalLight2.position.y = 100;
directionalLight2.position.z = -100;
var directionalLight2 = new THREE.DirectionalLight(0x999999);
directionalLight2.intesity = 0.1;
directionalLight2.position.x = -100;
directionalLight2.position.y = 100;
directionalLight2.position.z = -100;
var helper = new THREE.DirectionalLightHelper(directionalLight, 10);
var helper2 = new THREE.DirectionalLightHelper(directionalLight2, 10);
var helper = new THREE.DirectionalLightHelper(directionalLight, 10);
var helper2 = new THREE.DirectionalLightHelper(directionalLight2, 10);
this._layer.add(directionalLight);
this._layer.add(directionalLight2);
this._layer.add(directionalLight);
this._layer.add(directionalLight2);
this._layer.add(helper);
this._layer.add(helper2);
this._layer.add(helper);
this._layer.add(helper2);
} else {
// Directional light that will be projected from the sun
this._skyboxLight = new THREE.DirectionalLight(0xffffff, 1);
this._layer.add(this._skyboxLight);
}
}
_initSkybox() {
this._skybox = Skybox(this._world, this._skyboxLight);
this._layer.add(this._skybox._mesh);
}
// Add grid helper for context during initial development
@ -49,9 +73,20 @@ class EnvironmentLayer extends Layer {
var gridHelper = new THREE.GridHelper(size, step);
this._layer.add(gridHelper);
}
// Clean up environment
destroy() {
this._skyboxLight = null;
this._layer.remove(this._skybox._mesh);
this._skybox.destroy();
this._skybox = null;
super.destroy();
}
}
// Initialise without requiring new keyword
export default function() {
return new EnvironmentLayer();
export default function(options) {
return new EnvironmentLayer(options);
};

Wyświetl plik

@ -0,0 +1,268 @@
// jscs:disable
/*eslint eqeqeq:0*/
/**
* @author zz85 / https://github.com/zz85
*
* Based on 'A Practical Analytic Model for Daylight'
* aka The Preetham Model, the de facto standard analytic skydome model
* http://www.cs.utah.edu/~shirley/papers/sunsky/sunsky.pdf
*
* First implemented by Simon Wallner
* http://www.simonwallner.at/projects/atmospheric-scattering
*
* Improved by Martin Upitis
* http://blenderartists.org/forum/showthread.php?245954-preethams-sky-impementation-HDR
*
* Three.js integration by zz85 http://twitter.com/blurspline
*/
import THREE from 'three';
THREE.ShaderLib[ 'sky' ] = {
uniforms: {
luminance: { type: 'f', value: 1 },
turbidity: { type: 'f', value: 2 },
reileigh: { type: 'f', value: 1 },
mieCoefficient: { type: 'f', value: 0.005 },
mieDirectionalG: { type: 'f', value: 0.8 },
sunPosition: { type: 'v3', value: new THREE.Vector3() }
},
vertexShader: [
'varying vec3 vWorldPosition;',
'void main() {',
'vec4 worldPosition = modelMatrix * vec4( position, 1.0 );',
'vWorldPosition = worldPosition.xyz;',
'gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );',
'}',
].join( '\n' ),
fragmentShader: [
'uniform sampler2D skySampler;',
'uniform vec3 sunPosition;',
'varying vec3 vWorldPosition;',
'vec3 cameraPos = vec3(0., 0., 0.);',
'// uniform sampler2D sDiffuse;',
'// const float turbidity = 10.0; //',
'// const float reileigh = 2.; //',
'// const float luminance = 1.0; //',
'// const float mieCoefficient = 0.005;',
'// const float mieDirectionalG = 0.8;',
'uniform float luminance;',
'uniform float turbidity;',
'uniform float reileigh;',
'uniform float mieCoefficient;',
'uniform float mieDirectionalG;',
'// constants for atmospheric scattering',
'const float e = 2.71828182845904523536028747135266249775724709369995957;',
'const float pi = 3.141592653589793238462643383279502884197169;',
'const float n = 1.0003; // refractive index of air',
'const float N = 2.545E25; // number of molecules per unit volume for air at',
'// 288.15K and 1013mb (sea level -45 celsius)',
'const float pn = 0.035; // depolatization factor for standard air',
'// wavelength of used primaries, according to preetham',
'const vec3 lambda = vec3(680E-9, 550E-9, 450E-9);',
'// mie stuff',
'// K coefficient for the primaries',
'const vec3 K = vec3(0.686, 0.678, 0.666);',
'const float v = 4.0;',
'// optical length at zenith for molecules',
'const float rayleighZenithLength = 8.4E3;',
'const float mieZenithLength = 1.25E3;',
'const vec3 up = vec3(0.0, 1.0, 0.0);',
'const float EE = 1000.0;',
'const float sunAngularDiameterCos = 0.999956676946448443553574619906976478926848692873900859324;',
'// 66 arc seconds -> degrees, and the cosine of that',
'// earth shadow hack',
'const float cutoffAngle = pi/1.95;',
'const float steepness = 1.5;',
'vec3 totalRayleigh(vec3 lambda)',
'{',
'return (8.0 * pow(pi, 3.0) * pow(pow(n, 2.0) - 1.0, 2.0) * (6.0 + 3.0 * pn)) / (3.0 * N * pow(lambda, vec3(4.0)) * (6.0 - 7.0 * pn));',
'}',
// see http://blenderartists.org/forum/showthread.php?321110-Shaders-and-Skybox-madness
'// A simplied version of the total Reayleigh scattering to works on browsers that use ANGLE',
'vec3 simplifiedRayleigh()',
'{',
'return 0.0005 / vec3(94, 40, 18);',
// return 0.00054532832366 / (3.0 * 2.545E25 * pow(vec3(680E-9, 550E-9, 450E-9), vec3(4.0)) * 6.245);
'}',
'float rayleighPhase(float cosTheta)',
'{ ',
'return (3.0 / (16.0*pi)) * (1.0 + pow(cosTheta, 2.0));',
'// return (1.0 / (3.0*pi)) * (1.0 + pow(cosTheta, 2.0));',
'// return (3.0 / 4.0) * (1.0 + pow(cosTheta, 2.0));',
'}',
'vec3 totalMie(vec3 lambda, vec3 K, float T)',
'{',
'float c = (0.2 * T ) * 10E-18;',
'return 0.434 * c * pi * pow((2.0 * pi) / lambda, vec3(v - 2.0)) * K;',
'}',
'float hgPhase(float cosTheta, float g)',
'{',
'return (1.0 / (4.0*pi)) * ((1.0 - pow(g, 2.0)) / pow(1.0 - 2.0*g*cosTheta + pow(g, 2.0), 1.5));',
'}',
'float sunIntensity(float zenithAngleCos)',
'{',
'return EE * max(0.0, 1.0 - exp(-((cutoffAngle - acos(zenithAngleCos))/steepness)));',
'}',
'// float logLuminance(vec3 c)',
'// {',
'// return log(c.r * 0.2126 + c.g * 0.7152 + c.b * 0.0722);',
'// }',
'// Filmic ToneMapping http://filmicgames.com/archives/75',
'float A = 0.15;',
'float B = 0.50;',
'float C = 0.10;',
'float D = 0.20;',
'float E = 0.02;',
'float F = 0.30;',
'float W = 1000.0;',
'vec3 Uncharted2Tonemap(vec3 x)',
'{',
'return ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F;',
'}',
'void main() ',
'{',
'float sunfade = 1.0-clamp(1.0-exp((sunPosition.y/450000.0)),0.0,1.0);',
'// luminance = 1.0 ;// vWorldPosition.y / 450000. + 0.5; //sunPosition.y / 450000. * 1. + 0.5;',
'// gl_FragColor = vec4(sunfade, sunfade, sunfade, 1.0);',
'float reileighCoefficient = reileigh - (1.0* (1.0-sunfade));',
'vec3 sunDirection = normalize(sunPosition);',
'float sunE = sunIntensity(dot(sunDirection, up));',
'// extinction (absorbtion + out scattering) ',
'// rayleigh coefficients',
// 'vec3 betaR = totalRayleigh(lambda) * reileighCoefficient;',
'vec3 betaR = simplifiedRayleigh() * reileighCoefficient;',
'// mie coefficients',
'vec3 betaM = totalMie(lambda, K, turbidity) * mieCoefficient;',
'// optical length',
'// cutoff angle at 90 to avoid singularity in next formula.',
'float zenithAngle = acos(max(0.0, dot(up, normalize(vWorldPosition - cameraPos))));',
'float sR = rayleighZenithLength / (cos(zenithAngle) + 0.15 * pow(93.885 - ((zenithAngle * 180.0) / pi), -1.253));',
'float sM = mieZenithLength / (cos(zenithAngle) + 0.15 * pow(93.885 - ((zenithAngle * 180.0) / pi), -1.253));',
'// combined extinction factor ',
'vec3 Fex = exp(-(betaR * sR + betaM * sM));',
'// in scattering',
'float cosTheta = dot(normalize(vWorldPosition - cameraPos), sunDirection);',
'float rPhase = rayleighPhase(cosTheta*0.5+0.5);',
'vec3 betaRTheta = betaR * rPhase;',
'float mPhase = hgPhase(cosTheta, mieDirectionalG);',
'vec3 betaMTheta = betaM * mPhase;',
'vec3 Lin = pow(sunE * ((betaRTheta + betaMTheta) / (betaR + betaM)) * (1.0 - Fex),vec3(1.5));',
'Lin *= mix(vec3(1.0),pow(sunE * ((betaRTheta + betaMTheta) / (betaR + betaM)) * Fex,vec3(1.0/2.0)),clamp(pow(1.0-dot(up, sunDirection),5.0),0.0,1.0));',
'//nightsky',
'vec3 direction = normalize(vWorldPosition - cameraPos);',
'float theta = acos(direction.y); // elevation --> y-axis, [-pi/2, pi/2]',
'float phi = atan(direction.z, direction.x); // azimuth --> x-axis [-pi/2, pi/2]',
'vec2 uv = vec2(phi, theta) / vec2(2.0*pi, pi) + vec2(0.5, 0.0);',
'// vec3 L0 = texture2D(skySampler, uv).rgb+0.1 * Fex;',
'vec3 L0 = vec3(0.1) * Fex;',
'// composition + solar disc',
'//if (cosTheta > sunAngularDiameterCos)',
'float sundisk = smoothstep(sunAngularDiameterCos,sunAngularDiameterCos+0.00002,cosTheta);',
'// if (normalize(vWorldPosition - cameraPos).y>0.0)',
'L0 += (sunE * 19000.0 * Fex)*sundisk;',
'vec3 whiteScale = 1.0/Uncharted2Tonemap(vec3(W));',
'vec3 texColor = (Lin+L0); ',
'texColor *= 0.04 ;',
'texColor += vec3(0.0,0.001,0.0025)*0.3;',
'float g_fMaxLuminance = 1.0;',
'float fLumScaled = 0.1 / luminance; ',
'float fLumCompressed = (fLumScaled * (1.0 + (fLumScaled / (g_fMaxLuminance * g_fMaxLuminance)))) / (1.0 + fLumScaled); ',
'float ExposureBias = fLumCompressed;',
'vec3 curr = Uncharted2Tonemap((log2(2.0/pow(luminance,4.0)))*texColor);',
'vec3 color = curr*whiteScale;',
'vec3 retColor = pow(color,vec3(1.0/(1.2+(1.2*sunfade))));',
'gl_FragColor.rgb = retColor;',
'gl_FragColor.a = 1.0;',
'}',
].join( '\n' )
};
var Sky = function () {
var skyShader = THREE.ShaderLib[ 'sky' ];
var skyUniforms = THREE.UniformsUtils.clone( skyShader.uniforms );
var skyMat = new THREE.ShaderMaterial( {
fragmentShader: skyShader.fragmentShader,
vertexShader: skyShader.vertexShader,
uniforms: skyUniforms,
side: THREE.BackSide
} );
var skyGeo = new THREE.SphereBufferGeometry( 450000, 32, 15 );
var skyMesh = new THREE.Mesh( skyGeo, skyMat );
// Expose variables
this.mesh = skyMesh;
this.uniforms = skyUniforms;
};
export default Sky;

Wyświetl plik

@ -0,0 +1,195 @@
import THREE from 'three';
import Sky from './Sky';
import throttle from 'lodash.throttle';
var cubemap = {
vertexShader: [
'varying vec3 vPosition;',
'void main() {',
'vPosition = position;',
'gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );',
'}'
].join('\n'),
fragmentShader: [
'uniform samplerCube cubemap;',
'varying vec3 vPosition;',
'void main() {',
'gl_FragColor = textureCube(cubemap, normalize(vPosition));',
'}'
].join('\n')
};
class Skybox {
constructor(world, light) {
this._world = world;
this._light = light;
this._settings = {
distance: 40000,
turbidity: 10,
reileigh: 2,
mieCoefficient: 0.005,
mieDirectionalG: 0.8,
luminance: 1,
inclination: 0.48, // Elevation / inclination
azimuth: 0.25, // Facing front
};
this._initSkybox();
this._updateUniforms();
this._initEvents();
}
_initEvents() {
// Throttled to 1 per 100ms
this._throttledWorldUpdate = throttle(this._update, 100);
this._world.on('preUpdate', this._throttledWorldUpdate, this);
}
_initSkybox() {
// Cube camera for skybox
this._cubeCamera = new THREE.CubeCamera(1, 2000000, 128);
// Cube material
var cubeTarget = this._cubeCamera.renderTarget;
// Add Sky Mesh
this._sky = new Sky();
this._skyScene = new THREE.Scene();
this._skyScene.add(this._sky.mesh);
// Add Sun Helper
this._sunSphere = new THREE.Mesh(
new THREE.SphereBufferGeometry(2000, 16, 8),
new THREE.MeshBasicMaterial({
color: 0xffffff
})
);
this._sunSphere.position.y = -700000;
this._sunSphere.visible = false;
var skyboxUniforms = {
cubemap: { type: 't', value: cubeTarget }
};
var skyboxMat = new THREE.ShaderMaterial({
uniforms: skyboxUniforms,
vertexShader: cubemap.vertexShader,
fragmentShader: cubemap.fragmentShader,
side: THREE.BackSide
});
this._mesh = new THREE.Mesh(new THREE.BoxGeometry(190000, 190000, 190000), skyboxMat);
}
_updateUniforms() {
var settings = this._settings;
var uniforms = this._sky.uniforms;
uniforms.turbidity.value = settings.turbidity;
uniforms.reileigh.value = settings.reileigh;
uniforms.luminance.value = settings.luminance;
uniforms.mieCoefficient.value = settings.mieCoefficient;
uniforms.mieDirectionalG.value = settings.mieDirectionalG;
var theta = Math.PI * (settings.inclination - 0.5);
var phi = 2 * Math.PI * (settings.azimuth - 0.5);
this._sunSphere.position.x = settings.distance * Math.cos(phi);
this._sunSphere.position.y = settings.distance * Math.sin(phi) * Math.sin(theta);
this._sunSphere.position.z = settings.distance * Math.sin(phi) * Math.cos(theta);
// Move directional light to sun position
this._light.position.copy(this._sunSphere.position);
this._sky.uniforms.sunPosition.value.copy(this._sunSphere.position);
}
_update(delta) {
if (!this._done) {
this._done = true;
} else {
return;
}
// if (!this._angle) {
// this._angle = 0;
// }
//
// // Animate inclination
// this._angle += Math.PI * delta;
// this._settings.inclination = 0.5 * (Math.sin(this._angle) / 2 + 0.5);
// Update light intensity depending on elevation of sun (day to night)
this._light.intensity = 1 - 0.95 * (this._settings.inclination / 0.5);
// // console.log(delta, this._angle, this._settings.inclination);
//
// TODO: Only do this when the uniforms have been changed
this._updateUniforms();
// TODO: Only do this when the cubemap has actually changed
this._cubeCamera.updateCubeMap(this._world._engine._renderer, this._skyScene);
}
getRenderTarget() {
return this._cubeCamera.renderTarget;
}
// Destroy the skybox and remove it from memory
destroy() {
this._world.off('preUpdate', this._throttledWorldUpdate);
this._throttledWorldUpdate = null;
this._world = null;
this._light = null;
this._cubeCamera = null;
this._sky.mesh.geometry.dispose();
this._sky.mesh.geometry = null;
if (this._sky.mesh.material.map) {
this._sky.mesh.material.map.dispose();
this._sky.mesh.material.map = null;
}
this._sky.mesh.material.dispose();
this._sky.mesh.material = null;
this._sky.mesh = null;
this._sky = null;
this._skyScene = null;
this._sunSphere.geometry.dispose();
this._sunSphere.geometry = null;
if (this._sunSphere.material.map) {
this._sunSphere.material.map.dispose();
this._sunSphere.material.map = null;
}
this._sunSphere.material.dispose();
this._sunSphere.material = null;
this._sunSphere = null;
this._mesh.geometry.dispose();
this._mesh.geometry = null;
if (this._mesh.material.map) {
this._mesh.material.map.dispose();
this._mesh.material.map = null;
}
this._mesh.material.dispose();
this._mesh.material = null;
}
}
// Initialise without requiring new keyword
export default function(world, light) {
return new Skybox(world, light);
};

Wyświetl plik

@ -39,15 +39,33 @@ class ImageTile extends Tile {
var mesh = new THREE.Object3D();
var geom = new THREE.PlaneBufferGeometry(this._side, this._side, 1);
var material = new THREE.MeshBasicMaterial({
depthWrite: false
});
var material;
if (!this._world._environment._skybox) {
material = new THREE.MeshBasicMaterial({
depthWrite: false
});
// var material = new THREE.MeshPhongMaterial({
// depthWrite: false
// });
} else {
// Other MeshStandardMaterial settings
//
// material.envMapIntensity will change the amount of colour reflected(?)
// from the environment map – can be greater than 1 for more intensity
material = new THREE.MeshStandardMaterial({
depthWrite: false
});
material.roughness = 1;
material.metalness = 0.1;
material.envMap = this._world._environment._skybox.getRenderTarget();
}
var localMesh = new THREE.Mesh(geom, material);
localMesh.rotation.x = -90 * Math.PI / 180;
mesh.add(localMesh);
mesh.renderOrder = 0;
mesh.position.x = this._center[0];

Wyświetl plik

@ -3,6 +3,7 @@ import ImageTile from './ImageTile';
import ImageTileLayerBaseMaterial from './ImageTileLayerBaseMaterial';
import throttle from 'lodash.throttle';
import THREE from 'three';
import extend from 'lodash.assign';
// DONE: Find a way to avoid the flashing caused by the gap between old tiles
// being removed and the new tiles being ready for display
@ -45,6 +46,12 @@ import THREE from 'three';
class ImageTileLayer extends TileLayer {
constructor(path, options) {
var defaults = {
distance: 40000
};
options = extend(defaults, options);
super(options);
this._path = path;
@ -54,8 +61,16 @@ class ImageTileLayer extends TileLayer {
super._onAdd(world);
// Add base layer
var geom = new THREE.PlaneBufferGeometry(40000, 40000, 1);
var mesh = new THREE.Mesh(geom, ImageTileLayerBaseMaterial('#f5f5f3'));
var geom = new THREE.PlaneBufferGeometry(200000, 200000, 1);
var baseMaterial;
if (this._world._environment._skybox) {
baseMaterial = ImageTileLayerBaseMaterial('#f5f5f3', this._world._environment._skybox.getRenderTarget());
} else {
baseMaterial = ImageTileLayerBaseMaterial('#f5f5f3');
}
var mesh = new THREE.Mesh(geom, baseMaterial);
mesh.rotation.x = -90 * Math.PI / 180;
this._baseLayer = mesh;

Wyświetl plik

@ -1,6 +1,6 @@
import THREE from 'three';
export default function(colour) {
export default function(colour, skyboxTarget) {
var canvas = document.createElement('canvas');
canvas.width = 1;
canvas.height = 1;
@ -26,10 +26,21 @@ export default function(colour) {
texture.needsUpdate = true;
var material = new THREE.MeshBasicMaterial({
map: texture,
depthWrite: false
});
var material;
if (!skyboxTarget) {
material = new THREE.MeshBasicMaterial({
map: texture,
depthWrite: false
});
} else {
material = new THREE.MeshStandardMaterial({
depthWrite: false
});
material.roughness = 1;
material.metalness = 0.1;
material.envMap = skyboxTarget;
}
return material;
};

Wyświetl plik

@ -10,6 +10,7 @@ var tileURLRegex = /\{([szxy])\}/g;
class Tile {
constructor(quadcode, path, layer) {
this._layer = layer;
this._world = layer._world;
this._quadcode = quadcode;
this._path = path;
@ -64,8 +65,9 @@ class Tile {
// Ensure that this leaves no trace of the tile – no textures, no meshes,
// nothing in memory or the GPU
destroy() {
// Delete reference to layer
// Delete reference to layer and world
this._layer = null;
thos._world = null;
// Delete location references
this._boundsLatLon = null;
@ -111,7 +113,7 @@ class Tile {
_getTileURL(urlParams) {
if (!urlParams.s) {
// Default to a random choice of a, b or c
s = String.fromCharCode(97 + Math.floor(Math.random() * 3));
urlParams.s = String.fromCharCode(97 + Math.floor(Math.random() * 3));
}
tileURLRegex.lastIndex = 0;

Wyświetl plik

@ -44,7 +44,7 @@ class TopoJSONTile extends Tile {
var defaults = {
filter: null,
style: {
color: '#ff0000'
color: '#ffffff'
}
};
@ -82,8 +82,6 @@ class TopoJSONTile extends Tile {
var mesh = new THREE.Object3D();
mesh.renderOrder = 1;
mesh.position.x = this._center[0];
mesh.position.z = this._center[1];
@ -386,12 +384,26 @@ class TopoJSONTile extends Tile {
geometry.computeBoundingBox();
var material = new THREE.MeshPhongMaterial({
vertexColors: THREE.VertexColors,
side: THREE.BackSide
// depthWrite: false
});
var material;
if (!this._world._environment._skybox) {
material = new THREE.MeshPhongMaterial({
vertexColors: THREE.VertexColors,
side: THREE.BackSide
});
} else {
material = new THREE.MeshStandardMaterial({
vertexColors: THREE.VertexColors,
side: THREE.BackSide
});
material.roughness = 1;
material.metalness = 0.1;
material.envMapIntensity = 3;
material.envMap = this._world._environment._skybox.getRenderTarget();
}
var mesh = new THREE.Mesh(geometry, material);
// This is only useful for flat objects
// mesh.renderOrder = 1;
this._mesh.add(mesh);