OpenGL规范从2.0开始支持显示边长为非2次幂的Texture,但限制条件是需要环绕模式为CLAMP_TO_EDGE并且过滤模式为NEAREST或者LINEAR。
解除限制的条件是硬件支持OES_texture_npot的扩展。
https://www.khronos.org/registry/OpenGL/extensions/OES/OES_texture_npot.txt
This extension adds support for the REPEAT and MIRRORED_REPEAT
texture wrap modes and the minification filters supported for
non-power of two 2D textures, cubemaps and for 3D textures, if
the OES_texture_3D extension is supported.
Section 3.8.2 of the OpenGL ES 2.0 specification describes
rules for sampling from an incomplete texture. There were specific
rules added for non-power of two textures i.e. if the texture wrap
mode is not CLAMP_TO_EDGE or minification filter is not NEAREST or
LINEAR and the texture is a non-power-of-two texture, then sampling
the texture will return (0, 0, 0, 1).
These rules are no longer applied by an implementation that supports
this extension.
GLES didn't have clamp to border until 3.2, but provides several alternative extensions:
https://github.com/google/skia/blob/main/src/gpu/gl/GrGLCaps.cpp
获取硬件扩展列表的代码如下:
std::string GetGLString(unsigned int pname) {
const char* gl_string =
reinterpret_cast<const char*>(glGetString(pname));
if (gl_string)
return std::string(gl_string);
return "";
}
...
const char* gl_extensions = GetGLString(GL_EXTENSIONS).c_str();
ULOGE("gl_extensions %s", gl_extensions);
//看打印的字符串里是否包含OES_texture_npot
OpenGL 2.0规范里有这个限制,是因为NPOT纹理设置REPEAT等模式时,在应用插值采样后,会造成图案连接处有接缝:
Seamless tilemap rendering (borderless adjacent images)
OpenGL对NPOT纹理的支持情况:
OpenGL ES 3.0 has full NPOT support in core; ES 2.0 has limited NPOT support (no mipmaps, no Repeat wrap mode) in core; and ES 1.1 has no NPOT support.
For ES 1.1 and 2.0, full NPOT support comes with GL_ARB_texture_non_power_of_two orGL_OES_texture_npot extension. In practice, iOS devices don’t support this; and on Android side there’s support on Qualcomm Adreno and ARM Mali. Possibly some others.
For ES 1.1, limited NPOT support comes with GL_APPLE_texture_2D_limited_npot (all iOS devices) or GL_IMG_texture_npot (some ImgTec Android devices I guess).
而谷歌从Android7.0开始强制要求设备支持OpenGL3.1, 之前的设备还是可以只支持OpenGL2.0:android-7.0-cdd.pdf
为什么你的手机无法升级到安卓7.0?
但还是有人遇到Android7.0的设备默认只支持OpenGL2.x:In Android 6 releases of Fairphone OS/Open, version 3.0 of OpenGL ES was available. After upgrading to Android 7 on the Fairphone 2, only OpenGL ES 2.0 is available.
所以可以认为,Android 7.0以上的设备以及iOS 7.0(iPhone系列 5S)以上的设备,启用OpenGL3.0后,支持对NPOT纹理应用GL_REPEAT等功能。而Android的7.0以前的设备,如果硬件支持OES_texture_npot扩展,那么也同样支持。
iOS升级3.0的文档:Adopting OpenGL ES 3.0
参考:
NPOT texture in iOS can't be repeat mode!
PowerVR Supported Extensions OpenGL ES and EGL
update:
实践的结论是,用shader在OpenGL2.0上实现NPOT的GL_REPEAT模式,预览效果也还好。在几台Android和iOS设备上测试,连接处的缝隙看不出来。
所以OpenGL2.0不支持的原因,我猜是在mipmap的场景下可能有问题。
实现的代码也比较简单:
// GL_REPEAT
gl_FragColor = texture2D(uTexture, fract(vTexCoord));
// GL_MIRRORED_REPEAT
vec2 clipCoord = mod(vTexCoord, 2.0);
gl_FragColor = texture2D(uTexture, 1.0 - abs(1.0 - clipCoord));
网友评论