将大图片上传到webgl中的GPU

如何在不冻结浏览器的情况下使用webgl将大图像上传到GPU(想想高分辨率天空盒或纹理图集)?

我首先想到的是,是否有办法让texImage2D异步执行(将图像上传到GPU是IO-ish,对不对?),但是我找不到任何方法。 然后,我尝试使用texSubImage2D上传适合16毫秒时间窗口的小块(我瞄准60 fps)。 但texSubImage2D只有在传递ArrayBufferView时才会使用偏移量AND宽度/高度参数 - 传递Image对象时,只能指定偏移量,它会(我猜测)会上传整个图像。 我想首先将图像绘制到画布上(以将其作为缓冲区)与将整个图像上传到GPU一样慢。

下面是我的意思的一个最简单的例子:http://jsfiddle.net/2v63f/3/。 我花费大约130毫秒将这个图像上传到GPU。

与jsfiddle完全相同的代码:

var canvas = document.getElementById('can');
var gl = canvas.getContext('webgl');

var image = new Image();
image.crossOrigin = "anonymous";
//image.src = 'http://i.imgur.com/9Tq28Qj.jpg?1';
image.src = 'http://i.imgur.com/G0qL97y.jpg'
image.addEventListener('load', function () {
    var texture = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, texture);

    var now = performance.now();
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
    console.log(performance.now() - now);
});

引用的图像看起来是3840x1920

对于高分辨率的天空盒,通常可以放弃对alpha通道的需求,然后决定其他像素格式结构是否可以在质量和数据大小之间提供合理的折衷。

指定的RGBA编码意味着这将需要29,491,200字节的数据传输后图像解码。 我试图用RGB测试,放弃阿尔法,但看到了类似的111毫秒传输时间。 假设您可以在使用之前对图像进行预处理,并且只关心测量数据到GPU的数据传输时间,则可以对数据执行某种形式的有损编码或压缩,以减少需要的带宽量转让。

其中一种更为简单的编码方法是使用RGB 565将数据大小减半并将数据发送到芯片。这将以色彩范围为代价将数据大小减少到14,745,600字节。

var buff = new Uint16Array(image.width*image.height);
//encode image to buffer
//on texture load-time, perform the following call
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, image.width, image.height, 0, gl.RGB, gl.UNSIGNED_SHORT_5_6_5, buff);

假设您可以确认对S3TC扩展的支持(https://developer.mozilla.org/en-US/docs/Web/WebGL/Using_Extensions#WEBGL_compressed_texture_s3tc),您还可以存储和下载DXT1格式的纹理并减少内存传输需求降至3,686,400字节。 看起来任何形式的S3TC都会导致相同的RGB565色彩范围缩小。

var ext = (
  gl.getExtension("WEBGL_compressed_texture_s3tc") ||
  gl.getExtension("MOZ_WEBGL_compressed_texture_s3tc") ||
  gl.getExtension("WEBKIT_WEBGL_compressed_texture_s3tc")
);

gl.compressedTexImage2D(gl.TEXTURE_2D, 0, ext.COMPRESSED_RGB_S3TC_DXT1_EXT, image.width, image.height, 0, buff);

大多数块压缩提供近距离下降的图像质量,但允许在一定距离更丰富的图像。 如果您需要近距离拍摄高分辨率,则最初可以加载较低分辨率或压缩纹理,以用作较差的LOD远景,并且可以在接近所讨论的纹理时加载较高分辨率的较小子集。

在http://jsfiddle.net/zy8hkby3/2/的简单测试中,纹理 - 有效负载大小的降低可能会导致数据传输的时间需求呈指数级下降,但这很可能取决于GPU。

链接地址: http://www.djcxy.com/p/80633.html

上一篇: Uploading large images to the GPU in webgl

下一篇: Local storage browser for Google Cloud Storage and dev