WebGL 上的错误 "Tex image TEXTURE_2D level 0 is incurring lazy initialization"

Error "Tex image TEXTURE_2D level 0 is incurring lazy initialization" on WebGL

我在 WebGL 上收到错误消息:Error: WebGL warning: drawElements: Tex image TEXTURE_2D level 0 is incurring lazy initialization.,我想知道它的实际含义。

惰性初始化怎么会成为单线程应用程序中的一个问题呢?我将其理解为当您在 getter?

中初始化变量时

我试着寻找我的错误信息,但没有真正找到任何有用的信息。

这是我处理纹理的代码:

            const images = await Promise.all(model.maps.map(map => new Promise((resolve, reject) => {
                const image = new Image();

                image.src = map;
                image.onload = event => {
                    const texture = gl.createTexture();

                    gl.bindTexture(gl.TEXTURE_2D, texture);
                    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, image.width, image.height, 0, gl.RGBA, gl.FLOAT, null);
                    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
                    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
                    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.bindTexture(gl.TEXTURE_2D, null);

                    resolve(texture);
                };

                image.onerror = error => {
                    console.log(error);
                    resolve(null);
                };
            })));

我绘制函数的相关部分基本上是:

gl.bindTexture(gl.TEXTURE_2D, textures[material.textureIndex]);
gl.activeTexture(gl.TEXTURE0);
gl.drawElements(gl.TRIANGLES, material.faceCount * 3, gl.UNSIGNED_SHORT, drawnCount);

话虽如此,如果我使用 6 参数语法:gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.FLOAT, image); 则此错误消息不再显示,我设法正确呈现。

这不是错误。这是一个警告。

Error: WebGL warning ...

前面写着"Error"真是太迷惑了,但即使只写了"warning"我也争论了很久,这是不好的警告。

警告是 WebGL 需要做一些重要的工作。

当你制作一个纹理并且你没有传递任何数据时,你将 null 作为最后一个参数传递给 texImage2D,这意味着在某些时候 WebGL 必须清除纹理。假设纹理是 2048x2048 RGBA/UNSIGNED_BYTE。实际上,WebGL 必须分配 16meg 的 ram (2048x2048x4),将 16meg 的 ram 清除为 0,并在实际使用纹理之前调用 gl.texSubImage2D 将零放入纹理中。如果他们不这样做,纹理中将包含随机数据,这些数据可能是机密、密码、以前的图形内存(如照片)或其他任何内容。

因此,该警告告诉您发生了一些重要的工作。

此警告的问题是停止警告的解决方法比警告本身更糟糕。解决方法是让您自己清除纹理。为此,您需要像在 new Uint8Array(2048 * 2048 * 4) 中一样在 JavaScript 中分配 16meg。这意味着 JavaScript 正在分配 16 兆,它也清除了 16 兆。它还分配一个 Uint8Array 对象来跟踪该 16meg。该 Uint8Array 对象是一个复杂的 JavaScript 对象,可能是多个对象组合在一起的集合,例如还分配了一个 ArrayBuffer 对象。这些对象都有原型链,并且能够向它们添加属性和方法以及 getter 和 setter。 Uint8ArrayArrayBuffer 也必须被跟踪,以便它们可以在以后被垃圾收集,这意味着它们存在开销。更糟糕的是,如果浏览器是 Chrome 的多进程并且我相信 Firefox 正在努力,那么 JavaScript 中分配的 16meg 必须复制到 GPU 进程,这意味着首先 GPU 进程需要分配16meg 的 ram,数据必须从进程 运行 网页复制到 GPU 进程,以便它可以传递给图形驱动程序。更多的工作。

所以换句话说,让 Firefox 关闭它的警告实际上会使您的代码变慢并使用更多的内存,如果 firefox 只是默默地自行清除纹理。因此,为什么我说警告不应该存在

Firefox 的开发人员有这样的观点,即只要 WebGL 做了一些繁重的事情,他们就想给你一个警告。鉴于治愈方法会使您的代码更重,我不同意他们的 POV。 Chrome 不给出此警告。这也让开发人员感到困惑,因为他们认为自己做错了什么。他们没有做错任何事。

https://bugzilla.mozilla.org/show_bug.cgi?id=1478216

至于没有渲染的东西,在你发布的代码中你没有在纹理中放置任何东西,所以纹理当然是 0,0,0,0。