【问题标题】:Rendering to non-power-of-two texture on iPhone在 iPhone 上渲染为非二次幂纹理
【发布时间】:2011-01-22 01:51:00
【问题描述】:

是否可以在 iPhone(2G 及更早版本)上使用 OpenGL ES 1.1 渲染到纹理?如果我将纹理绑定为渲染缓冲区,它必须是渲染缓冲区的大小,而不是 POT 大小。但是 OpenGL ES 1.1 要求纹理是 POT。

也许它不能在 ES 1.1 上完成?

【问题讨论】:

    标签: iphone opengl-es render-to-texture


    【解决方案1】:

    虽然 OpenGL ES 1.1 不支持非二次幂纹理,但较新的 iOS 设备型号具有扩展名 GL_APPLE_texture_2D_limited_npot,其中指出:

    传统的 OpenGL ES 1.X 纹理 仅限于具有二次幂的图像 (锅)尺寸。 APPLE_texture_2D_limited_npot 扩展放松了这些尺寸 2D 纹理的限制。这 立方体的限制仍然存在 地图和 3D 纹理(如果支持)。

    没有额外的程序或 由此引入的枚举 API 扩展名,除了一个 导出的实现 扩展字符串将允许 用于传递 2D 纹理的应用程序 尺寸可能是也可能不是 二的幂。

    在没有 OES_texture_npot 的情况下, 解除这些限制, 既不是 mipmapping 也不是包装模式 支持 CLAMP_TO_EDGE 以外的其他 结合 NPOT 2D 纹理。 具有环绕模式的 NPOT 2D 纹理 这不是 CLAMP_TO_EDGE 或 不是最近的最小过滤器或 LINEAR 被认为是不完整的。如果 这样的纹理绑定到纹理 单位,就好像纹理映射 该纹理单元被禁用。

    您可以使用以下代码来确定您的设备是否支持此扩展程序(摘自 Philip Rideout 的优秀 iPhone 3D Programming 书籍):

    const char* extensions = (char*) glGetString(GL_EXTENSIONS); 
    bool npot = strstr(extensions, "GL_APPLE_texture_2D_limited_npot") != 0;
    

    在这些设备上,您应该能够使用非二次幂纹理,只要您设置了正确的纹理包装:

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    

    不幸的是,我拥有的this example application 使用 OpenGL ES 2.0 渲染到非二次幂纹理,所以我不确定在这种情况下是否会对您有所帮助。

    【讨论】:

    • 您应该使用strstr来检查扩展字符串中的扩展名。这并不能确保您不会误解以相同前缀开头的另一个扩展名。如果你有 GL_ARB_shadow_ambient,说用 strstr 检查 GL_ARB_shadow 会咬你。很久以前,当软件更新在驱动程序中带来了新的 GL 扩展时,我曾被咬过一次,并在其发布数月后破坏了我的代码。
    • @rotoglup - 这是一个很好的观点。正如我所说,这是从 Philip Rideout 的书中提取的代码。也许你可以为书上的勘误给他写点什么。
    • 感谢@rotoglup,我将把它添加到我的书勘误表中。
    【解决方案2】:

    是可以的,只要得到比非POT大2的下一个幂即可。

    然后生成一个framebuffer:

    GLuint aFramebuffer;
    glGenFramebuffersOES(1, &aFramebuffer);
    

    还有一个纹理:

    GLuint aTexturebuffer;
    glGenTextures(1, &aTexturebuffer);
    

    然后你做同样的纹理之类的事情:

    glBindTexture(GL_TEXTURE_2D, aTexturebuffer);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glColor4ub(0, 0, 0, 255);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, textureWidth, textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    
    int area[] = {0.0, 0.0, renderWidth, renderHeight};
    
    glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, area);
    
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, aFramebuffer);
    glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, aTexturebuffer, 0);
    

    这里我使用了 draw_texture 扩展。 textureWidthtextureHeight 是 2 的幂,renderWidthrenderHeight 是渲染器的宽度和高度。 然后当你绑定到aFramebuffer 时,它会绘制到纹理。

    【讨论】:

    • 不幸的是,它不起作用。 glCheckFramebufferStatusOES 返回 GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS。
    • @Kronikarz:你也创建了渲染缓冲区吗?如glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_RGBA8_OES, width, height); 连接到帧缓冲区?
    • @Kronikarz:我相信,根据我的经验,您还应该能够在不四舍五入的情况下渲染到非 POT 纹理。
    • @Kronikarz:需要明确的是,在非常特定的条件下,iPhone 绝对支持 GL 1.1 下的非 POT 纹理。 (我一直在使用它们。)技术说明在这里:khronos.org/registry/gles/extensions/APPLE/… 我找不到 iOS 文档的引用。您的 tex 参数必须符合某些限制。
    • @Kronikarz:啊,你又回到了 2G 或其他什么地方。您应该在您的问题中澄清这一点,以便人们知道您在询问遗留(坦率地说)平台的东西。祝你好运!
    猜你喜欢
    • 2016-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多