diff --git a/src/render/painter.ts b/src/render/painter.ts index 62397eb17a..90999af93f 100644 --- a/src/render/painter.ts +++ b/src/render/painter.ts @@ -79,6 +79,14 @@ export type RenderOptions = { isRenderingGlobe: boolean; }; +type RenderHookPhase = + | 'beforeOpaque' + | 'afterOpaque' + | 'beforeTranslucent' + | 'afterTranslucent'; + +type RenderHook = (painter: Painter, renderOptions: RenderOptions) => void; + /** * @internal * Initialize a new painter object. @@ -135,6 +143,8 @@ export class Painter { // every time the camera-matrix changes the terrain-facilitators will be redrawn. terrainFacilitator: {dirty: boolean; matrix: mat4; renderTime: number}; + _renderHooks: Map = new Map(); + constructor(gl: WebGLRenderingContext | WebGL2RenderingContext, transform: IReadonlyTransform) { this.context = new Context(gl); this.transform = transform; @@ -560,6 +570,7 @@ export class Painter { this._showOverdrawInspector = options.showOverdrawInspector; this.depthRangeFor3D = [0, 1 - ((style._order.length + 2) * this.numSublayers * this.depthEpsilon)]; + this._runRenderHooks('beforeOpaque',renderOptions); // Opaque pass =============================================== // Draw opaque layers top-to-bottom first. if (!this.renderToTexture) { @@ -575,6 +586,9 @@ export class Painter { } } + this._runRenderHooks('afterOpaque',renderOptions); + this._runRenderHooks('beforeTranslucent',renderOptions); + // Translucent pass =============================================== // Draw all other layers bottom-to-top. this.renderPass = 'translucent'; @@ -605,6 +619,8 @@ export class Painter { this.renderLayer(this, tileManager, layer, coords, renderOptions); } + this._runRenderHooks('afterTranslucent',renderOptions); + // Render atmosphere, only for Globe projection if (renderOptions.isRenderingGlobe) { drawAtmosphere(this, this.style.sky, this.style.light); @@ -843,4 +859,30 @@ export class Painter { const {drawingBufferWidth, drawingBufferHeight} = this.context.gl; return this.width !== drawingBufferWidth || this.height !== drawingBufferHeight; } + + /** + * + * @param phase + */ + _runRenderHooks(phase: RenderHookPhase,renderOptions: RenderOptions) { + const hooks = this._renderHooks.get(phase); + if (!hooks) return; + for (const hook of hooks) { + hook(this,renderOptions); + } + } + + /** + * + * @param phase + * @param hook + */ + addRenderHook(phase: RenderHookPhase, hook: RenderHook) { + let list = this._renderHooks.get(phase); + if (!list) { + list = []; + this._renderHooks.set(phase, list); + } + list.push(hook); + } }