Lazily create the WebGL helper

This commit is contained in:
Tim Schaub
2021-11-13 11:14:59 -07:00
parent 1d94477ed3
commit 0dfbedb099
10 changed files with 236 additions and 72 deletions

View File

@@ -41,7 +41,6 @@ export const WebGLWorkerMessageType = {
/**
* @typedef {Object} Options
* @property {string} [className='ol-layer'] A CSS class name to set to the canvas element.
* @property {Object<string,import("../../webgl/Helper").UniformValue>} [uniforms] Uniform definitions for the post process steps
* @property {Array<PostProcessesOptions>} [postProcesses] Post-processes definitions
*/
@@ -70,27 +69,73 @@ class WebGLLayerRenderer extends LayerRenderer {
*/
this.inversePixelTransform_ = createTransform();
/**
* @private
*/
this.postProcesses_ = options.postProcesses;
/**
* @private
*/
this.uniforms_ = options.uniforms;
/**
* @type {WebGLHelper}
* @protected
*/
this.helper = new WebGLHelper({
postProcesses: options.postProcesses,
uniforms: options.uniforms,
});
this.helper;
}
if (options.className !== undefined) {
this.helper.getCanvas().className = options.className;
removeHelper_() {
if (this.helper) {
this.helper.dispose();
delete this.helper;
}
}
/**
* Determine whether renderFrame should be called.
* @param {import("../../PluggableMap.js").FrameState} frameState Frame state.
* @return {boolean} Layer is ready to be rendered.
*/
prepareFrame(frameState) {
if (!this.helper && !!this.getLayer().getSource()) {
this.helper = new WebGLHelper({
postProcesses: this.postProcesses_,
uniforms: this.uniforms_,
});
const className = this.getLayer().getClassName();
if (className) {
this.helper.getCanvas().className = className;
}
this.afterHelperCreated();
}
return this.prepareFrameInternal(frameState);
}
/**
* @protected
*/
afterHelperCreated() {}
/**
* Determine whether renderFrame should be called.
* @param {import("../../PluggableMap.js").FrameState} frameState Frame state.
* @return {boolean} Layer is ready to be rendered.
* @protected
*/
prepareFrameInternal(frameState) {
return true;
}
/**
* Clean up.
*/
disposeInternal() {
this.helper.dispose();
delete this.helper;
this.removeHelper_();
super.disposeInternal();
}

View File

@@ -132,7 +132,6 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer {
uniforms[DefaultUniform.PROJECTION_MATRIX] = projectionMatrixTransform;
super(layer, {
className: options.className,
uniforms: uniforms,
postProcesses: options.postProcesses,
});
@@ -146,10 +145,21 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer {
DYNAMIC_DRAW
);
this.program_ = this.helper.getProgram(
options.fragmentShader,
options.vertexShader
);
/**
* @private
*/
this.vertexShader_ = options.vertexShader;
/**
* @private
*/
this.fragmentShader_ = options.fragmentShader;
/**
* @type {WebGLProgram}
* @private
*/
this.program_;
/**
* @type {boolean}
@@ -158,12 +168,21 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer {
this.hitDetectionEnabled_ =
options.hitFragmentShader && options.hitVertexShader ? true : false;
this.hitProgram_ =
this.hitDetectionEnabled_ &&
this.helper.getProgram(
options.hitFragmentShader,
options.hitVertexShader
);
/**
* @private
*/
this.hitVertexShader_ = options.hitVertexShader;
/**
* @private
*/
this.hitFragmentShader_ = options.hitFragmentShader;
/**
* @type {WebGLProgram}
* @private
*/
this.hitProgram_;
const customAttributes = options.attributes
? options.attributes.map(function (attribute) {
@@ -263,8 +282,7 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer {
* @type {WebGLRenderTarget}
* @private
*/
this.hitRenderTarget_ =
this.hitDetectionEnabled_ && new WebGLRenderTarget(this.helper);
this.hitRenderTarget_;
this.worker_ = createWebGLWorker();
this.worker_.addEventListener(
@@ -360,6 +378,22 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer {
);
}
afterHelperCreated() {
this.program_ = this.helper.getProgram(
this.fragmentShader_,
this.vertexShader_
);
if (this.hitDetectionEnabled_) {
this.hitProgram_ = this.helper.getProgram(
this.hitFragmentShader_,
this.hitVertexShader_
);
this.hitRenderTarget_ = new WebGLRenderTarget(this.helper);
}
}
/**
* @param {import("../../source/Vector.js").VectorSourceEvent} event Event.
* @private
@@ -436,11 +470,11 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer {
}
/**
* Determine whether render should be called.
* Determine whether renderFrame should be called.
* @param {import("../../PluggableMap.js").FrameState} frameState Frame state.
* @return {boolean} Layer is ready to be rendered.
*/
prepareFrame(frameState) {
prepareFrameInternal(frameState) {
const layer = this.getLayer();
const vectorSource = layer.getSource();
const viewState = frameState.viewState;

View File

@@ -103,7 +103,6 @@ function getRenderExtent(frameState, extent) {
* @property {string} fragmentShader Fragment shader source.
* @property {Object<string, import("../../webgl/Helper").UniformValue>} [uniforms] Additional uniforms
* made available to shaders.
* @property {string} [className='ol-layer'] A CSS class name to set to the canvas element.
* @property {number} [cacheSize=512] The texture cache size.
*/
@@ -120,7 +119,6 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
constructor(tileLayer, options) {
super(tileLayer, {
uniforms: options.uniforms,
className: options.className,
});
/**
@@ -154,10 +152,21 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
*/
this.tempSize_ = [0, 0];
this.program_ = this.helper.getProgram(
options.fragmentShader,
options.vertexShader
);
/**
* @type {WebGLProgram}
* @private
*/
this.program_;
/**
* @private
*/
this.vertexShader_ = options.vertexShader;
/**
* @private
*/
this.fragmentShader_ = options.fragmentShader;
/**
* Tiles are rendered as a quad with the following structure:
@@ -173,11 +182,11 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
*
* Triangle A: P0, P1, P3
* Triangle B: P1, P2, P3
*
* @private
*/
const indices = new WebGLArrayBuffer(ELEMENT_ARRAY_BUFFER, STATIC_DRAW);
indices.fromArray([0, 1, 3, 1, 2, 3]);
this.helper.flushBufferData(indices);
this.indices_ = indices;
this.indices_ = new WebGLArrayBuffer(ELEMENT_ARRAY_BUFFER, STATIC_DRAW);
this.indices_.fromArray([0, 1, 3, 1, 2, 3]);
const cacheSize = options.cacheSize !== undefined ? options.cacheSize : 512;
@@ -187,9 +196,22 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
*/
this.tileTextureCache_ = new LRUCache(cacheSize);
/**
* @type {number}
* @private
*/
this.renderedOpacity_ = NaN;
}
afterHelperCreated() {
this.program_ = this.helper.getProgram(
this.fragmentShader_,
this.vertexShader_
);
this.helper.flushBufferData(this.indices_);
}
/**
* @protected
* @param {import("../../Tile.js").default} tile Tile.
@@ -207,11 +229,11 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
}
/**
* Determine whether render should be called.
* Determine whether renderFrame should be called.
* @param {import("../../PluggableMap.js").FrameState} frameState Frame state.
* @return {boolean} Layer is ready to be rendered.
*/
prepareFrame(frameState) {
prepareFrameInternal(frameState) {
if (isEmpty(getRenderExtent(frameState, frameState.extent))) {
return false;
}