3

我正在尝试通过多重采样从帧缓冲区中获取像素。它只返回零。我确实按照此处此处的建议调用 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 检查创建帧缓冲区是否成功,因为它们创建成功。我的代码中的错误在哪里?

4

2 回答 2

1

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

像那样:

glResolveMultisampleFramebufferAPPLE()
glBindFramebufferOES(GL_READ_FRAMEBUFFER_APPLE, framebuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer);
glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
于 2013-09-01T22:38:31.243 回答
0

问题不在于 OpenGL,而在于 Cocos3d 渲染(-visit 没有设置一些绘图属性,但 -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;
}
于 2013-09-02T09:17:45.700 回答