javascript - FRAMEBUFFER INCOMPLETE ATTACHMENT 只发生在 Android 和/Firefox

标签 javascript cross-browser webgl framebuffer

我有一些 javascript/webgl 代码可以在我尝试过的所有浏览器上运行,但在 Android 上运行的移动版 firefox 除外。问题与“framebuffer complete”有关,但我不知 Prop 体是什么问题。

这是我能制作的最小的复制品。它应该只是创建一个纹理和一个帧缓冲区,设置一些属性,然后检查帧缓冲区是否“完整”:

var canvas = document.createElement('canvas');
var gl = canvas.getContext('webgl');
var GL = WebGLRenderingContext;
if (gl.getExtension('OES_texture_float') === null) {
    alert("No float support.");
}

var texture = gl.createTexture();
var frameBuffer = gl.createFramebuffer();
gl.bindTexture(GL.TEXTURE_2D, texture);
gl.bindFramebuffer(GL.FRAMEBUFFER, frameBuffer);

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.texImage2D(
    GL.TEXTURE_2D, //target
    0,             //level
    GL.RGBA,       //internalformat
    2,             //width
    2,             //height
    0,             //border
    GL.RGBA,       //format
    GL.FLOAT,      // type [changing to UNSIGNED_BYTE "fixes" the failure...?]
    null           // pixels
);
gl.framebufferTexture2D(
    GL.FRAMEBUFFER,
    GL.COLOR_ATTACHMENT0,
    GL.TEXTURE_2D,
    texture,
    0);

var result = gl.checkFramebufferStatus(GL.FRAMEBUFFER);
if (result === GL.FRAMEBUFFER_COMPLETE) {
    alert("success (FRAMEBUFFER_COMPLETE)");
} else {
    alert("ERROR " + ({
        [0]: "Argument wasn't a frame buffer",
        [GL.INVALID_ENUM]: "INVALID_ENUM",
        [GL.FRAMEBUFFER_INCOMPLETE_ATTACHMENT]: "FRAMEBUFFER_INCOMPLETE_ATTACHMENT",
        [GL.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT]:
            "FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT",
        [GL.FRAMEBUFFER_INCOMPLETE_DIMENSIONS]: "FRAMEBUFFER_INCOMPLETE_DIMENSIONS",
        [GL.FRAMEBUFFER_UNSUPPORTED]: "FRAMEBUFFER_UNSUPPORTED"
    }[result] || result));
}

在我的测试中,此代码在 Windows+Firefox-44、Windows+Chrome-49、Android+Chrome 和 Ubuntu+Firefox 上成功。但它在 Android+Firefox 上因 FRAMEBUFFER_INCOMPLETE_ATTACHMENT 而失败。

此外,我发现它似乎只影响FLOAT 纹理。如果我将类型更改为 UNSIGNED_BYTE,它就会通过。

因为我一般不熟悉 opengl,所以很可能我犯了一些明显的疏忽(例如,没有绑定(bind)必需的属性),而移动版 firefox 是唯一没有默默修复我的错误的浏览器。

另一个可能相关的事情是必须将 GL.FRAMEBUFFER 传递给 gl.checkFramebufferStatus,而不是实际的 frameBuffer 实例。当我传递 frameBuffer 时,结果总是 0。通常 0 表示成功,但是 the mdn docs甚至不要将 0 列为该函数的可能返回值;他们说好的结果是 FRAMEBUFFER_COMPLETE

最佳答案

如果它在其他浏览器中在完全相同的手机上工作,那么我会 file a bug with Mozilla .

但一般来说,将浮点纹理附加到帧缓冲区的能力并未得到普遍支持。在 OpenGL ES 2.0 中,任何格式都不能保证有效:(

在 WebGL 中,只有 3 种格式可以保证有效。 From the spec :

The following combinations of framebuffer object attachments, when all of the attachments are framebuffer attachment complete, non-zero, and have the same width and height, must result in the framebuffer being framebuffer complete:

  • COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture
  • COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture + DEPTH_ATTACHMENT = DEPTH_COMPONENT16 renderbuffer
  • COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture + DEPTH_STENCIL_ATTACHMENT = DEPTH_STENCIL renderbuffer

附件的所有其他组合取决于 GPU/驱动程序/浏览器。

关于javascript - FRAMEBUFFER INCOMPLETE ATTACHMENT 只发生在 Android 和/Firefox,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36109347/

相关文章:

javascript - 当数据是js对象时,用d3重新定位传单上的点

javascript - Momentjs 午夜以来的分钟数

javascript - 选择框并获取选项标签

html - 带有 CSS::before 的自定义复选框 - 在 Firefox/Edge 中不起作用

html - 在 chrome 和 firefox 中渲染不同

javascript - AJAX XHR请求onReadyStateChange事件顺序和次数澄清

css - 为什么 text-align 的浏览器前缀有不同的行为,哪个是正确的?

javascript - 如何从已创建的 WebGL 上下文中获取 WebGLProgram 对象?

docker - 在容器内使用 webgl 和 Nvidia GPU 运行 headless Chrome

three.js - Three.js png纹理-Alpha渲染为白色而不是透明