Drawing into OpenGL ES framebuffer and getting UIImage from it on iPhone

老子叫甜甜 提交于 2020-01-12 03:53:11

问题


I'm trying to do offscreen rendering of some primitives in OpenGL ES on iOS. The code is as follows:

// context and neccesary buffers
@interface RendererGL
{
   EAGLContext* myContext;
   GLuint framebuffer;
   GLuint colorRenderbuffer;
   GLuint depthRenderbuffer;
}

.m file:

- (id) init
{
    self = [super init];
    if (self)
    {
            // initializing context
        myContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
        [EAGLContext setCurrentContext:myContext];
        [self setupOpenGL]; // creating buffers
    }
    return self;
}

-(void) setupOpenGL
{
    int width = 256;
    int height = 256;

    // generating buffers and binding them as Apple,s tutorial says

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

    glGenRenderbuffersOES(1, &colorRenderbuffer);
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer);
    glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_RGBA8_OES, width, height);
    glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, colorRenderbuffer);

    glGenRenderbuffersOES(1, &depthRenderbuffer);
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
    glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, width, height);
    glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);

    GLenum status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) ;
    if(status != GL_FRAMEBUFFER_COMPLETE_OES) {
        NSLog(@"failed to make complete framebuffer object %x", status);
    }
}

- (UIImage *) renderImage
{
        int width = 256;
        int height = 256;

        [EAGLContext setCurrentContext:myContext];
        glEnable(GL_DEPTH_TEST);

// clear color - cyan       
        glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// trying to draw some primitive - red line
        float line[] = {-0.5f, -0.5f, 0.5f, 0.5f};

        glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer); //should I do this?

        glEnableClientState(GL_VERTEX_ARRAY);
        glVertexPointer(2, GL_FLOAT, 0, line);

        glColor4f(1.0, 0.0, 0.0, 1.0);
        glLineWidth(10);

        glDrawArrays(GL_LINES, 0, 2); // draw line with two points

        [myContext presentRenderbuffer:GL_RENDERBUFFER_OES]; // and this?

// then I grab image from _frameBuffer and return it as UIImage - this part is working
        NSInteger x = 0, y = 0;
        NSInteger dataLength = width * height * 4;
        GLubyte *data = (GLubyte*)malloc(dataLength * sizeof(GLubyte));

        glPixelStorei(GL_PACK_ALIGNMENT, 4);
        glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);

        CGDataProviderRef ref = CGDataProviderCreateWithData(NULL, data, dataLength, NULL);
        CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
        CGImageRef iref = CGImageCreate(width, height, 8, 32, width * 4, colorspace, kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast,
                                        ref, NULL, true, kCGRenderingIntentDefault);


        UIGraphicsBeginImageContext(CGSizeMake(width, height));
        CGContextRef cgcontext = UIGraphicsGetCurrentContext();
        CGContextSetBlendMode(cgcontext, kCGBlendModeCopy);
        CGContextDrawImage(cgcontext, CGRectMake(0.0, 0.0, width, height), iref);
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();

        free(data);
        CFRelease(ref);
        CFRelease(colorspace);
        CGImageRelease(iref);

        return image;
    }

the problem is that -renderImage returning completely cyan image, without red line. What can it be? Did I missed some actions before drawing line?


回答1:


the first problem is that I was creating EAGLContext for OpenGL ES 2.0, but functions which I used were for OpenGL ES 1.1. The solution is to set constant to kEAGLRenderingAPIOpenGLES1

the second - I did not set model and projection matricies (if I use 1.1)

glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrthof(-1.0f, 1.0f, -1.5f, 1.5f, -1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);

after this all works)



来源:https://stackoverflow.com/questions/10936157/drawing-into-opengl-es-framebuffer-and-getting-uiimage-from-it-on-iphone

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!