带有opengl视图的"renderincontext"问题

use*_*972 6 objective-c ios

我有一个问题,有openGL视图.我有两个openGL视图.第二个视图作为子视图添加到主视图中.两个opengl视图在两个不同的opengl上下文中绘制.我需要使用两个opengl视图捕获屏幕.

问题是,如果我尝试在上下文中呈现一个CAEAGLLayer,如下所示:

CGContextRef context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, 1*(self.frame.size.width*0.5), 1*(self.frame.size.height*0.5));
CGContextScaleCTM(context, 3, 3);
CGContextTranslateCTM(context, abcd, abcd);

CAEAGLLayer *eaglLayer = (CAEAGLLayer*) self.myOwnView.layer;
[eaglLayer renderInContext:context];
Run Code Online (Sandbox Code Playgroud)

这是行不通的.如果我看到上下文(将输出作为图像),则缺少opengl层中的内容.但我发现输出图像中的工具栏和2D图像附加到视图中.我不确定这个问题.请帮忙.

ldo*_*ogy 6

我遇到了类似的问题,并找到了更优雅的解决方案.基本上,你是CAEAGLLayer的子类,并添加你自己的renderInContext实现,它只是要求OpenGL视图使用glReadPixels渲染内容.美妙的是,现在您可以在层次结构中的任何图层上调用renderInContext,结果是一个完全组合,完美的截图,其中包含您的OpenGL视图!

我们在子类CAEAGLLayer中的renderInContext是:

- (void)renderInContext:(CGContextRef)ctx
{
    [super renderInContext: ctx];
    [self.delegate renderInContext: ctx];
}
Run Code Online (Sandbox Code Playgroud)

然后,在OpenGL视图中,我们替换layerClass,以便它返回我们的子类而不是普通的CAEAGLLayer:

+ (Class)layerClass
{
    return [MyCAEAGLLayer class];
}
Run Code Online (Sandbox Code Playgroud)

我们在视图中添加一个方法,以实际将视图的内容呈现到上下文中.请注意,此代码必须在渲染GL视图后运行,但在调用之前presentRenderbuffer,渲染缓冲区将包含您的帧.否则,生成的图像很可能是空的(您可能会在此特定问题上看到设备和模拟器之间的不同行为).

- (void) renderInContext: (CGContextRef) context
{
    GLint backingWidth, backingHeight;

    // Bind the color renderbuffer used to render the OpenGL ES view
    // If your application only creates a single color renderbuffer which is already bound at this point,
    // this call is redundant, but it is needed if you're dealing with multiple renderbuffers.
    // Note, replace "_colorRenderbuffer" with the actual name of the renderbuffer object defined in your class.
    glBindRenderbuffer(GL_RENDERBUFFER, _colorRenderBuffer);

    // Get the size of the backing CAEAGLLayer
    glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &backingWidth);
    glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &backingHeight);

    NSInteger x = 0, y = 0, width = backingWidth, height = backingHeight;
    NSInteger dataLength = width * height * 4;
    GLubyte *data = (GLubyte*)malloc(dataLength * sizeof(GLubyte));

    // Read pixel data from the framebuffer
    glPixelStorei(GL_PACK_ALIGNMENT, 4);
    glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);

    // Create a CGImage with the pixel data
    // If your OpenGL ES content is opaque, use kCGImageAlphaNoneSkipLast to ignore the alpha channel
    // otherwise, use kCGImageAlphaPremultipliedLast
    CGDataProviderRef ref = CGDataProviderCreateWithData(NULL, data, dataLength, NULL);
    CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
    CGImageRef iref = CGImageCreate(width, height, 8, 32, width * 4, colorspace, kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast,
                                    ref, NULL, true, kCGRenderingIntentDefault);

    CGFloat scale = self.contentScaleFactor;
    NSInteger widthInPoints, heightInPoints;
    widthInPoints = width / scale;
    heightInPoints = height / scale;

    // UIKit coordinate system is upside down to GL/Quartz coordinate system
    // Flip the CGImage by rendering it to the flipped bitmap context
    // The size of the destination area is measured in POINTS
    CGContextSetBlendMode(context, kCGBlendModeCopy);
    CGContextDrawImage(context, CGRectMake(0.0, 0.0, widthInPoints, heightInPoints), iref);

    // Clean up
    free(data);
    CFRelease(ref);
    CFRelease(colorspace);
    CGImageRelease(iref);
}
Run Code Online (Sandbox Code Playgroud)

最后,为了获取截图,您可以在通常的情况下使用renderInContext.当然,美妙之处在于您无需直接获取OpenGL视图.您可以获取OpenGL视图的一个超级视图,并获得一个包含OpenGL视图以及旁边的任何其他内容或其上的组合截图:

UIGraphicsBeginImageContextWithOptions(superviewToGrab.bounds.size, YES, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
[superviewToGrab.layer renderInContext: context]; // This recursively calls renderInContext on all the sublayers, including your OpenGL layer(s)
CGImageRef screenShot = UIGraphicsGetImageFromCurrentImageContext().CGImage;
UIGraphicsEndImageContext();
Run Code Online (Sandbox Code Playgroud)