绘制到OpenGL ES帧缓冲区并在iPhone上从中获取UIImage [英] Drawing into OpenGL ES framebuffer and getting UIImage from it on iPhone

查看:192
本文介绍了绘制到OpenGL ES帧缓冲区并在iPhone上从中获取UIImage的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正试图在iOS上的OpenGL ES中对一些基元进行屏幕外渲染。代码如下:

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文件:

- (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;
    }

问题是-renderImage返回完全青色的图像,没有红线。它能是什么?我在绘制线之前是否错过了一些操作?

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

推荐答案

第一个问题是我正在为OpenGL ES 2.0创建EAGLContext,但是功能我使用的是OpenGL ES 1.1。解决方案是将常量设置为kEAGLRenderingAPIOpenGLES1

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

第二个 - 我没有设置模型和投影基质(如果我使用1.1)

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

此后全部有效)

这篇关于绘制到OpenGL ES帧缓冲区并在iPhone上从中获取UIImage的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆