我试图在我的全屏渲染输出上应用Core
Image过滤器,但是看起来像我缺少一些东西,因为我将黑屏作为输出.
首先我将整个场景画成纹理.然后我从这个纹理创建CoreImage,我终于画出来了.但我所得到的只是黑屏.我正在遵循苹果指南线绘制纹理,并将CoreImage与OpenGLES集成:WWDC2012 511和https://developer.apple.com/library/ios/documentation/3ddrawing/conceptual/opengles_programmingguide/WorkingwithEAGLContexts/WorkingwithEAGLContexts.html
这里是相关代码:
渲染:
@interface Renderer () { EAGLContext* _context; GLuint _defaultFramebuffer,_drawFramebuffer,_depthRenderbuffer,_colorRenderbuffer,_drawTexture; GLint _backingWidth,_backingHeight; CIImage *_coreImage; CIFilter *_coreFilter; CIContext *_coreContext; }
初始化方法:
- (BOOL)initOpenGL { _context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; if (!_context) return NO; [EAGLContext setCurrentContext:_context]; glGenFramebuffers(1,&_defaultFramebuffer); glBindFramebuffer(GL_FRAMEBUFFER,_defaultFramebuffer); glGenRenderbuffers(1,&_colorRenderbuffer); glBindRenderbuffer(GL_RENDERBUFFER,_colorRenderbuffer); glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_RENDERBUFFER,_colorRenderbuffer); glGenFramebuffers(1,&_drawFramebuffer); glBindFramebuffer(GL_FRAMEBUFFER,_drawFramebuffer); glGenTextures(1,&_drawTexture); glBindTexture(GL_TEXTURE_2D,_drawTexture); glFramebufferTexture2D(GL_FRAMEBUFFER,GL_TEXTURE_2D,_drawTexture,0); glGenRenderbuffers(1,&_depthRenderbuffer); glBindRenderbuffer(GL_RENDERBUFFER,_depthRenderbuffer); glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,_depthRenderbuffer); _coreFilter = [CIFilter filterWithName:@"CIColorInvert"]; [_coreFilter setDefaults]; NSDictionary *opts = @{ kCIContextWorkingColorSpace : [NSNull null] }; _coreContext = [CIContext contextWithEAGLContext:_context options:opts]; return YES; }
每当层大小更改(在init和方向更改时)分配内存:
- (void)resizeFromLayer:(CAEAGLLayer *)layer { layer.contentsScale = 1; glBindFramebuffer(GL_FRAMEBUFFER,_defaultFramebuffer); glBindRenderbuffer(GL_RENDERBUFFER,_colorRenderbuffer); [_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:layer]; glGetRenderbufferParameteriv(GL_RENDERBUFFER,GL_RENDERBUFFER_WIDTH,&_backingWidth); glGetRenderbufferParameteriv(GL_RENDERBUFFER,GL_RENDERBUFFER_HEIGHT,&_backingHeight); // glCheckFramebufferStatus ... SUCCESS glBindFramebuffer(GL_FRAMEBUFFER,_drawFramebuffer); glBindTexture(GL_TEXTURE_2D,_drawTexture); glTexImage2D(GL_TEXTURE_2D,GL_RGBA,_backingWidth,_backingHeight,GL_UNSIGNED_BYTE,NULL); glBindRenderbuffer(GL_RENDERBUFFER,_depthRenderbuffer); glRenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH_COMPONENT16,_backingHeight); // glCheckFramebufferStatus ... SUCCESS }
绘制方法:
- (void)render:(Scene *)scene { [EAGLContext setCurrentContext:_context]; glBindFramebuffer(GL_FRAMEBUFFER,_drawFramebuffer); // Draw using GLKit,custom shaders,drawArrays,drawElements // Now rendered scene is in _drawTexture glBindFramebuffer(GL_FRAMEBUFFER,_defaultFramebuffer); glBindRenderbuffer(GL_RENDERBUFFER,_colorRenderbuffer); // Create CIImage with our render-to-texture texture _coreImage = [CIImage imageWithTexture:_drawTexture size:CGSizeMake(_backingWidth,_backingHeight) flipped:NO colorSpace:nil]; // Ignore filtering for now; Draw CIImage to current render buffer [_coreContext drawImage:_coreImage inRect:CGRectMake(0,_backingHeight) fromRect:CGRectMake(0,_backingHeight)]; // Present [_context presentRenderbuffer:GL_RENDERBUFFER]; }
注意,绘制场景后,_drawTexture包含渲染场景.我使用Xcode调试工具(Capture OpenGL ES框架)进行检查.
编辑:如果我尝试从一些其他纹理创建CIImage,然后_drawTexture,它正确显示.我的怀疑是,当CIContext尝试通过CIImage呈现时,_drawTexture可能没有准备好或被某种方式锁定.
EDIT2:我也试图用视口清除替换所有绘图代码:
glViewport(0,_backingHeight); glClearColor(0,0.8,1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
结果仍然是黑色的.这表明问题可能是绘制纹理或帧缓冲区的东西.
解决方法
我终于找到了什么问题. iOS上的2个纹理的非强制功能必须具有线性滤波和夹紧到边缘包装:
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_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
我的纹理与屏幕大小相同,但是我没有设置这四个参数.
对于后代:上面的代码是OpenGL ES和CoreImage的互连的完美有效的例子.只需确保你正确地初始化你的纹理!