iOS上带有多采样的glReadPixels



我正在尝试通过多重采样从帧缓冲区获取像素。它只返回零。我确实按照这里和这里的建议调用了glResolveMultisampleFramebufferAPPLE,但我不知道我的情况下有什么问题。

首先,我创建了带有颜色附件的非多采样帧缓冲区:

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);

我跳过了创建帧缓冲区成功的两次gl检查,因为它们正在成功创建。我的代码中的错误在哪里?

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

像这样:

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

问题不在OpenGL中,而是在Cocos3d渲染中(-visive没有为绘图设置一些属性,但-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;
}

相关内容

  • 没有找到相关文章

最新更新