2013-07-29 39 views
3

我试图从多重采样的帧缓冲中获取像素。它只返回零。我打电话glResolveMultisampleFramebufferAPPLE建议herehere,但我无法弄清楚我的情况是什么问题。带多重采样的iOS上的glReadPixels

首先我创建非多重采样帧缓冲器颜色附件:

GLuint framebuffer, colorRenderbuffer; 

glGenFramebuffersOES(1, &framebuffer); 
glBindFramebufferOES(GL_FRAMEBUFFER_OES, framebuffer); 

glGenRenderbuffersOES(1, &colorRenderbuffer); 
glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer); 
glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_RGBA8_OES, w, h); 
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, colorRenderbuffer); 

然后创建多重采样帧缓冲的颜色和深度附件:

GLuint sampleFramebuffer, sampleColorRenderbuffer, sampleDepthRenderbuffer; 

glGenFramebuffersOES(1, &sampleFramebuffer); 
glBindFramebufferOES(GL_FRAMEBUFFER_OES, sampleFramebuffer); 

glGenRenderbuffersOES(1, &sampleColorRenderbuffer); 
glBindRenderbufferOES(GL_RENDERBUFFER_OES, sampleColorRenderbuffer); 
glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER_OES, 4, GL_RGBA8_OES, w, h); 
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, sampleColorRenderbuffer); 

glGenRenderbuffersOES(1, &sampleDepthRenderbuffer); 
glBindRenderbufferOES(GL_RENDERBUFFER_OES, sampleDepthRenderbuffer); 
glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER_OES, 4, GL_DEPTH_COMPONENT16_OES, w, h); 
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, sampleDepthRenderbuffer); 

然后清除帧缓冲区:

glBindFramebufferOES(GL_FRAMEBUFFER_OES, framebuffer); 
glClear(GL_COLOR_BUFFER_BIT); 

glBindFramebufferOES(GL_FRAMEBUFFER_OES, sampleFramebuffer); 
glViewport(0, 0, w, h); 
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

做我的图画(这是Cocos3D绘图代码):

[cc3Layer visit]; 

然后解析缓冲区:

glBindFramebufferOES(GL_DRAW_FRAMEBUFFER_APPLE, framebuffer); 
glBindFramebufferOES(GL_READ_FRAMEBUFFER_APPLE, sampleFramebuffer); 
glResolveMultisampleFramebufferAPPLE(); 

glBindFramebufferOES(GL_READ_FRAMEBUFFER_APPLE, framebuffer); 

,然后让所有零:

glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, buffer); 

glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer); 

我跳过了成功的两种玻璃的检查与创建帧缓冲,因为它们是成功创建。我的代码中的错误在哪里?

+0

你不会碰巧在使用丢弃吗? –

+0

@JustinMeiners我肯定会,但据我了解,这一步只是为了性能问题。是否有理由提高无效代码的性能? :)另外,它是在glReadPixels和glBindRenderbuffer之后制作的,对吗? – medvedNick

回答

0

问题并没有在OpenGL,但在Cocos3d渲染( - 参观没有设立绘制一些属性,但-drawScene那样)。这是工作代码:

+(UIImage*) takeScreenshotFromScreenRect:(CGRect)rect withResultSize:(CGSize)outSize 
{ 
    CCDirector *director = [CCDirector sharedDirector]; 
    director.nextDeltaTimeZero = YES; 

    rect.origin.x *= CC_CONTENT_SCALE_FACTOR(); 
    rect.origin.y *= CC_CONTENT_SCALE_FACTOR(); 
    rect.size.width *= CC_CONTENT_SCALE_FACTOR(); 
    rect.size.height *= CC_CONTENT_SCALE_FACTOR(); 

    int w = rect.size.width; 
    int h = rect.size.height; 

    int winW = director.winSizeInPixels.width; 
    int winH = director.winSizeInPixels.height; 

    GLuint bufferLength = w * h * 4; 
    GLubyte* buffer = (GLubyte*)malloc(bufferLength); 

    [director pause]; 

    static GLuint framebuffer = 0, colorRenderbuffer; 
    static GLuint sampleFramebuffer, sampleColorRenderbuffer, sampleDepthRenderbuffer; 

    if (framebuffer == 0) 
    { 
     glGenFramebuffersOES(1, &framebuffer); 
     glGenRenderbuffersOES(1, &colorRenderbuffer); 
     glGenFramebuffersOES(1, &sampleFramebuffer); 
     glGenRenderbuffersOES(1, &sampleColorRenderbuffer); 
     glGenRenderbuffersOES(1, &sampleDepthRenderbuffer); 
    } 

    glBindFramebufferOES(GL_FRAMEBUFFER_OES, framebuffer); 

    glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer); 
    glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_RGBA8_OES, winW, winH); 
    glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, colorRenderbuffer); 

    glBindFramebufferOES(GL_FRAMEBUFFER_OES, sampleFramebuffer); 

    glBindRenderbufferOES(GL_RENDERBUFFER_OES, sampleColorRenderbuffer); 
    glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER_OES, director.openGLView.pixelSamples, GL_RGBA8_OES, winW, winH); 
    glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, sampleColorRenderbuffer); 


    glBindRenderbufferOES(GL_RENDERBUFFER_OES, sampleDepthRenderbuffer); 
    glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER_OES, director.openGLView.pixelSamples, GL_DEPTH_COMPONENT16_OES, winW, winH); 
    glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, sampleDepthRenderbuffer); 

    glBindFramebufferOES(GL_FRAMEBUFFER_OES, framebuffer); 
    glClear(GL_COLOR_BUFFER_BIT); 
    glClearColor(150.0/255, 190.0/255, 255.0/255, 1); 

    glBindFramebufferOES(GL_FRAMEBUFFER_OES, sampleFramebuffer); 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    glClearColor(150.0/255, 190.0/255, 255.0/255, 1); 

    [director drawScene]; 

    glBindFramebufferOES(GL_DRAW_FRAMEBUFFER_APPLE, framebuffer); 
    glBindFramebufferOES(GL_READ_FRAMEBUFFER_APPLE, sampleFramebuffer); 
    glResolveMultisampleFramebufferAPPLE(); 

    glBindFramebufferOES(GL_READ_FRAMEBUFFER_APPLE, framebuffer); 

    glReadPixels(rect.origin.x, rect.origin.y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, buffer); 

    GLenum attachments[] = {GL_COLOR_ATTACHMENT0_OES, GL_DEPTH_ATTACHMENT_OES}; 
    glDiscardFramebufferEXT(GL_READ_FRAMEBUFFER_APPLE, 2, attachments); 

     // restoring render buffers from cocos 

    ES1Renderer *renderer = [[CCDirector sharedDirector].openGLView valueForKey:@"renderer_"]; 

    glBindFramebuffer(GL_FRAMEBUFFER_OES, renderer.msaaFrameBuffer); 
    glBindFramebuffer(GL_RENDERBUFFER_OES, renderer.msaaColorBuffer); 


    CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer, bufferLength, NULL); 

    [director resume]; 


    int bitsPerComponent = 8; 
    int bitsPerPixel = 32; 
    int bytesPerRow = 4 * w; 
    CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB(); 
    CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault; 
    CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault; 
    CGImageRef iref = CGImageCreate(w, h, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent); 

    uint32_t* pixels = (uint32_t*)malloc(bufferLength); 
    CGContextRef context = CGBitmapContextCreate(pixels, outSize.width, outSize.height, 8, outSize.width * 4, CGImageGetColorSpace(iref), kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); 

    CGContextTranslateCTM(context, 0, outSize.height); 
    CGContextScaleCTM(context, 1.0f, -1.0f); 

    switch (director.deviceOrientation) 
    { 
     case CCDeviceOrientationPortrait: 
      break; 
     case CCDeviceOrientationPortraitUpsideDown: 
      CGContextRotateCTM(context, CC_DEGREES_TO_RADIANS(180)); 
      CGContextTranslateCTM(context, -outSize.width, -outSize.height); 
      break; 
     case CCDeviceOrientationLandscapeLeft: 
      CGContextRotateCTM(context, CC_DEGREES_TO_RADIANS(-90)); 
      CGContextTranslateCTM(context, -outSize.height, 0); 
      break; 
     case CCDeviceOrientationLandscapeRight: 
      CGContextRotateCTM(context, CC_DEGREES_TO_RADIANS(90)); 
      CGContextTranslateCTM(context, outSize.width * 0.5f, -outSize.height); 
      break; 
    } 

    CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, outSize.width, outSize.height), iref); 
    CGImageRef imageFromContext = CGBitmapContextCreateImage(context); 
    UIImage *outputImage = [UIImage imageWithCGImage:imageFromContext]; 

    CGDataProviderRelease(provider); 
    CGImageRelease(iref); 
    CGContextRelease(context); 
    free(buffer); 
    free(pixels); 

    return outputImage; 
} 
+0

thx。我只测试:glBindRenderbuffer(GL_RENDERBUFFER,colorRenderbuffer);对我的渲染引擎不兼容。也许是因为它使用了一个opengl ES2上下文....或者我永远不会知道! – Vivien

1

您应该在读取像素之前绑定非多重采样颜色渲染缓冲区。

这样的:

glResolveMultisampleFramebufferAPPLE() 
glBindFramebufferOES(GL_READ_FRAMEBUFFER_APPLE, framebuffer); 
glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer); 
glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, buffer); 
+0

感谢您的回答,但该绑定不是必需的。我会更新问题以显示工作代码 – medvedNick