【问题标题】:rendering UIImage with size > 1024 with OpenGL ES 2.0 on the iPhone在 iPhone 上使用 OpenGL ES 2.0 渲染大小 > 1024 的 UIImage
【发布时间】:2011-11-09 12:41:17
【问题描述】:

我正在 iPhone 4 (1936X2592) 上捕获全分辨率 UIImage
然后我将其缩放为 1936x1936 大小的正方形。

现在我需要将此图像加载到纹理中,并让 OpenGL 使用一些 GLSL 对其进行渲染。

问题是 OpenGL 只支持 2 个纹理大小的幂,并且最多只能支持 1024。

那我该如何解决呢?

谢谢。

编辑:我的问题无关紧要,我的目标是 3GS 及以上,它支持 2048x2048 图像大小。 我的问题是另一个问题:Camera frame to UIImage to OpenGL rendering gives an odd image

【问题讨论】:

    标签: iphone ios opengl-es uiimage rendering


    【解决方案1】:

    从 3GS 开始,OpenGL 支持最高 2048x2048 的纹理。 4S 和 iPad2 支持 4096x4096。

    但是,如果情况并非如此,那么您的选择围绕着将像素打包在一起并使用有损压缩或使用多个纹理,您可以在 GLSL 中或通过几何体修复这两者(需要付费)。

    最明显的选择是上传为四个图块。每个方向上 1936 的输出大小允许您上传具有一些重叠的纹理,这样即使使用线性纹理过滤,您也应该能够获得无缝连接。假设你只需要水平分割,你可以确保一个纹理的底部两行与另一个纹理的顶部两行相同,并将几何连接放在这两行之间。

    其他选项不仅不太明显,而且不太有用。在有损打包方面,您可以将纹理从 RGB 转换到 YUV 空间,并且在代表每个 RGBA 样本的 32 位中存储四个 5 位 Y 样本、一个 6 位 U 样本和一个 6 位 V 样本。然后,您将在着色器中解包并重新组合。但是,您的视觉质量会降低,性能也会大大降低。

    【讨论】:

    • 我的应用程序支持 3GS 及以上,因此它解决了这个问题,但 OpenGL 仅支持 2 个纹理的功率,而 1936 不支持。那我该怎么做呢?
    • 您能否填充到 2048(或者,使用带有 NULL 数据指针的 glTexImage2D 创建一个 2048x2048 纹理,然后使用您的实际数据使用 glTexSubImage2D,以便 GL 为您完成工作),然后提供纹理坐标是否适当地使用仅 1936 像素的纹理?
    【解决方案2】:

    鉴于 iPhone 4 只有 960x640 的屏幕,为什么不把它降低到 1024x1024?这样您就不会不必要地浪费内存。

    如果做不到,则将其拆分为 4 个纹理。

    编辑:当你再画 4 个时,你实际上不必破坏原始图像。

    至于将图像拆分为 4 个单独的 UIImages 非常简单。要将左上角 1024x1024 渲染到 UIImage 中,您可以执行以下操作。

    subImageArea = CGRectMake( 0, 0, 1024, 1024 );
    CGImage* pCGSubImage = CGImageCreateWithImageInRect( [pUILargeImage CGImage], subImageArea );
    UIImage* pUISubImage = [UIImage initWithCGImage: pCGSubImage];
    

    【讨论】:

    • 我希望将全分辨率渲染图像保存在 iPhone 的相机胶卷中。能否详细说明如何将一个 UIImage 拆分为多个纹理?
    【解决方案3】:

    根据我在您之前的答案中读到的内容,您可以使用 2048x2048 的纹理大小。

    我在做截图的时候也遇到了类似的问题,屏幕尺寸960x640 -> 1024x1024 纹理尺寸,我就是这么干的:

    void *buffer = malloc( x * y * 4 );
    
    glReadPixels(0,0,x,y,GL_RGBA,GL_UNSIGNED_BYTE,buffer);
    glEnable(GL_TEXTURE_2D);
    
    glGenTextures(1, &screenShotTexture);
    glBindTexture(GL_TEXTURE_2D, screenShotTexture);
    
    glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE);
    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_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
    free(buffer);
    

    当然,我确保 x 和 y 是 POT。 我还必须处理纹理贴图,如下所示:

    static const float screenTexCoordsR[] = {
    0.0, 0.0,
    0.0, 0.9375,
    0.625, 0.0,
    0.625, 0.9375
    };
    

    你的不会那么浪费,而不是 0.9375 和 0.625 你会有 0.9453 或其他东西。

    【讨论】:

    • 我不明白您是如何将 fbo 像素读入缓冲区的,然后再将任何内容放在那里。
    • 在我的情况下,我直接使用 glReadPixels 阅读,但您可能需要从 uiimage 数据中对其进行内存复制。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-15
    • 1970-01-01
    • 1970-01-01
    • 2012-01-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多