【发布时间】:2014-01-07 15:25:26
【问题描述】:
我正在尝试在我的全屏渲染输出上应用 CoreImage 过滤器,但看起来我遗漏了一些东西,因为我得到了黑屏作为输出。
首先我将整个场景绘制到纹理上。然后我从那个纹理中创建 CoreImage,我最终绘制并呈现它。但我得到的只是黑屏。我遵循 Apple 关于绘制纹理并将 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_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _drawTexture, 0);
glGenRenderbuffers(1, &_depthRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, _depthRenderbuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthRenderbuffer);
_coreFilter = [CIFilter filterWithName:@"CIColorInvert"];
[_coreFilter setDefaults];
NSDictionary *opts = @{ kCIContextWorkingColorSpace : [NSNull null] };
_coreContext = [CIContext contextWithEAGLContext:_context options:opts];
return YES;
}
每当层大小改变时分配内存(在初始化和方向改变时):
- (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, 0, GL_RGBA, _backingWidth, _backingHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glBindRenderbuffer(GL_RENDERBUFFER, _depthRenderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, _backingWidth, _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, 0, _backingWidth, _backingHeight) fromRect:CGRectMake(0, 0, _backingWidth, _backingHeight)];
// Present
[_context presentRenderbuffer:GL_RENDERBUFFER];
}
注意,绘制场景后,_drawTexture 包含渲染场景。我使用 Xcode 调试工具(捕获 OpenGL ES 帧)检查了这一点。
编辑:如果我尝试使用其他纹理创建 CIImage,然后是 _drawTexture,它会正确显示它。我怀疑 _drawTexture 可能没有准备好,或者当 CIContext 尝试通过 CIImage 渲染它时被锁定。
EDIT2:我还尝试用视口清除替换所有绘图代码:
glViewport(0, 0, _backingWidth, _backingHeight);
glClearColor(0, 0.8, 0, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
结果仍然是黑色的。它表明问题可能与绘制纹理或帧缓冲区有关。
【问题讨论】:
-
为什么这会被否决?
-
这很有趣。通常,我会说这是因为 Core Image 上下文不是使用与您的渲染相同的 OpenGL ES 上下文创建的,但在这里看起来设置正确。如果您使用直通着色器并使用渲染纹理将四边形绘制到屏幕上,您能否验证场景是否正确渲染到纹理?最后,如果你没有嫁给 Core Image,我这里有一个小项目:github.com/BradLarson/GPUImage,它也可以做这种风格的 GPU 端后处理。请参阅其中的 CubeExample 示例应用程序,它可以满足您的需求。
-
好的,我使用 _drawTexture 渲染了一个四边形,它是黑色的。所以看起来该纹理或在其上的渲染有问题。也许我错过了渲染到纹理的东西。差异只是我将纹理附加为 GL_COLOR_ATTACHEMNT0 而不是渲染缓冲区。
-
哦,感谢您提出 GPUImage。我实际上对你的项目很熟悉,我可能会回到它,甚至与 CoreImage 一起支持它。
标签: ios opengl-es core-image