Skip to content

Commit

Permalink
Switch to WebGL2
Browse files Browse the repository at this point in the history
  • Loading branch information
gberaudo committed Sep 14, 2023
1 parent aaf8038 commit e2b3236
Show file tree
Hide file tree
Showing 12 changed files with 68 additions and 56 deletions.
4 changes: 2 additions & 2 deletions examples/webgl-layer-swipe.html
Expand Up @@ -4,8 +4,8 @@
shortdesc: Cropping a WebGL tile layer
docs: >
The <code>prerender</code> and <code>postrender</code> events on a WebGL tile layer can be
used to manipulate the WebGL context before and after rendering. In this case, the
<a href="https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/scissor"><code>gl.scissor()</code></a>
used to manipulate the WebGL context before and after rendering. In this case, the
<a href="https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/scissor"><code>gl.scissor()</code></a>
method is called to clip the top layer based on the position of a slider.
tags: "swipe, webgl"
cloak:
Expand Down
14 changes: 14 additions & 0 deletions src/ol/layer/WebGLTile.js
Expand Up @@ -131,6 +131,20 @@ function parseStyle(style, bandCount) {
if (style.color !== undefined) {
const color = expressionToGlsl(context, style.color, ValueTypes.COLOR);
pipeline.push(`color = ${color};`);
} else if (bandCount === 1) {
const color = expressionToGlsl(
context,
['array', ['band', 1], ['band', 1], ['band', 1], 1],
ValueTypes.COLOR
);
pipeline.push(`color = ${color};`);
} else if (bandCount === 2) {
const color = expressionToGlsl(
context,
['array', ['band', 1], ['band', 1], ['band', 1], ['band', 2]],
ValueTypes.COLOR
);
pipeline.push(`color = ${color};`);
}

if (style.contrast !== undefined) {
Expand Down
4 changes: 2 additions & 2 deletions src/ol/render/Event.js
Expand Up @@ -10,7 +10,7 @@ class RenderEvent extends Event {
* @param {import("../transform.js").Transform} [inversePixelTransform] Transform for
* CSS pixels to rendered pixels.
* @param {import("../Map.js").FrameState} [frameState] Frame state.
* @param {?(CanvasRenderingContext2D|WebGLRenderingContext)} [context] Context.
* @param {?(CanvasRenderingContext2D|WebGL2RenderingContext)} [context] Context.
*/
constructor(type, inversePixelTransform, frameState, context) {
super(type);
Expand All @@ -34,7 +34,7 @@ class RenderEvent extends Event {
* Canvas context. Not available when the event is dispatched by the map. For Canvas 2D layers,
* the context will be the 2D rendering context. For WebGL layers, the context will be the WebGL
* context.
* @type {CanvasRenderingContext2D|WebGLRenderingContext|undefined}
* @type {CanvasRenderingContext2D|WebGL2RenderingContext|undefined}
* @api
*/
this.context = context;
Expand Down
10 changes: 5 additions & 5 deletions src/ol/renderer/webgl/Layer.js
Expand Up @@ -80,7 +80,7 @@ class WebGLLayerRenderer extends LayerRenderer {
}

/**
* @param {WebGLRenderingContext} context The WebGL rendering context.
* @param {WebGL2RenderingContext} context The WebGL rendering context.
* @param {import("../../Map.js").FrameState} frameState Frame state.
* @protected
*/
Expand All @@ -98,7 +98,7 @@ class WebGLLayerRenderer extends LayerRenderer {
}

/**
* @param {WebGLRenderingContext} context The WebGL rendering context.
* @param {WebGL2RenderingContext} context The WebGL rendering context.
* @param {import("../../Map.js").FrameState} frameState Frame state.
* @protected
*/
Expand Down Expand Up @@ -216,7 +216,7 @@ class WebGLLayerRenderer extends LayerRenderer {

/**
* @param {import("../../render/EventType.js").default} type Event type.
* @param {WebGLRenderingContext} context The rendering context.
* @param {WebGL2RenderingContext} context The rendering context.
* @param {import("../../Map.js").FrameState} frameState Frame state.
* @private
*/
Expand Down Expand Up @@ -245,7 +245,7 @@ class WebGLLayerRenderer extends LayerRenderer {
}

/**
* @param {WebGLRenderingContext} context The rendering context.
* @param {WebGL2RenderingContext} context The rendering context.
* @param {import("../../Map.js").FrameState} frameState Frame state.
* @protected
*/
Expand All @@ -254,7 +254,7 @@ class WebGLLayerRenderer extends LayerRenderer {
}

/**
* @param {WebGLRenderingContext} context The rendering context.
* @param {WebGL2RenderingContext} context The rendering context.
* @param {import("../../Map.js").FrameState} frameState Frame state.
* @protected
*/
Expand Down
23 changes: 7 additions & 16 deletions src/ol/webgl.js
Expand Up @@ -79,16 +79,10 @@ export const FLOAT = 0x1406;
/** end of goog.webgl constants
*/

/**
* @const
* @type {Array<string>}
*/
const CONTEXT_IDS = ['experimental-webgl', 'webgl', 'webkit-3d', 'moz-webgl'];

/**
* @param {HTMLCanvasElement} canvas Canvas.
* @param {Object} [attributes] Attributes.
* @return {WebGLRenderingContext} WebGL rendering context.
* @return {WebGL2RenderingContext} WebGL rendering context.
*/
export function getContext(canvas, attributes) {
attributes = Object.assign(
Expand All @@ -98,16 +92,13 @@ export function getContext(canvas, attributes) {
},
attributes
);
const ii = CONTEXT_IDS.length;
for (let i = 0; i < ii; ++i) {
try {
const context = canvas.getContext(CONTEXT_IDS[i], attributes);
if (context) {
return /** @type {!WebGLRenderingContext} */ (context);
}
} catch (e) {
// pass
try {
const context = canvas.getContext('webgl2', attributes);
if (context) {
return /** @type {!WebGL2RenderingContext} */ (context);
}
} catch (e) {
// pass
}
return null;
}
Expand Down
2 changes: 1 addition & 1 deletion src/ol/webgl/Buffer.js
Expand Up @@ -33,7 +33,7 @@ export const BufferUsage = {
* * A plain array using `#fromArray(array)`
*
* Note:
* See the documentation of [WebGLRenderingContext.bufferData](https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bufferData)
* See the documentation of [WebGL2RenderingContext.bufferData](https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/bufferData)
* for more info on buffer usage.
*/
class WebGLArrayBuffer {
Expand Down
14 changes: 7 additions & 7 deletions src/ol/webgl/Helper.js
Expand Up @@ -111,7 +111,7 @@ export const AttributeType = {

/**
* @typedef {Object} CanvasCacheItem
* @property {WebGLRenderingContext} context The context of this canvas.
* @property {WebGL2RenderingContext} context The context of this canvas.
* @property {number} users The count of users of this canvas.
*/

Expand Down Expand Up @@ -141,7 +141,7 @@ function getUniqueCanvasCacheKey() {

/**
* @param {string} key The cache key for the canvas.
* @return {WebGLRenderingContext} The canvas.
* @return {WebGL2RenderingContext} The canvas.
*/
function getOrCreateContext(key) {
let cacheItem = canvasCache[key];
Expand Down Expand Up @@ -274,7 +274,7 @@ function releaseCanvas(key) {
* Attributes are used to specify these uses. Specify the attribute names with
* {@link module:ol/webgl/Helper~WebGLHelper#enableAttributes} (see code snippet below).
*
* Please note that you will have to specify the type and offset of the attributes in the data array. You can refer to the documentation of [WebGLRenderingContext.vertexAttribPointer](https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/vertexAttribPointer) for more explanation.
* Please note that you will have to specify the type and offset of the attributes in the data array. You can refer to the documentation of [WebGL2RenderingContext.vertexAttribPointer](https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/vertexAttribPointer) for more explanation.
* ```js
* // here we indicate that the data array has the following structure:
* // [posX, posY, offsetX, offsetY, texCoordU, texCoordV, posX, posY, ...]
Expand Down Expand Up @@ -335,7 +335,7 @@ class WebGLHelper extends Disposable {

/**
* @private
* @type {WebGLRenderingContext}
* @type {WebGL2RenderingContext}
*/
this.gl_ = getOrCreateContext(this.canvasCacheKey_);

Expand Down Expand Up @@ -670,8 +670,8 @@ class WebGLHelper extends Disposable {
/**
* Apply the successive post process passes which will eventually render to the actual canvas.
* @param {import("../Map.js").FrameState} frameState current frame state
* @param {function(WebGLRenderingContext, import("../Map.js").FrameState):void} [preCompose] Called before composing.
* @param {function(WebGLRenderingContext, import("../Map.js").FrameState):void} [postCompose] Called before composing.
* @param {function(WebGL2RenderingContext, import("../Map.js").FrameState):void} [preCompose] Called before composing.
* @param {function(WebGL2RenderingContext, import("../Map.js").FrameState):void} [postCompose] Called before composing.
*/
finalizeDraw(frameState, preCompose, postCompose) {
// apply post processes using the next one as target
Expand Down Expand Up @@ -701,7 +701,7 @@ class WebGLHelper extends Disposable {

/**
* Get the WebGL rendering context
* @return {WebGLRenderingContext} The rendering context.
* @return {WebGL2RenderingContext} The rendering context.
*/
getGL() {
return this.gl_;
Expand Down
2 changes: 1 addition & 1 deletion src/ol/webgl/PaletteTexture.js
Expand Up @@ -19,7 +19,7 @@ class PaletteTexture {
}

/**
* @param {WebGLRenderingContext} gl Rendering context.
* @param {WebGL2RenderingContext} gl Rendering context.
* @return {WebGLTexture} The texture.
*/
getTexture(gl) {
Expand Down
20 changes: 10 additions & 10 deletions src/ol/webgl/PostProcessingPass.js
Expand Up @@ -6,13 +6,13 @@ import {getUid} from '../util.js';

const DEFAULT_VERTEX_SHADER = `
precision mediump float;
attribute vec2 a_position;
varying vec2 v_texCoord;
varying vec2 v_screenCoord;
uniform vec2 u_screenSize;
void main() {
v_texCoord = a_position * 0.5 + 0.5;
v_screenCoord = v_texCoord * u_screenSize;
Expand All @@ -22,20 +22,20 @@ const DEFAULT_VERTEX_SHADER = `

const DEFAULT_FRAGMENT_SHADER = `
precision mediump float;
uniform sampler2D u_image;
uniform float u_opacity;
varying vec2 v_texCoord;
void main() {
gl_FragColor = texture2D(u_image, v_texCoord) * u_opacity;
}
`;

/**
* @typedef {Object} Options
* @property {WebGLRenderingContext} webGlContext WebGL context; mandatory.
* @property {WebGL2RenderingContext} webGlContext WebGL context; mandatory.
* @property {number} [scaleRatio] Scale ratio; if < 1, the post process will render to a texture smaller than
* the main canvas that will then be sampled up (useful for saving resource on blur steps).
* @property {string} [vertexShader] Vertex shader source
Expand Down Expand Up @@ -177,7 +177,7 @@ class WebGLPostProcessingPass {

/**
* Get the WebGL rendering context
* @return {WebGLRenderingContext} The rendering context.
* @return {WebGL2RenderingContext} The rendering context.
*/
getGL() {
return this.gl_;
Expand Down Expand Up @@ -261,8 +261,8 @@ class WebGLPostProcessingPass {
* Render to the next postprocessing pass (or to the canvas if final pass).
* @param {import("../Map.js").FrameState} frameState current frame state
* @param {WebGLPostProcessingPass} [nextPass] Next pass, optional
* @param {function(WebGLRenderingContext, import("../Map.js").FrameState):void} [preCompose] Called before composing.
* @param {function(WebGLRenderingContext, import("../Map.js").FrameState):void} [postCompose] Called before composing.
* @param {function(WebGL2RenderingContext, import("../Map.js").FrameState):void} [preCompose] Called before composing.
* @param {function(WebGL2RenderingContext, import("../Map.js").FrameState):void} [postCompose] Called before composing.
*/
apply(frameState, nextPass, preCompose, postCompose) {
const gl = this.getGL();
Expand Down
23 changes: 15 additions & 8 deletions src/ol/webgl/TileTexture.js
Expand Up @@ -13,7 +13,7 @@ import {createCanvasContext2D} from '../dom.js';
import {toSize} from '../size.js';

/**
* @param {WebGLRenderingContext} gl The WebGL context.
* @param {WebGL2RenderingContext} gl The WebGL context.
* @param {WebGLTexture} texture The texture.
* @param {boolean} interpolate Interpolate when resampling.
*/
Expand All @@ -27,7 +27,7 @@ function bindAndConfigure(gl, texture, interpolate) {
}

/**
* @param {WebGLRenderingContext} gl The WebGL context.
* @param {WebGL2RenderingContext} gl The WebGL context.
* @param {WebGLTexture} texture The texture.
* @param {import("../DataTile.js").ImageLike} image The image.
* @param {boolean} interpolate Interpolate when resampling.
Expand Down Expand Up @@ -57,9 +57,9 @@ function uploadDataTexture(
const gl = helper.getGL();
let textureType;
let canInterpolate;
if (data instanceof Float32Array) {
const isFloat32 = data instanceof Float32Array;
if (isFloat32) {
textureType = gl.FLOAT;
helper.getExtension('OES_texture_float');
const extension = helper.getExtension('OES_texture_float_linear');
canInterpolate = extension !== null;
} else {
Expand All @@ -78,21 +78,28 @@ function uploadDataTexture(
unpackAlignment = 2;
}

// See https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/texImage2D
// And https://registry.khronos.org/webgl/specs/latest/2.0/
// "Sized internal formats are supported in WebGL 2.0 and internalformat is no longer required to be the same as format"
let format;
let internalFormat;
switch (bandCount) {
case 1: {
format = gl.LUMINANCE;
internalFormat = isFloat32 ? gl.R32F : gl.LUMINANCE;
format = isFloat32 ? gl.RED : gl.LUMINANCE;
break;
}
case 2: {
format = gl.LUMINANCE_ALPHA;
internalFormat = isFloat32 ? gl.RG32F : gl.LUMINANCE_ALPHA;
format = isFloat32 ? gl.RG : gl.LUMINANCE_ALPHA;
break;
}
case 3: {
format = gl.RGB;
internalFormat = isFloat32 ? gl.RGB32F : gl.RGB;
break;
}
case 4: {
internalFormat = isFloat32 ? gl.RGBA32F : gl.RGBA;
format = gl.RGBA;
break;
}
Expand All @@ -106,7 +113,7 @@ function uploadDataTexture(
gl.texImage2D(
gl.TEXTURE_2D,
0,
format,
internalFormat,
size[0],
size[1],
0,
Expand Down
6 changes: 3 additions & 3 deletions test/browser/spec/ol/layer/WebGLTile.test.js
Expand Up @@ -581,7 +581,7 @@ describe('ol/layer/WebGLTile', function () {
it('dispatches a precompose event with WebGL context', (done) => {
let called = false;
layer.on('precompose', (event) => {
expect(event.context).to.be.a(WebGLRenderingContext);
expect(event.context).to.be.a(WebGL2RenderingContext);
called = true;
});

Expand All @@ -596,7 +596,7 @@ describe('ol/layer/WebGLTile', function () {
it('dispatches a prerender event with WebGL context and inverse pixel transform', (done) => {
let called = false;
layer.on('prerender', (event) => {
expect(event.context).to.be.a(WebGLRenderingContext);
expect(event.context).to.be.a(WebGL2RenderingContext);
const mapSize = event.frameState.size;
const bottomLeft = getRenderPixel(event, [0, mapSize[1]]);
expect(bottomLeft).to.eql([0, 0]);
Expand All @@ -614,7 +614,7 @@ describe('ol/layer/WebGLTile', function () {
it('dispatches a postrender event with WebGL context and inverse pixel transform', (done) => {
let called = false;
layer.on('postrender', (event) => {
expect(event.context).to.be.a(WebGLRenderingContext);
expect(event.context).to.be.a(WebGL2RenderingContext);
const mapSize = event.frameState.size;
const topRight = getRenderPixel(event, [mapSize[1], 0]);
const pixelRatio = event.frameState.pixelRatio;
Expand Down
2 changes: 1 addition & 1 deletion test/browser/spec/ol/webgl/helper.test.js
Expand Up @@ -80,7 +80,7 @@ describe('ol/webgl/WebGLHelper', function () {
});

it('initialized WebGL context & canvas', function () {
expect(h.getGL() instanceof WebGLRenderingContext).to.eql(true);
expect(h.getGL() instanceof WebGL2RenderingContext).to.eql(true);
expect(h.getCanvas() instanceof HTMLCanvasElement).to.eql(true);
});

Expand Down

0 comments on commit e2b3236

Please sign in to comment.