【问题标题】:Unable to render alpha channel as a texture in WebGL无法在 WebGL 中将 Alpha 通道渲染为纹理
【发布时间】:2018-04-01 07:55:21
【问题描述】:

我正在读取具有图像数据的 DICOM 文件的 alpha 通道,之后我使用 this tutorial 对其进行解析和渲染,此外我将 alpha 通道转发到 webgl 程序以渲染纹理.

但是,它适用于少数图像,也适用于某些图像。 以下是几个用例:

SNO 宽度 高度 状态

  1. 宽度:628,高度:888,Alpha 通道长度:557664(工作正常)。

  2. 宽度:448,高度:612,Alpha 通道长度:274176(工作正常)。

  3. 宽度:446,高度:612,Alpha 通道长度:272952(不起作用)。

  4. 宽度:2219,高度:1200,Alpha 通道长度:2662800(不起作用)。

对于用例 3 和 4,我收到以下错误消息:

  • 错误:WebGL:texImage2D:提供的缓冲区太小。 (需要2663999,有2662800)
  • 错误:WebGL:generateMipmap:纹理的基本级别没有二维的幂。

有什么建议吗?

【问题讨论】:

    标签: textures webgl


    【解决方案1】:

    错误实际上就是他们所说的。

    1. Error: WebGL: texImage2D: Provided buffer is too small. (needs 2663999, has 2662800)

      您调用了gl.texImage2D,但纹理的尺寸大于您提供的数据。

      例如,如果你这样做了

      var width = 16;
      var height = 16;
      gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0,
                    gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(10));
      

      你会得到同样的错误。您指定了一个纹理 16x16xRGBA(4) 表示数据必须是 16*16*4 或 1024 字节,但上面的代码只传递了 10 个字节

      需要注意的一点是UNPACK_ALIGNMENT 设置。默认为 4 这意味着每行数据将被填充到 4 个字节。换句话说,7x3 的 alpha 纹理将是

      width = 7
      height = 3
      bytesPerPixel = 1   // gl.ALPHA
      unpaddedRowSize = width * bytesPerPixel
      paddedRowSize = Math.floor((minBytesPerRow + 3) / 4) * 4;  // = 8
      requiredDataSize = (height - 1 * paddedRowSize) + unpaddedRowSize
      

      您可能认为 ALPHA 只需要 7x3 或 21 个字节,但实际上您需要 8+8+7 或 23 个字节,因为除最后一行之外的每一行都填充为 4 的倍数

      您可以通过调用告诉 WebGL 将 UNPACK_ALIGNMENT 设置为 1

      gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
      

      现在它只需要 21 个字节,因为它不再填充行。

    2. Error: WebGL: generateMipmap: The base level of the texture does not have power-of-two dimensions

      WebGL 1.0 不能使用 mips,除非纹理在两个维度上都是 2 的幂。您的示例纹理在任一维度上都不是 2 的幂,因此您不能使用 mips,也不能为它们调用 gl.generateMipmap

      相反,您必须将纹理过滤设置为仅使用顶级(0 级)mip

      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); // or gl.NEAREST
      

      并且你必须将包装设置为CLAMP_TO_EDGE

      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);
      

      WebGL 2.0 消除了这些限制

    【讨论】:

    • 我尝试了您提供的所有建议,但遗憾的是没有任何效果,但是如果我将 alpha 通道保存到单独的画布并尝试将该画布渲染为 webgl 中的纹理,它可以工作
    猜你喜欢
    • 2012-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-03
    • 1970-01-01
    相关资源
    最近更新 更多