javascript WebGL 和两种图像大小的威力

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3792027/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 02:15:24  来源:igfitidea点击:

WebGL and the power of two image size

javascriptwebgl

提问by Mr Bell

I want to use WebGL to make a little 3D gallery of Flickr photo streams. It looks like WebGL only allows square images that's dimensions are a power of two to be used as textures. I need to be able to display images of any proportion and dimension. I can see that if I copy the image data into another image that is the nearest square dimension and then use texture coordinates to make it display right. The problem is, and correct me if I am wrong, that I can't do that image manipulation in JavaScript and would need a server running ASP.NET, Java or something like that to do the processing for me before WebGL could get its hands on it.

我想使用 WebGL 制作一个 Flickr 照片流的小 3D 画廊。看起来 WebGL 只允许尺寸为 2 的幂的方形图像用作纹理。我需要能够显示任何比例和尺寸的图像。我可以看到,如果我将图像数据复制到另一个最近的正方形尺寸的图像中,然后使用纹理坐标使其正确显示。问题是,如果我错了,请纠正我,我不能在 JavaScript 中进行图像处理,并且需要一个运行 ASP.NET、Java 或类似东西的服务器来为我进行处理,然后 WebGL 才能得到它的帮助在上面。

Is there a way of using arbitrarily sized images in WebGL and JavaScript without the need for a server to act as a middle man image processor?

有没有办法在 WebGL 和 JavaScript 中使用任意大小的图像,而无需服务器充当中间人图像处理器?

回答by user52875

I have no problem with npot textures (FF & chrome) provided that you execute:

如果您执行以下操作,我对 npot 纹理(FF 和 chrome)没有任何问题:

texParameteri(TEXTURE_2D, TEXTURE_MAG_FILTER, LINEAR);
texParameteri(TEXTURE_2D, TEXTURE_MIN_FILTER, LINEAR);
texParameteri(TEXTURE_2D, TEXTURE_WRAP_S, CLAMP_TO_EDGE);
texParameteri(TEXTURE_2D, TEXTURE_WRAP_T, CLAMP_TO_EDGE);

回答by brainjam

This pagenicely sums up the situation (and more or less restates what the other answerers here have already said). Basically, WebGL does not support NPOT textures with mipmapping and/or repeats. And if you can't get away without those modes, the texture can be resized in a 2D canvas. And the page includes some handy code for canvas resizing.

这个页面很好地总结了情况(或多或少重申了这里其他回答者已经说过的内容)。基本上,WebGL 不支持带有 mipmapping 和/或重复的 NPOT 纹理。如果没有这些模式就无法逃脱,可以在 2D 画布中调整纹理的大小。该页面包含一些用于调整画布大小的方便代码。

Update:WebGL2, the next version of WebGL, supports NPOT textures.

更新:WebGL2,WebGL 的下一个版本,支持 NPOT 纹理

回答by ooOlly

Reference provided by @EnabrenTane is very helpful. Non-Power of Two Texture Support

@EnabrenTane 提供的参考非常有帮助。两个纹理支持的非幂

While OpenGL 2.0 and later for the desktop offer full support for non-power-of-two (NPOT) textures, OpenGL ES 2.0 and WebGL have only limited NPOT support. The restrictions are defined in Sections 3.8.2, "Shader Execution", and 3.7.11, "Mipmap Generation", of the OpenGL ES 2.0 specification, and are summarized here:

  • generateMipmap(target) generates an INVALID_OPERATION error if the level 0 image of the texture currently bound to target has an NPOT width or height.
  • Sampling an NPOT texture in a shader will produce the RGBA color (0, 0, 0, 1) if:
    • The minification filter is set to anything but NEAREST or LINEAR: in other words, if it uses one of the mipmapped filters.
    • The repeat mode is set to anything but CLAMP_TO_EDGE; repeating NPOT textures are not supported.

虽然用于桌面的 OpenGL 2.0 及更高版本提供对非二次方 (NPOT) 纹理的全面支持,但 OpenGL ES 2.0 和 WebGL 仅提供有限的 NPOT 支持。这些限制在 OpenGL ES 2.0 规范的第 3.8.2 节“着色器执行”和第 3.7.11 节“Mipmap 生成”中定义,总结如下:

  • 如果当前绑定到目标的纹理的 0 级图像具有 NPOT 宽度或高度,则 generateMipmap(target) 会生成 INVALID_OPERATION 错误。
  • 如果满足以下条件,则在着色器中对 NPOT 纹理进行采样将产生 RGBA 颜色 (0, 0, 0, 1):
    • 缩小过滤器设置为 NEAREST 或 LINEAR 以外的任何值:换句话说,如果它使用 mipmapped 过滤器之一。
    • 重复模式设置为除 CLAMP_TO_EDGE 之外的任何内容;不支持重复的 NPOT 纹理。

回答by LarsH

I don't understand the low-level details well enough to completely answer your question, but here are some things I found:

我不太了解底层细节,无法完全回答你的问题,但我发现了一些东西:

This postis not encouraging:

这篇文章并不令人鼓舞:

Texture handling has been updated in Minefield so that [it] better matches the specification; previously it was quite forgiving [...] and allowed you to use textures that weren't really valid from a WebGL viewpoint. Now it doesn't [...] you'll see an error message saying “A texture is going to be rendered as if it were black, as per the OpenGL ES 2.0.24 spec section 3.8.2, because it is a 2D texture, with a minification filter not requiring a mipmap, with its width or height not a power of two, and with a wrap mode different from CLAMP_TO_EDGE.”

Minefield 中的纹理处理已更新,以便 [it] 更好地匹配规范;以前它非常宽容 [...] 并允许您使用从 WebGL 的角度来看不是真正有效的纹理。现在它没有 [...] 您会看到一条错误消息,指出“根据 OpenGL ES 2.0.24 规范第 3.8.2 节,纹理将被渲染为黑色,因为它是一个2D 纹理,带有不需要 mipmap 的缩小过滤器,其宽度或高度不是 2 的幂,并且具有不同于 CLAMP_TO_EDGE 的环绕模式。”

I don't know if those extra conditions apply to your app. See also the OpenGL ES spec.

我不知道这些额外条件是否适用于您的应用。另请参阅OpenGL ES 规范

This threadgoes fairly in-depth on support for "NPOT":

该线程对“NPOT”的支持进行了相当深入的讨论:

OpenGL supports NPOT textures in two ways. The first is called "Rectangle Textures" (RT), which can be any size, but can't be repeating, mip-mapped or have borders. And rather than using 0-1 texture coordinates, they use 0-w, 0-h. OpenGL Also supports true NPOT textures, which have similar constraints to RT, but which use the normal 0-1 texture coordinates.

The issue is that some older hardware (and when I say "older" I mean hardware from 2005) only supports RT, not true NPOT. It's not possible to emulate NPOT when you just have RT support because in GLSL you use a different sampler for RT (sampler2DRect vs sampler2D).

OpenGL ES only supports NPOT, not RT.

OpenGL 以两种方式支持 NPOT 纹理。第一种称为“矩形纹理”(RT),可以是任意大小,但不能重复、mip 映射或有边框。他们不使用 0-1 纹理坐标,而是使用 0-w、0-h。OpenGL 还支持真正的 NPOT 纹理,它具有与 RT 类似的约束,但使用正常的 0-1 纹理坐标。

问题是一些较旧的硬件(当我说“较旧”时,我指的是 2005 年的硬件)仅支持 RT,而不是真正的 NPOT。当您只有 RT 支持时,无法模拟 NPOT,因为在 GLSL 中您使用不同的采样器进行 RT(sampler2DRect 与 sampler2D)。

OpenGL ES 只支持 NPOT,不支持 RT。

...

...

A WebGL implementation can scale up NPOT texture data to the next highest power of two dimension during texImage2D and texSubImage2D calls. This wouldn't involve any API changes. O3D does this in some cases as proof that the technique can work without the end user knowing. I think it would be a bad idea to expose rectangular textures in the WebGL API; they are definitely not the path forward.

WebGL 实现可以在 texImage2D 和 texSubImage2D 调用期间将 NPOT 纹理数据放大到二维的下一个最高幂。这不会涉及任何 API 更改。在某些情况下,O3D 这样做是为了证明该技术可以在最终用户不知情的情况下工作。我认为在 WebGL API 中公开矩形纹理是一个坏主意;他们绝对不是前进的道路。

So, take that FWIW...

所以,拿那个 FWIW...

回答by Ryan S

A simple solution would be to resize using 2d canvas and use that as a texture.

一个简单的解决方案是使用 2d 画布调整大小并将其用作纹理。