WebGL and the power of two image size
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.
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?
I have no problem with npot textures (FF & chrome) provided that you execute:
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);
This page nicely 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.
Update: WebGL2, the next version of WebGL, supports NPOT textures.
Reference provided by @EnabrenTane is very helpful. Non-Power of Two Texture Support
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.
I don't understand the low-level details well enough to completely answer your question, but here are some things I found:
This post is 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.”
I don't know if those extra conditions apply to your app. See also the OpenGL ES spec.
This thread goes fairly in-depth on support for "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.
...
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.
So, take that FWIW...
A simple solution would be to resize using 2d canvas and use that as a texture.
精彩评论