From 31f9a7110918b667932d4c28d8a4fee69d9390ca Mon Sep 17 00:00:00 2001 From: Aiosa Date: Wed, 27 Sep 2023 15:16:23 +0200 Subject: [PATCH] Working tiledimage-level transparency in a single pass. --- src/webgl/drawer.js | 25 +++++++++++++++++++++---- src/webgl/renderer.js | 8 +++++--- src/webgl/webGLContext.js | 9 ++++++--- 3 files changed, 32 insertions(+), 10 deletions(-) diff --git a/src/webgl/drawer.js b/src/webgl/drawer.js index 0da257b2..d0bbee3d 100644 --- a/src/webgl/drawer.js +++ b/src/webgl/drawer.js @@ -97,6 +97,11 @@ $.WebGL = class WebGL extends OpenSeadragon.DrawerBase { const engine = new $.WebGLModule($.extend(this.options, { uniqueId: "openseadragon", + "2.0": { + canvasOptions: { + stencil: true + } + } })); engine.addRenderingSpecifications({ @@ -116,7 +121,7 @@ $.WebGL = class WebGL extends OpenSeadragon.DrawerBase { this.renderer = engine; this.renderer.setDataBlendingEnabled(true); - // const gl = this.renderer.gl; + const gl = this.renderer.gl; // this._renderToTexture = gl.createTexture(); // gl.activeTexture(gl.TEXTURE0); // gl.bindTexture(gl.TEXTURE_2D, this._renderToTexture); @@ -138,6 +143,10 @@ $.WebGL = class WebGL extends OpenSeadragon.DrawerBase { // gl.bindFramebuffer(gl.FRAMEBUFFER, this._glFrameBuffer); // gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this._renderToTexture, 0); + gl.enable(gl.STENCIL_TEST); + gl.stencilMask(0xff); + gl.stencilFunc(gl.GREATER, 1, 0xff); + gl.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE); return engine.canvas; } @@ -153,10 +162,11 @@ $.WebGL = class WebGL extends OpenSeadragon.DrawerBase { zoom: this.viewport.getZoom(true) }; - let flipMultiplier = this.viewport.flipped ? -1 : 1; + + // let flipMultiplier = this.viewport.flipped ? -1 : 1; // calculate view matrix for viewer let posMatrix = $.Mat3.makeTranslation(-viewport.center.x, -viewport.center.y); - let scaleMatrix = $.Mat3.makeScaling(2 / viewport.bounds.width * flipMultiplier, -2 / viewport.bounds.height); + let scaleMatrix = $.Mat3.makeScaling(2 / viewport.bounds.width, -2 / viewport.bounds.height); let rotMatrix = $.Mat3.makeRotation(-viewport.rotation); let viewMatrix = scaleMatrix.multiply(rotMatrix).multiply(posMatrix); @@ -169,6 +179,12 @@ $.WebGL = class WebGL extends OpenSeadragon.DrawerBase { for (const tiledImage of tiledImages) { let tilesToDraw = tiledImage.getTilesToDraw(); + if (tilesToDraw.length === 0) { + continue; + } + + gl.clear(gl.STENCIL_BUFFER_BIT); + let overallMatrix = viewMatrix; let imageRotation = tiledImage.getRotation(true); // if needed, handle the tiledImage being rotated @@ -187,7 +203,7 @@ $.WebGL = class WebGL extends OpenSeadragon.DrawerBase { //todo better access to the rendering context const shader = this.renderer.specification(0).shaders.renderShader._renderContext; // iterate over tiles and add data for each one to the buffers - for (let tileIndex = 0; tileIndex < tilesToDraw.length; tileIndex++){ + for (let tileIndex = tilesToDraw.length - 1; tileIndex >= 0; tileIndex--){ const tile = tilesToDraw[tileIndex].tile; const matrix = this._getTileMatrix(tile, tiledImage, overallMatrix); @@ -264,6 +280,7 @@ $.WebGL = class WebGL extends OpenSeadragon.DrawerBase { let localMatrix = t1.multiply($.Mat3.makeScaling(-1, 1)).multiply(t2); matrix = matrix.multiply(localMatrix); } + let overallMatrix = viewMatrix.multiply(matrix); return overallMatrix.values; } diff --git a/src/webgl/renderer.js b/src/webgl/renderer.js index 7be24859..35d94f76 100644 --- a/src/webgl/renderer.js +++ b/src/webgl/renderer.js @@ -81,7 +81,6 @@ $.WebGLModule = class extends $.EventSource { this.visualisationInUse = function(visualisation) { }; this.visualisationChanged = function(oldVis, newVis) { }; - /** * Debug mode. * @member {boolean} @@ -124,12 +123,15 @@ $.WebGLModule = class extends $.EventSource { try { const canvas = document.createElement("canvas"); for (let version of [this.webGlPreferredVersion, "2.0", "1.0"]) { + const contextOpts = incomingOptions[version] || {}; + const Context = $.WebGLModule.determineContext(version); - let glContext = Context && Context.create(canvas); + //todo documment this + let glContext = Context && Context.create(canvas, contextOpts.canvasOptions || {}); if (glContext) { this.gl = glContext; - const contextOpts = incomingOptions[version] || {}; + const readGlProp = function(prop, defaultValue) { return glContext[contextOpts[prop] || defaultValue] || glContext[defaultValue]; }; diff --git a/src/webgl/webGLContext.js b/src/webgl/webGLContext.js index 8056836c..4e92f4ad 100644 --- a/src/webgl/webGLContext.js +++ b/src/webgl/webGLContext.js @@ -60,9 +60,10 @@ $.WebGLModule.WebGLImplementation = class { /** * Static context creation (to avoid class instantiation in case of missing support) * @param canvas + * @param options desired options used in the canvas webgl context creation * @return {WebGLRenderingContextBase} //todo base is not common to all, remove from docs */ - static create(canvas) { + static create(canvas, options) { throw("::create() must be implemented!"); } @@ -184,8 +185,10 @@ $.WebGLModule.WebGL20 = class extends $.WebGLModule.WebGLImplementation { return "2.0"; } - static create(canvas) { - return canvas.getContext('webgl2', { premultipliedAlpha: true, alpha: true }); + static create(canvas, options) { + options.alpha = true; + options.premultipliedAlpha = true; + return canvas.getContext('webgl2', options); } //todo try to implement on the global scope version-independntly