diff --git a/src/js/libpannellum.js b/src/js/libpannellum.js index 880c81f..8609dd0 100644 --- a/src/js/libpannellum.js +++ b/src/js/libpannellum.js @@ -382,6 +382,7 @@ function Renderer(container) { program.texCoordLocation = gl.getAttribLocation(program, 'a_texCoord'); gl.enableVertexAttribArray(program.texCoordLocation); + const promises = []; if (imageType != 'multires') { // Provide texture coordinates for rectangle if (!texCoordBuffer) @@ -421,52 +422,40 @@ function Renderer(container) { // Upload images to texture depending on type if (imageType == 'cubemap') { // Load all six sides of the cube map - gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image[1]); - gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image[3]); - gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image[4]); - gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image[5]); - gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image[0]); - gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image[2]); + promises.push(fetch(image[1].src).then(res => res.blob()).then(blob => createImageBitmap(blob)).then(bitmap => gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, bitmap)).finally(() => URL.revokeObjectURL(image[1].src))); + promises.push(fetch(image[3].src).then(res => res.blob()).then(blob => createImageBitmap(blob)).then(bitmap => gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, bitmap)).finally(() => URL.revokeObjectURL(image[3].src))); + promises.push(fetch(image[4].src).then(res => res.blob()).then(blob => createImageBitmap(blob)).then(bitmap => gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, bitmap)).finally(() => URL.revokeObjectURL(image[4].src))); + promises.push(fetch(image[5].src).then(res => res.blob()).then(blob => createImageBitmap(blob)).then(bitmap => gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, bitmap)).finally(() => URL.revokeObjectURL(image[5].src))); + promises.push(fetch(image[0].src).then(res => res.blob()).then(blob => createImageBitmap(blob)).then(bitmap => gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, bitmap)).finally(() => URL.revokeObjectURL(image[0].src))); + promises.push(fetch(image[2].src).then(res => res.blob()).then(blob => createImageBitmap(blob)).then(bitmap => gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, bitmap)).finally(() => URL.revokeObjectURL(image[2].src))); } else { - if (image.width <= maxWidth) { - gl.uniform1i(gl.getUniformLocation(program, 'u_splitImage'), 0); - // Upload image to the texture - gl.texImage2D(glBindType, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image); - } else { - // Image needs to be split into two parts due to texture size limits - gl.uniform1i(gl.getUniformLocation(program, 'u_splitImage'), 1); - - // Draw image on canvas - var cropCanvas = document.createElement('canvas'); - cropCanvas.width = image.width / 2; - cropCanvas.height = image.height; - var cropContext = cropCanvas.getContext('2d'); - cropContext.drawImage(image, 0, 0); + const blobPromise = fetch(image.src).then(res => res.blob()); + blobPromise.finally(() => URL.revokeObjectURL(image.src)); - // Upload first half of image to the texture - var cropImage = cropContext.getImageData(0, 0, image.width / 2, image.height); - gl.texImage2D(glBindType, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, cropImage); + // Split the image into two parts to split the blocking time of the main thread + gl.uniform1i(gl.getUniformLocation(program, 'u_splitImage'), 1); + // Upload first half of image to the texture + promises.push(blobPromise.then(blob => createImageBitmap(blob, 0, 0, image.width / 2, image.height)).then(bitmap => gl.texImage2D(glBindType, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, bitmap))); + // Upload second half of image to the texture + promises.push(blobPromise.then(blob => createImageBitmap(blob, image.width / 2, 0, image.width / 2, image.height)).then(bitmap => { // Create and bind texture for second half of image program.texture2 = gl.createTexture(); gl.activeTexture(gl.TEXTURE1); gl.bindTexture(glBindType, program.texture2); gl.uniform1i(gl.getUniformLocation(program, 'u_image1'), 1); - // Upload second half of image to the texture - cropContext.drawImage(image, -image.width / 2, 0); - cropImage = cropContext.getImageData(0, 0, image.width / 2, image.height); - gl.texImage2D(glBindType, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, cropImage); - // Set parameters for rendering any size gl.texParameteri(glBindType, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(glBindType, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texParameteri(glBindType, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(glBindType, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texImage2D(glBindType, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, bitmap); + // Reactivate first texture unit gl.activeTexture(gl.TEXTURE0); - } + })); } // Set parameters for rendering any size @@ -521,7 +510,7 @@ function Renderer(container) { throw {type: 'webgl error'}; } - callback(); + Promise.all(promises).then(() => callback()); }; /**