maplibre-gl
Version:
BSD licensed community fork of mapbox-gl, a WebGL interactive maps library
150 lines (131 loc) • 6.22 kB
text/typescript
import type {CanonicalTileID} from '../../source/tile_id';
import type {PreparedShader} from '../../shaders/shaders';
import type {Context} from '../../gl/context';
import type {Mesh} from '../../render/mesh';
import type {Program} from '../../render/program';
import type {SubdivisionGranularitySetting} from '../../render/subdivision_granularity_settings';
import type {ProjectionSpecification} from '@maplibre/maplibre-gl-style-spec';
import type {EvaluationParameters} from '../../style/evaluation_parameters';
/**
* Custom projections are handled both by a class which implements this `Projection` interface,
* and a class that is derived from the `Transform` base class. What is the difference?
*
* The transform-derived class:
* - should do all the heavy lifting for the projection - implement all the `project*` and `unproject*` functions, etc.
* - must store the map's state - center, pitch, etc. - this is handled in the `Transform` base class
* - must be cloneable - it should not create any heavy resources
*
* The projection-implementing class:
* - must provide basic information and data about the projection, which is *independent of the map's state* - name, shader functions, subdivision settings, etc.
* - must be a "singleton" - no matter how many copies of the matching Transform class exist, the Projection should always exist as a single instance (per Map)
* - may create heavy resources that should not exist in multiple copies (projection is never cloned) - for example, see the GPU inaccuracy mitigation for globe projection
* - must be explicitly disposed of after usage using the `destroy` function - this allows the implementing class to free any allocated resources
*/
/**
* @internal
*/
export type ProjectionGPUContext = {
context: Context;
useProgram: (name: string) => Program<any>;
};
/**
* @internal
* Specifies the usage for a square tile mesh:
* - 'stencil' for drawing stencil masks
* - 'raster' for drawing raster tiles, hillshade, etc.
*/
export type TileMeshUsage = 'stencil' | 'raster';
/**
* An interface the implementations of which are used internally by MapLibre to handle different projections.
*/
export interface Projection {
/**
* @internal
* A short, descriptive name of this projection, such as 'mercator' or 'globe'.
*/
get name(): ProjectionSpecification['type'];
/**
* @internal
* True if this projection needs to render subdivided geometry.
* Optimized rendering paths for non-subdivided geometry might be used throughout MapLibre.
* The value of this property may change during runtime, for example in globe projection depending on zoom.
*/
get useSubdivision(): boolean;
/**
* Name of the shader projection variant that should be used for this projection.
* Note that this value may change dynamically, for example when globe projection internally transitions to mercator.
* Then globe projection might start reporting the mercator shader variant name to make MapLibre use faster mercator shaders.
*/
get shaderVariantName(): string;
/**
* A `#define` macro that is injected into every MapLibre shader that uses this projection.
* @example
* `const define = projection.shaderDefine; // '#define GLOBE'`
*/
get shaderDefine(): string;
/**
* @internal
* A preprocessed prelude code for both vertex and fragment shaders.
*/
get shaderPreludeCode(): PreparedShader;
/**
* Vertex shader code that is injected into every MapLibre vertex shader that uses this projection.
*/
get vertexShaderPreludeCode(): string;
/**
* @internal
* An object describing how much subdivision should be applied to rendered geometry.
* The subdivision settings should be a constant for a given projection.
* Projections that do not require subdivision should return {@link SubdivisionGranularitySetting.noSubdivision}.
*/
get subdivisionGranularity(): SubdivisionGranularitySetting;
/**
* @internal
* A number representing the current transition state of the projection.
* The return value should be a number between 0 and 1,
* where 0 means the projection is fully in the initial state,
* and 1 means the projection is fully in the final state.
*/
get transitionState(): number;
/**
* @internal
* Gets the error correction latitude in radians.
*/
get latitudeErrorCorrectionRadians(): number;
/**
* @internal
* Cleans up any resources the projection created, especially GPU buffers.
*/
destroy(): void;
/**
* @internal
* Runs any GPU-side tasks this projection required. Called at the beginning of every frame.
*/
updateGPUdependent(renderContext: ProjectionGPUContext): void;
/**
* @internal
* Returns a subdivided mesh for a given tile ID, covering 0..EXTENT range.
* @param context - WebGL context.
* @param tileID - The tile coordinates for which to return a mesh. Meshes for tiles that border the top/bottom mercator edge might include extra geometry for the north/south pole.
* @param hasBorder - When true, the mesh will also include a small border beyond the 0..EXTENT range.
* @param allowPoles - When true, the mesh will also include geometry to cover the north (south) pole, if the given tileID borders the mercator range's top (bottom) edge.
* @param usage - Specify the usage of the tile mesh, as different usages might use different levels of subdivision.
*/
getMeshFromTileID(context: Context, tileID: CanonicalTileID, hasBorder: boolean, allowPoles: boolean, usage: TileMeshUsage): Mesh;
/**
* @internal
* Recalculates the projection state based on the current evaluation parameters.
* @param params - Evaluation parameters.
*/
recalculate(params: EvaluationParameters): void;
/**
* @internal
* Returns true if the projection is currently transitioning between two states.
*/
hasTransition(): boolean;
/**
* @internal
* Sets the error query latidude in degrees
*/
setErrorQueryLatitudeDegrees(value: number);
}