2013-07-29 118 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