首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >CIFilter在OpenGL纹理渲染中的应用

CIFilter在OpenGL纹理渲染中的应用
EN

Stack Overflow用户
提问于 2014-01-07 15:25:26
回答 1查看 2.6K关注 0票数 12

我试图在我的全屏渲染输出上应用CoreImage过滤器,但是看起来我缺少了什么,因为我获得了黑色屏幕作为输出。

首先,我把整个场景画成一个纹理。然后我用这个纹理创建CoreImage,我最终画出来并呈现出来。但我只得到了黑色的屏幕。我按照苹果公司的指导方针绘制纹理,并将CoreImage与OpenGLES集成: WWDC2012 511和programmingguide/WorkingwithEAGLContexts/WorkingwithEAGLContexts.html

以下是相关代码:

渲染器:

代码语言:javascript
复制
@interface Renderer () {
  EAGLContext* _context;
  GLuint _defaultFramebuffer, _drawFramebuffer, _depthRenderbuffer, _colorRenderbuffer, _drawTexture;
  GLint _backingWidth, _backingHeight;
  CIImage *_coreImage;
  CIFilter *_coreFilter;
  CIContext *_coreContext;
}

初始化方法:

代码语言:javascript
复制
- (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;
}

每当层大小发生变化时( init和方位变化),则会有异种存储器:

代码语言:javascript
复制
- (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
}

绘制方法:

代码语言:javascript
复制
- (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:我还尝试将所有绘图代码替换为仅清除视图:

代码语言:javascript
复制
  glViewport(0, 0, _backingWidth, _backingHeight);
  glClearColor(0, 0.8, 0, 1);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

结果仍然是黑色的。这表明问题可能是具有绘制纹理或帧缓冲区的问题。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-01-07 21:37:29

我终于找到了问题所在。iOS上的2种纹理的非功率必须具有线性滤波和夹紧来进行边缘包装:

代码语言:javascript
复制
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互连的完美例子。只需确保你初始化你的纹理正确!

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20975434

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档