generateMipmap 完成了吗?

Is generateMipmap done?

在我的应用程序中,我为 6x4096x4096 立方体贴图纹理生成了 mipmap。接下来,我需要对该纹理进行一些其他随时间变化的变化。所有绘图都在 requestAnimationFrame 的循环内完成。

根据浏览器、设备等的不同,有时需要三个、有时四个甚至五个连续的循环帧才能最终生成这些 mipmap,我需要知道在哪个帧中已经完成了 mipmap。

所以问题是:如何检查由 WebGL 命令 "generateMipmap" 为 "TEXTURE_CUBE_MAP" 生成的 requestAnimationFrame 循环 mipmaps 在哪一帧准备好?是否有用于检查 "generateMipmap" 完成状态的标志?

generateMipmap 是一个 "synchronous" 调用。虽然浏览器可以尝试通过立即返回来优化它,但在生成 mip-levels 实际完成之前,第一次使用调用 generateMipmap 的纹理将确保 mip-levels'可以使用了。将其放入代码中:

const texture = gl.createTexture();
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, /* ... */);
gl.generateMipmap(gl.TEXTURE_2D);
gl.uniform1i(someSamplerUniform, 0);
gl.drawArrays(/* ... */); // Here WebGL implementation will make sure that
                          // mip-levels for tetxure are ready. If they aren't,
                          // this call will cause blocking.

如果改变贴图0mip-level的内容,需要重新调用generateMipmap

Here's 有关此行为的更多信息。

无法确定 generateMipmap 何时完成或需要多长时间。我会很惊讶它需要这么长时间,但如果关键是你想避免卡顿,一个解决方案就是制作你自己的 mips。这样你就可以每帧​​每张脸上传一个lod,甚至在 更小的增量。

另一种可能的解决方案,但可能只适用于 Chrome,就是猜测并等待几帧代码,如

gl.generateMipmap(...);
gl.flush();  // make sure the previous command will be executed

// now do something to wait 4 frames like
var framesToWait = 4;
function render() {
  if (framesToWait) {
    --framesToWait;
  } else {
     ... call drawArrays ...
  }
  requestAnimationFrame(render);
}
requestAnimationFrame(render);

这个 可能 有效,因为 chrome 是 multi-process。不过我不确定重点是什么。

在 WebGL2 中,您可以使用 FenceSync 对象来查明某事何时完成。