我有一组~200 base64编码的PNG(全部来自一个共享的JSON文件),我想直接在循环中加载为WebGL纹理,而不必求助于回调/事件处理程序(用于更简单的代码和更少的事件处理开销)。有没有办法在Javascript中执行此操作?
我知道加载base64编码图像的规范方法是通过数据URI。但似乎设置src
对象的Image
属性实际上并不解码图像数据,而只是将其排队以进行异步加载(意味着将Image
对象作为WebGL纹理上传设置src
属性后失败;设置上传纹理的onload
处理程序成功。)
答案 0 :(得分:1)
为什么呢?你为什么要同步这样做?浏览器中的JavaScript不是为了同步运行而设计的。你将冻结浏览器并可能获得“此脚本执行时间太长”对话框。
异步不难做到,为什么不这样做呢?
var loadTextureFromImage = function(url, callback) {
// use cyan as the default color.
var initialColor = new Uint8Array([0,255,255,255]);
// make a texture with 1x1 pixels so we can use the texture immediately
// while we wait for the image to load
var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0,
gl.RGBA, gl.UNSIGNED_BYTE, initialColor);
var img = new Image();
img.onload = function() {
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
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.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
callback(img);
};
return tex;
};
var loadTexturesFromImages(listOfImages, callback) {
var numLeftToDownload = listOfImages.length;
var checkFinished = function() {
--numLeftToDownload;
if (numLeftToDownload == 0 && callback) {
callback();
}
};
return listOfImages.map(function(url) {
return loadTexturesFromImage(url, checkFinished);
});
};
以下是使用上述功能的一些代码
var imagesToLoad = [
"http://foo.com/image1.jpg",
"http://foo.com/image2.jpg",
"data:image/png;base64,iVBORw0KG...",
];
var textures = loadTexturesFromImages(imagesToLoad);
现在你可以开始渲染了。它们都将以青色呈现,并在下载/解码时更新到图像。
如果您想等到它们全部下载完毕,请提供回复loadTexturesFromImages
。
我想你问题的简短答案是,“不,你不能同步解码图像”。答案很长,如果你想同步解码它们you'll have to decode them yourself。但现在你回到上面提到的问题。也就是说,你将冻结浏览器,你的用户可能会收到一个对话框,询问他们是否要杀死该脚本。