UNPKG

mapbox-gl

Version:
133 lines (111 loc) 4.71 kB
// @flow import StyleLayer from '../style_layer.js'; import properties from './sky_style_layer_properties.js'; import {Transitionable, Transitioning, PossiblyEvaluated} from '../properties.js'; import {renderColorRamp} from '../../util/color_ramp.js'; import type {PaintProps} from './sky_style_layer_properties.js'; import type Texture from '../../render/texture.js'; import type Painter from '../../render/painter.js'; import type {LayerSpecification} from '../../style-spec/types.js'; import type Framebuffer from '../../gl/framebuffer.js'; import type {RGBAImage} from '../../util/image.js'; import type SkyboxGeometry from '../../render/skybox_geometry.js'; import type {LightPosition} from '../light.js'; import {warnOnce, degToRad} from '../../util/util.js'; import {vec3, quat} from 'gl-matrix'; function getCelestialDirection(azimuth: number, altitude: number, leftHanded: boolean): vec3 { const up = vec3.fromValues(0, 0, 1); const rotation = quat.identity(quat.create()); quat.rotateY(rotation, rotation, leftHanded ? -degToRad(azimuth) + Math.PI : degToRad(azimuth)); quat.rotateX(rotation, rotation, -degToRad(altitude)); vec3.transformQuat(up, up, rotation); return vec3.normalize(up, up); } class SkyLayer extends StyleLayer { _transitionablePaint: Transitionable<PaintProps>; _transitioningPaint: Transitioning<PaintProps>; paint: PossiblyEvaluated<PaintProps>; _lightPosition: LightPosition; skyboxFbo: ?Framebuffer; skyboxTexture: ?WebGLTexture; _skyboxInvalidated: ?boolean; colorRamp: RGBAImage; colorRampTexture: ?Texture; skyboxGeometry: SkyboxGeometry; constructor(layer: LayerSpecification) { super(layer, properties); this._updateColorRamp(); } _handleSpecialPaintPropertyUpdate(name: string) { if (name === 'sky-gradient') { this._updateColorRamp(); } else if (name === 'sky-atmosphere-sun' || name === 'sky-atmosphere-halo-color' || name === 'sky-atmosphere-color' || name === 'sky-atmosphere-sun-intensity') { this._skyboxInvalidated = true; } } _updateColorRamp() { const expression = this._transitionablePaint._values['sky-gradient'].value.expression; this.colorRamp = renderColorRamp({ expression, evaluationKey: 'skyRadialProgress' }); if (this.colorRampTexture) { this.colorRampTexture.destroy(); this.colorRampTexture = null; } } needsSkyboxCapture(painter: Painter) { if (!!this._skyboxInvalidated || !this.skyboxTexture || !this.skyboxGeometry) { return true; } if (!this.paint.get('sky-atmosphere-sun')) { const lightPosition = painter.style.light.properties.get('position'); return this._lightPosition.azimuthal !== lightPosition.azimuthal || this._lightPosition.polar !== lightPosition.polar; } } getCenter(painter: Painter, leftHanded: boolean) { const type = this.paint.get('sky-type'); if (type === 'atmosphere') { const sunPosition = this.paint.get('sky-atmosphere-sun'); const useLightPosition = !sunPosition; const light = painter.style.light; const lightPosition = light.properties.get('position'); if (useLightPosition && light.properties.get('anchor') === 'viewport') { warnOnce('The sun direction is attached to a light with viewport anchor, lighting may behave unexpectedly.'); } return useLightPosition ? getCelestialDirection(lightPosition.azimuthal, -lightPosition.polar + 90, leftHanded) : getCelestialDirection(sunPosition[0], -sunPosition[1] + 90, leftHanded); } else if (type === 'gradient') { const direction = this.paint.get('sky-gradient-center'); return getCelestialDirection(direction[0], -direction[1] + 90, leftHanded); } } is3D() { return false; } isSky() { return true; } markSkyboxValid(painter: Painter) { this._skyboxInvalidated = false; this._lightPosition = painter.style.light.properties.get('position'); } hasOffscreenPass() { return true; } getProgramIds(): string[] | null { const type = this.paint.get('sky-type'); if (type === 'atmosphere') { return ['skyboxCapture', 'skybox']; } else if (type === 'gradient') { return ['skyboxGradient']; } return null; } } export default SkyLayer;