diff --git a/src/webgldrawer.js b/src/webgldrawer.js index 0489eecb..bd712f28 100644 --- a/src/webgldrawer.js +++ b/src/webgldrawer.js @@ -92,6 +92,8 @@ this._renderingCanvas = null; this._backupCanvasDrawer = null; + this._imageSmoothingEnabled = true; // will be updated by setImageSmoothingEnabled + // Add listeners for events that require modifying the scene or camera this._boundToTileReady = ev => this._tileReadyHandler(ev); this._boundToImageUnloaded = ev => this._imageUnloadedHandler(ev); @@ -135,10 +137,7 @@ gl.bindRenderbuffer(gl.RENDERBUFFER, null); gl.bindFramebuffer(gl.FRAMEBUFFER, null); - let canvases = Array.from(this._TextureMap.keys()); - canvases.forEach(canvas => { - this._cleanupImageData(canvas); // deletes texture, removes from _TextureMap - }); + this._unloadTextures(); // Delete all our created resources gl.deleteBuffer(this._secondPass.bufferOutputPosition); @@ -486,11 +485,18 @@ // Public API required by all Drawer implementations /** - * Required by DrawerBase, but has no effect on WebGLDrawer. - * @param {Boolean} enabled + * Sets whether image smoothing is enabled or disabled + * @param {Boolean} enabled If true, uses gl.LINEAR as the TEXTURE_MIN_FILTER and TEXTURE_MAX_FILTER, otherwise gl.NEAREST. */ setImageSmoothingEnabled(enabled){ - // noop - this property does not impact WebGLDrawer + const changed = this._imageSmoothingEnabled !== enabled; + this._imageSmoothingEnabled = enabled; + if( changed ){ + // We need to unload all existing textures so they can be recreated with the new filter + this._unloadTextures(); + } + // trigger a re-draw + this.viewer.world.draw(); } /** @@ -600,6 +606,11 @@ } + // private + _textureFilter(){ + return this._imageSmoothingEnabled ? this._gl.LINEAR : this._gl.NEAREST; + } + // private _setupRenderer(){ let gl = this._gl; @@ -616,7 +627,7 @@ gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, this._renderToTexture); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this._renderingCanvas.width, this._renderingCanvas.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, this._textureFilter()); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); @@ -815,7 +826,7 @@ gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, this._renderToTexture); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, w, h, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, this._textureFilter()); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); @@ -955,8 +966,8 @@ // Set the parameters so we can render any size image. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, this._textureFilter()); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, this._textureFilter()); // Upload the image into the texture. this._uploadImageData(tileContext); @@ -980,6 +991,14 @@ }; } + // private + _unloadTextures(){ + let canvases = Array.from(this._TextureMap.keys()); + canvases.forEach(canvas => { + this._cleanupImageData(canvas); // deletes texture, removes from _TextureMap + }); + } + // private _uploadImageData(tileContext){ diff --git a/test/demo/drawercomparison.js b/test/demo/drawercomparison.js index bb96219b..16acc74e 100644 --- a/test/demo/drawercomparison.js +++ b/test/demo/drawercomparison.js @@ -193,6 +193,11 @@ function updateTiledImage(tiledImage, data, value, item){ tiledImage.setOpacity(Number(value)); } else if (field == 'flipped'){ tiledImage.setFlip($(item).prop('checked')); + } else if (field == 'smoothing'){ + const checked = $(item).prop('checked'); + viewer1.drawer.setImageSmoothingEnabled(checked); + viewer2.drawer.setImageSmoothingEnabled(checked); + $('[data-field=smoothing]').prop('checked', checked); } else if (field == 'cropped'){ if( $(item).prop('checked') ){ let scale = tiledImage.source.width; @@ -355,6 +360,7 @@ function makeImagePickerElement(key, label){ + `.replaceAll('data-image=""', `data-image="${key}"`).replace('__title__', label));