我正在尝试在全屏渲染输出上应用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;
}
每当层大小更改时(在初始化和方向更改时)的Alloc内存:
- (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);
结果仍然是黑色的。这表明问题可能出在绘制纹理或帧缓冲区上。
我终于找到了问题所在。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互连的完全有效的示例。只要确保您正确初始化纹理即可!
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句