glGenerateMipmap - 非 2 的幂

glGenerateMipmap - non-power-of-2

环境Ubuntu17.04,Chrome60.

在没有 warnings/errors 的情况下在本地运行此示例:https://github.com/mdn/webgl-examples/tree/gh-pages/tutorial/sample6

然后将 cubetexture.png 替换为 non-power-of-2 图像: https://github.com/mdn/webgl-examples/blob/gh-pages/tutorial/sample6/webgl-demo.js#L220

符合预期 warnings/errors :

[.Offscreen-For-WebGL-0x13d050ba2c00]RENDER WARNING: texture bound to texture unit 0 is not renderable. It maybe non-power-of-2 and have incompatible texture filtering.

[.Offscreen-For-WebGL-0x13d050ba2c00]GL ERROR :GL_INVALID_OPERATION : glGenerateMipmap: Can not generate mips

接下来添加参数:

gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
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);

然后在没有警告的情况下运行正常,但仍然意外得到错误:

[.Offscreen-For-WebGL-0x13d050fb4000]GL ERROR :GL_INVALID_OPERATION : glGenerateMipmap: Can not generate mips

除了错误消息外,non-power-of-2 图像在立方体上渲染正常。 Firefox 54 中的行为相同。这里有什么提示吗?

您无法在 WebGL1 中为非 2 的幂次方纹理生成 mipmap。这就是重点,WebGL1 时期不支持 mipmapped 非 2 次幂纹理。所以你设置了过滤,所以它只使用级别 0

gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);

这意味着没有理由生成 mip,因为它们永远不会被使用。 See this article.

WebGL 基于 OpenGL ES 2.0。虽然 WebGL 的在线文档定义了可用的功能,但对于限制和一些特定行为,您需要解决 OpenGL ES 2.0 完整规范。 在 https://www.khronos.org/registry/OpenGL/specs/es/2.0/es_full_spec_2.0.pdf

有售

对于TexImage2D函数在3.7.1:

If level is greater than zero, and either width or height is not a power of two, the error INVALID_VALUE is generated

对于 GenerateMipmap3.7.11:

If either the width or height of the level zero array are not a power or two, the error INVALID_OPERATION is generated

结论

非二次幂纹理只能有第一(零)级。而且您无法为非二次方纹理生成 mipmap。


另外值得注意的是,非二次方纹理有额外的限制:

文章 3.7:

If any dimension of any array in a mipmap is not a power of two (e.g. if rounding down as described above is performed), then the mipmap is described as a non-power-of-two texture. Non-power-of-two textures have restrictions on the allowed texture wrap modes and filters, as described in section 3.8.2

3.8.2中:

Calling a sampler from a fragment shader will return (R, G, B, A) = (0, 0, 0, 1) if any of the following conditions are true:

....

• A two-dimensional sampler is called, the corresponding texture image is a non-power-of-two image (as described in the Mipmapping discussion of section 3.7.7), and either the texture wrap mode is not CLAMP_TO_EDGE, or the minification filter is neither NEAREST nor LINEAR.