iOS OpenGL renderbufferStorage:fromDrawable 方法详解
iOS中OpenGL的渲染流程之前已经介绍过此处不再介绍。
点击参考OpenGL iOS端渲染流程
renderbufferStorage:fromDrawable:
作用:将可绘制对象的存储绑定到OpenGL ES renderbuffer对象。
Declaration
- (BOOL)renderbufferStorage:(NSUInteger)target
fromDrawable:(id<EAGLDrawable>)drawable;
Parameters
target OpenGL ES绑定点用于当前绑定的renderbuffer。该参数的值必须是GL_RENDERBUFFER(或者GL_RENDERBUFFER_OES在OpenGL ES 1.1上下文中)。
drawable 管理renderbuffer的数据存储的对象。在iOS中,此参数的值必须是一个 CAEAGLLayer 对象。
Return Value YES if successful; otherwise, NO.
函数的内部实现流程
为了创建一个可以呈现给屏幕的renderbuffer,您可以绑定renderbuffer,然后通过调用此方法为其分配共享存储空间。此方法调用是为了替换正常情况下的glRenderbufferStorage方法(对于非iOS平台的其他平台)。其存储已分配了此方法的renderbuffer可以随后通过调用glRenderbufferStorage函数来显示数据。
一个通过renderbufferStorage:fromDrawable 方法来分配存储空间的renderbuffer可以在之后通过调用 presentRenderbuffer:来显示renderbuffer的内容。
宽度,高度和内部颜色缓冲区格式是从CAEAGLLayer对象的属性中导出的。在调用此方法之前,可以通过在可绘制对象的drawableProperties字典中添加一个kEAGLDrawablePropertyColorFormat键来覆盖内部颜色缓冲区格式。
要使OpenGL ES renderbuffer与CAEAGLLayer对象分离,请将drawable参数设置为nil即可将两者分离。
关于正常情况下的glRenderbufferStorage方法(对于非iOS平台的其他平台)请参考 OpenGL glRenderbufferStorage 函数详解
需要注意的是:
在iOS 6.0及更高版本中,此方法会自动刷新OpenGL ES的命令缓冲区,这导致了此函数不适合在对性能有较高要求的代码中中重复调用。
Failed to make complete framebuffer object 0x8CD6
// 常见错误解决 对于iOS8.x有renderbufferStorage:GL_RENDERBUFFER failed 解决办法如下:
CALayer *superLayer = layer.superlayer;
[layer removeFromSuperlayer];
if( ! [context_ renderbufferStorage:GL_RENDERBUFFER fromDrawable:layer] )
{
NSLog(@"failed to call context");
}
if (superLayer) {
[superLayer addSublayer:layer];
}
// fix iOS8 layoutSubviews时调用 if( ! [context_ renderbufferStorage:GL_RENDERBUFFER fromDrawable:layer] ) failed 的bug。
// 解决方法1:
// 当在viewDidLoad内绑定CCEGGLView视图时将layer的父layer移除此时layer的父layer状态未初始化完毕。opengl可能仍为此父视图是在后台运行的。(猜测)
// UIViewController present 和 pop时layoutSubviews会有同样的问题产生。
// CALayer *superLayer = self.layer.superlayer;
// [self.layer removeFromSuperlayer];
// [renderer_ resizeFromLayer:(CAEAGLLayer*)self.layer];
// if (superLayer) {
// [superLayer addSublayer:self.layer];
// }
// 解决方法2:
// 不要在viewDidLoad方法内绑定CCEGGLView视图。
// dispatch_async(dispatch_get_main_queue(), ^{
// OpenGLView *glview = [self createOpenGLView];
// [self.view addSubview:glview];
// });