mirror of
https://github.com/openseadragon/openseadragon.git
synced 2024-11-21 20:56:09 +03:00
Modular webgl2 drawer: fix small bugs. Add drawer IDs to demo page urls to allow refreshing/direct running
This commit is contained in:
parent
e07745d790
commit
e3024deb46
@ -114,6 +114,30 @@ $.WebGL = class WebGL extends OpenSeadragon.DrawerBase {
|
||||
engine.init(size.x, size.y);
|
||||
this.viewer.addHandler("resize", this._resizeRenderer.bind(this));
|
||||
this.renderer = engine;
|
||||
this.renderer.setDataBlendingEnabled(true);
|
||||
|
||||
// const gl = this.renderer.gl;
|
||||
// this._renderToTexture = gl.createTexture();
|
||||
// gl.activeTexture(gl.TEXTURE0);
|
||||
// gl.bindTexture(gl.TEXTURE_2D, this._renderToTexture);
|
||||
// gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, size.x, size.y, 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_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||
// gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||
//
|
||||
// // set up the framebuffer for render-to-texture
|
||||
// this._glFrameBuffer = gl.createFramebuffer();
|
||||
// gl.bindFramebuffer(gl.FRAMEBUFFER, this._glFrameBuffer);
|
||||
// gl.framebufferTexture2D(
|
||||
// gl.FRAMEBUFFER,
|
||||
// gl.COLOR_ATTACHMENT0, // attach texture as COLOR_ATTACHMENT0
|
||||
// gl.TEXTURE_2D, // attach a 2D texture
|
||||
// this._renderToTexture, // the texture to attach
|
||||
// 0
|
||||
// );
|
||||
// gl.bindFramebuffer(gl.FRAMEBUFFER, this._glFrameBuffer);
|
||||
// gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this._renderToTexture, 0);
|
||||
|
||||
return engine.canvas;
|
||||
}
|
||||
|
||||
@ -136,23 +160,19 @@ $.WebGL = class WebGL extends OpenSeadragon.DrawerBase {
|
||||
let rotMatrix = $.Mat3.makeRotation(-viewport.rotation);
|
||||
let viewMatrix = scaleMatrix.multiply(rotMatrix).multiply(posMatrix);
|
||||
|
||||
this.renderer.clear();
|
||||
this.renderer.setDataBlendingEnabled(false);
|
||||
// const gl = this.renderer.gl;
|
||||
// gl.bindFramebuffer(gl.FRAMEBUFFER, this._glFrameBuffer);
|
||||
// clear the buffer to draw a new image
|
||||
// gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
|
||||
//iterate over tiled images and draw each one using a two-pass rendering pipeline if needed
|
||||
|
||||
let drawn = 0;
|
||||
|
||||
for (const tiledImage of tiledImages) {
|
||||
console.log("START TILED IMAGE");
|
||||
let tilesToDraw = tiledImage.getTilesToDraw();
|
||||
|
||||
if (tilesToDraw.length === 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (drawn === 1) {
|
||||
this.renderer.setDataBlendingEnabled(true);
|
||||
}
|
||||
// if (tilesToDraw.length === 0) {
|
||||
// break;
|
||||
// }
|
||||
|
||||
let overallMatrix = viewMatrix;
|
||||
let imageRotation = tiledImage.getRotation(true);
|
||||
@ -168,12 +188,15 @@ $.WebGL = class WebGL extends OpenSeadragon.DrawerBase {
|
||||
overallMatrix = viewMatrix.multiply(localMatrix);
|
||||
}
|
||||
|
||||
|
||||
//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++){
|
||||
const tile = tilesToDraw[tileIndex].tile;
|
||||
|
||||
console.log("TILE " + tile.level + "-" + tile.x + "_" + tile.y);
|
||||
|
||||
const matrix = this._getTileMatrix(tile, tiledImage, overallMatrix);
|
||||
shader.opacity.set(tile.opacity * tiledImage.opacity);
|
||||
|
||||
@ -205,8 +228,6 @@ $.WebGL = class WebGL extends OpenSeadragon.DrawerBase {
|
||||
tiles: tilesToDraw.map(info => info.tile),
|
||||
});
|
||||
}
|
||||
|
||||
drawn++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -144,7 +144,7 @@ $.WebGLModule = class extends $.EventSource {
|
||||
const options = {
|
||||
wrap: readGlProp("wrap", "MIRRORED_REPEAT"),
|
||||
magFilter: readGlProp("magFilter", "LINEAR"),
|
||||
minFilter: readGlProp("minFilter", "NEAREST"),
|
||||
minFilter: readGlProp("minFilter", "LINEAR"),
|
||||
dataLoader: contextOpts.dataLoader || "TEXTURE_2D"
|
||||
};
|
||||
this.webglContext = new Context(this, glContext, options);
|
||||
@ -592,9 +592,11 @@ $.WebGLModule = class extends $.EventSource {
|
||||
|
||||
setDataBlendingEnabled(enabled) {
|
||||
if (enabled) {
|
||||
// this.gl.enable(this.gl.BLEND);
|
||||
// this.gl.blendEquation(this.gl.FUNC_ADD);
|
||||
// this.gl.blendFuncSeparate(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA, this.gl.ONE, this.gl.ONE);
|
||||
this.gl.enable(this.gl.BLEND);
|
||||
this.gl.blendEquation(this.gl.FUNC_ADD);
|
||||
this.gl.blendFuncSeparate(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA, this.gl.ONE, this.gl.ONE);
|
||||
this.gl.blendFunc(this.gl.ONE, this.gl.ONE_MINUS_SRC_ALPHA);
|
||||
} else {
|
||||
this.gl.disable(this.gl.BLEND);
|
||||
}
|
||||
|
@ -185,7 +185,7 @@ $.WebGLModule.WebGL20 = class extends $.WebGLModule.WebGLImplementation {
|
||||
}
|
||||
|
||||
static create(canvas) {
|
||||
return canvas.getContext('webgl2', { premultipliedAlpha: false, alpha: true });
|
||||
return canvas.getContext('webgl2', { premultipliedAlpha: true, alpha: true });
|
||||
}
|
||||
|
||||
//todo try to implement on the global scope version-independntly
|
||||
@ -263,6 +263,7 @@ vec4 lid_${layer._index}_xo() {
|
||||
return `#version 300 es
|
||||
precision mediump float;
|
||||
precision mediump sampler2DArray;
|
||||
precision mediump sampler2D;
|
||||
|
||||
${this.texture.declare(shaderDataIndexToGlobalDataIndex)}
|
||||
uniform float pixel_size_in_fragments;
|
||||
@ -283,17 +284,7 @@ void show(vec4 color) {
|
||||
vec4 fg = _last_rendered_color;
|
||||
_last_rendered_color = color;
|
||||
vec4 pre_fg = vec4(fg.rgb * fg.a, fg.a);
|
||||
final_color = pre_fg + final_color * (1.0-fg.a);
|
||||
}
|
||||
|
||||
void finalize() {
|
||||
show(vec4(.0));
|
||||
|
||||
if (close(final_color.a, 0.0)) {
|
||||
final_color = vec4(0.);
|
||||
} else {
|
||||
final_color = vec4(final_color.rgb/final_color.a, final_color.a);
|
||||
}
|
||||
final_color = pre_fg + final_color;
|
||||
}
|
||||
|
||||
vec4 blend_equation(in vec4 foreground, in vec4 background) {
|
||||
@ -317,7 +308,8 @@ ${definition}
|
||||
void main() {
|
||||
${execution}
|
||||
|
||||
finalize();
|
||||
//blend last level
|
||||
show(vec4(.0));
|
||||
}`;
|
||||
}
|
||||
|
||||
|
@ -20,12 +20,23 @@
|
||||
<div id="contentDiv" class="openseadragon1"></div>
|
||||
<script type="text/javascript">
|
||||
|
||||
const url = new URL(window.location.href);
|
||||
let drawer = url.searchParams.get("drawer");
|
||||
if (!drawer) {
|
||||
drawer = 'canvas';
|
||||
url.searchParams.set('drawer', drawer);
|
||||
if ("undefined" !== typeof history.replaceState) {
|
||||
history.replaceState(null, window.location.title, url.toString());
|
||||
}
|
||||
}
|
||||
|
||||
var viewer = OpenSeadragon({
|
||||
// debugMode: true,
|
||||
id: "contentDiv",
|
||||
prefixUrl: "../../build/openseadragon/images/",
|
||||
tileSources: "../data/testpattern.dzi",
|
||||
showNavigator: true
|
||||
showNavigator: true,
|
||||
drawer:drawer,
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
@ -65,12 +65,12 @@
|
||||
<h2>Compare behavior of <strong>Context2d</strong> and <strong>WebGL</strong> drawers</h2>
|
||||
<div class="mirrored">
|
||||
<div>
|
||||
<h3>Context2d drawer (default in OSD <= 4.1.0)</h3>
|
||||
<h3 id="title-w1">Loading...</h3>
|
||||
<div id="canvasdrawer" class="viewer-container"></div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3>New WebGL drawer</h3>
|
||||
<h3 id="title-w2">Loading...</h3>
|
||||
<div id="webgl" class="viewer-container"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -13,6 +13,19 @@ const labels = {
|
||||
bblue: 'Blue B',
|
||||
duomo: 'Duomo',
|
||||
}
|
||||
const drawers = {
|
||||
canvas: "Context2d drawer (default in OSD <= 4.1.0)",
|
||||
webgl: "New WebGL drawer",
|
||||
universal_webgl: "New WebGL (Modular)"
|
||||
}
|
||||
|
||||
//Support drawer type from the url
|
||||
const url = new URL(window.location.href);
|
||||
const drawer1 = url.searchParams.get("left") || 'canvas';
|
||||
const drawer2 = url.searchParams.get("right") || 'webgl';
|
||||
|
||||
$("#title-w1").html(drawers[drawer1]);
|
||||
$("#title-w2").html(drawers[drawer2]);
|
||||
|
||||
//Double viewer setup for comparison - CanvasDrawer and WebGLDrawer
|
||||
// viewer1: canvas drawer
|
||||
@ -25,7 +38,7 @@ let viewer1 = window.viewer1 = OpenSeadragon({
|
||||
crossOriginPolicy: 'Anonymous',
|
||||
ajaxWithCredentials: false,
|
||||
// maxImageCacheCount: 30,
|
||||
drawer:'canvas',
|
||||
drawer:drawer1,
|
||||
blendTime:0
|
||||
});
|
||||
|
||||
@ -39,25 +52,23 @@ let viewer2 = window.viewer2 = OpenSeadragon({
|
||||
crossOriginPolicy: 'Anonymous',
|
||||
ajaxWithCredentials: false,
|
||||
// maxImageCacheCount: 30,
|
||||
drawer:'webgl',
|
||||
drawer:drawer2,
|
||||
blendTime:0,
|
||||
});
|
||||
|
||||
// viewer3: html drawer
|
||||
var viewer3 = window.viewer3 = OpenSeadragon({
|
||||
id: "htmldrawer",
|
||||
drawer:'html',
|
||||
blendTime:2,
|
||||
prefixUrl: "../../build/openseadragon/images/",
|
||||
minZoomImageRatio:0.01,
|
||||
customDrawer: OpenSeadragon.HTMLDrawer,
|
||||
tileSources: [sources['leaves'], sources['rainbow'], sources['duomo']],
|
||||
sequenceMode: true,
|
||||
crossOriginPolicy: 'Anonymous',
|
||||
ajaxWithCredentials: false
|
||||
});
|
||||
|
||||
|
||||
// // viewer3: html drawer, unused
|
||||
// var viewer3 = window.viewer3 = OpenSeadragon({
|
||||
// id: "htmldrawer",
|
||||
// drawer:'html',
|
||||
// blendTime:2,
|
||||
// prefixUrl: "../../build/openseadragon/images/",
|
||||
// minZoomImageRatio:0.01,
|
||||
// customDrawer: OpenSeadragon.HTMLDrawer,
|
||||
// tileSources: [sources['leaves'], sources['rainbow'], sources['duomo']],
|
||||
// sequenceMode: true,
|
||||
// crossOriginPolicy: 'Anonymous',
|
||||
// ajaxWithCredentials: false
|
||||
// });
|
||||
|
||||
|
||||
// Sync navigation of viewer1 and viewer 2
|
||||
@ -126,6 +137,8 @@ Object.keys(sources).forEach((key, index)=>{
|
||||
}
|
||||
})
|
||||
|
||||
$('#image-picker').append(makeComparisonSwitcher());
|
||||
|
||||
$('#image-picker input.toggle').on('change',function(){
|
||||
let data = $(this).data();
|
||||
if(this.checked){
|
||||
@ -288,6 +301,30 @@ function addTileSource(viewer, image, checkbox){
|
||||
}
|
||||
}
|
||||
|
||||
function getAvailableDrawerSelect(name, selectedDrawer) {
|
||||
return `
|
||||
<select name="${name}">
|
||||
${Object.entries(drawers).map(([k, v]) => {
|
||||
const selected = selectedDrawer === k ? "selected" : "";
|
||||
return `<option value="${k}" ${selected}>${v}</option>`;
|
||||
}).join("\n")}
|
||||
</select>`;
|
||||
}
|
||||
|
||||
function makeComparisonSwitcher() {
|
||||
const left = getAvailableDrawerSelect("left", drawer1),
|
||||
right = getAvailableDrawerSelect("right", drawer2);
|
||||
return `
|
||||
<div>
|
||||
Note: you can run the comparison with desired drawers like this: drawercomparison.html?left=[type]&right=[type]
|
||||
<form method="get">
|
||||
${left}
|
||||
${right}
|
||||
<button>Submit</button>
|
||||
</form>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
function makeImagePickerElement(key, label){
|
||||
return $(`<div class="image-options">
|
||||
<span class="ui-icon ui-icon-arrowthick-2-n-s"></span>
|
||||
@ -306,7 +343,6 @@ function makeImagePickerElement(key, label){
|
||||
<label>Composite: <select data-image="" data-field="composite"></select></label>
|
||||
<label>Wrap: <select data-image="" data-field="wrapping"></select></label>
|
||||
</div>
|
||||
|
||||
</div>`.replaceAll('data-image=""', `data-image="${key}"`).replace('__title__', label));
|
||||
|
||||
}
|
||||
|
@ -27,9 +27,7 @@
|
||||
<div>
|
||||
<label>Select a drawer: </label>
|
||||
<select id="select-drawer">
|
||||
<option value="canvas">Canvas</option>
|
||||
<option value="webgl">WebGL</option>
|
||||
<option value="html">HTML</option>
|
||||
|
||||
</select>
|
||||
<label>Num images: </label>
|
||||
<input id="input-number" type="number" value="1" min="1" step="1">
|
||||
|
@ -13,6 +13,14 @@ const labels = {
|
||||
bblue: 'Blue B',
|
||||
duomo: 'Duomo',
|
||||
}
|
||||
const drawers = {
|
||||
canvas: "Context2d drawer (default in OSD <= 4.1.0)",
|
||||
webgl: "New WebGL drawer",
|
||||
universal_webgl: "New WebGL (Modular)",
|
||||
html: ""
|
||||
}
|
||||
|
||||
|
||||
let viewer;
|
||||
|
||||
( function () {
|
||||
@ -408,6 +416,10 @@ function rStats ( settings ) {
|
||||
|
||||
_base = document.createElement( 'div' );
|
||||
_base.className = 'rs-base';
|
||||
_base.style.bottom = '0px';
|
||||
_base.style.right = '0px';
|
||||
_base.style.top = 'initial';
|
||||
_base.style.left = 'initial';
|
||||
_div = document.createElement( 'div' );
|
||||
_div.className = 'rs-container';
|
||||
_div.style.height = 'auto';
|
||||
@ -509,6 +521,8 @@ function rStats ( settings ) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
var glStats = function() {
|
||||
|
||||
var _rS = null;
|
||||
@ -898,16 +912,9 @@ Stats.Panel = function ( name, fg, bg ) {
|
||||
|
||||
// })();
|
||||
|
||||
|
||||
$('#create-drawer').on('click',function(){
|
||||
let drawerType = $('#select-drawer').val();
|
||||
let num = Math.floor($('#input-number').val());
|
||||
rS('other').start();
|
||||
run(drawerType, num);
|
||||
});
|
||||
|
||||
|
||||
function run(drawerType, num) {
|
||||
rS('other').start();
|
||||
|
||||
if(viewer){
|
||||
viewer.destroy();
|
||||
}
|
||||
@ -969,3 +976,28 @@ function makeTileSources(num){
|
||||
|
||||
}
|
||||
|
||||
const url = new URL(window.location.href);
|
||||
const drawer = url.searchParams.get("drawer");
|
||||
const numberOfSources = Number.parseInt(url.searchParams.get("sources")) || 1;
|
||||
|
||||
$('#create-drawer').on('click',function(){
|
||||
const drawer = $('#select-drawer').val();
|
||||
let num = Math.floor($('#input-number').val());
|
||||
|
||||
url.searchParams.set("drawer", drawer);
|
||||
url.searchParams.set("sources", num);
|
||||
if ("undefined" !== typeof history.replaceState) {
|
||||
history.replaceState(null, window.location.title, url.toString());
|
||||
}
|
||||
run(drawer, num);
|
||||
});
|
||||
|
||||
$('#input-number').val(numberOfSources);
|
||||
$("#select-drawer").html(Object.entries(drawers).map(([k, v]) => {
|
||||
const selected = drawer === k ? "selected" : "";
|
||||
return `<option value="${k}" ${selected}>${v}</option>`;
|
||||
}).join("\n"));
|
||||
if (drawer) {
|
||||
run(drawer, numberOfSources);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user