代码之家  ›  专栏  ›  技术社区  ›  Hilton Campbell

将UIView的内容呈现为OpenGL纹理

  •  12
  • Hilton Campbell  · 技术社区  · 14 年前

    有没有一种方法可以在iOS中使用OpenGL将UIView的内容呈现为纹理?或者CGLayer的内容?

    2 回复  |  直到 14 年前
        1
  •  19
  •   Tommy    14 年前

    您可以使用视图的layer属性来获取CALayer并使用renderingcontext:在该属性上绘制到CoreGraphics上下文中。您可以使用自己分配的内存设置CoreGraphics上下文,以便接收像素缓冲区。然后可以通过普通方法将其上载到OpenGL。

    即席编码的过程如下:

    UIView *view = ... something ...;
    
    // make space for an RGBA image of the view
    GLubyte *pixelBuffer = (GLubyte *)malloc(
                                   4 * 
                                   view.bounds.size.width * 
                                   view.bounds.size.height);
    
    // create a suitable CoreGraphics context
    CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context =
        CGBitmapContextCreate(pixelBuffer, 
                              view.bounds.size.width, view.bounds.size.height, 
                              8, 4*view.bounds.size.width, 
                              colourSpace, 
                              kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
    CGColorSpaceRelease(colourSpace);
    
    // draw the view to the buffer
    [view.layer renderInContext:context];
    
    // upload to OpenGL
    glTexImage2D(GL_TEXTURE_2D, 0, 
                 GL_RGBA,
                 view.bounds.size.width, view.bounds.size.height, 0,
                 GL_RGBA, GL_UNSIGNED_BYTE, pixelBuffer);
    
    // clean up
    CGContextRelease(context);
    free(pixelBuffer);
    

    在这里处理两个纹理的非幂的最简单方法可能是创建足够大的两个纹理的幂,并使用glTexSubImage2D从源UIView上传部分。

        2
  •  5
  •   Community CDub    7 年前

    How do I grab an image form my EAGLLayer ?

    一旦你有了你的图像,它必须调整到二次方。您可以尝试拉伸图像,但如果您再次收缩图像,或重复拉伸图像,则会导致质量问题。最好的方法是将图像的正常大小绘制到一个带有额外像素的base-2纹理中,以形成缓冲区。这是代码(我是从别人的代码中修改的,但找不到原始代码,所以如果有人看到原始代码,请告诉我它是从哪里来的,以表示信任):

    -(UIImage*)base2Image:(UIImage *) srcImg {
        int frame2Base = 512;
    
        CGSize srcSize = [srcImg size];
        CGRect rec = CGRectMake(0, 0, frame2Base, frame2Base);
    
        [srcImg drawInRect:rec blendMode:kCGBlendModeNormal alpha:1.0];
    
        //create a context to do our clipping in
        UIGraphicsBeginImageContext(CGSizeMake(frame2Base, frame2Base));
        CGContextRef currentContext = UIGraphicsGetCurrentContext();
    
        //create a rect with the size we want to crop the image to
        CGRect clippedRect = CGRectMake(0, 0, frame2Base, frame2Base);
        CGContextClipToRect(currentContext, clippedRect);
    
        //create a rect equivalent to the full size of the image
        CGRect drawRect = CGRectMake(0, 0, srcSize.width, srcSize.height);
    
        //draw the image to our clipped context using our offset rect
        CGContextDrawImage(currentContext, drawRect, srcImg.CGImage);
    
        UIImage *dstImg =  UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return dstImg;
    }
    

    GLfloat texCoords[] = {
        0.0, (float)frameHeight/2BaseHeight,
        0.0, 0.0,
        (float)frameWidth/2BaseWidth, (float)frameHeight/2BaseHeight,
        (float)frameWidth/2BaseWidth, 0.0
    };
    

    你拿到了。从你的可见屏幕截图,现在是一个纹理。