我有一个问题,有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图像附加到视图中.我不确定这个问题.请帮忙.
我遇到了类似的问题,并找到了更优雅的解决方案.基本上,你是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)
| 归档时间: |
|
| 查看次数: |
2243 次 |
| 最近记录: |