2013-08-16 15 views
6

私はOpenGL ESを使用して特殊効果を表示していますが、これをユーザーに表示したくないだけで、結果をUIImage誰でも私を助けてくれますか?iOS OpenGL ES 2.0:オフスクリーンでレンダリングし、結果をUIImageに保存します。

これは私が使用しているコードですが、使用する赤いクリアカラーが含まれていますが、ジオメトリの図は表示されません。

#import "RendererGL.h" 
#import <GLKit/GLKit.h> 
#import <UIKit/UIKit.h> 
#import <OpenGLES/EAGL.h> 
#import <OpenGLES/EAGLDrawable.h> 
#import <OpenGLES/ES2/glext.h> 
#import <QuartzCore/QuartzCore.h> 

static NSInteger WIDTH_IN_PIXEL = 400; 
static NSInteger HEIGHT_IN_PIXEL = 300; 

typedef struct { 
    GLKVector3 positionCoords; 
} 
SceneVertex; 

static const SceneVertex vertices[] = 
{ 
    {{-0.5f, -0.5f, 0.0}}, // lower left corner 
    {{ 0.5f, -0.5f, 0.0}}, // lower right corner 
    {{-0.5f, 0.5f, 0.0}} // upper left corner 
}; 

@implementation RendererGL 
{ 
    EAGLContext* _myContext; 

    GLuint _framebuffer; 
    GLuint _colorRenderbuffer; 
    GLuint _depthRenderbuffer; 

    GLuint _vertexBufferID; 

    GLKBaseEffect *_baseEffect; 
} 

- (id) init 
{ 
    self = [super init]; 
    if (self) 
    { 
     _myContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; 
     [EAGLContext setCurrentContext:_myContext]; 
     [self setupOffscreenBuffer]; 
     [self setUpEffect]; 
     [self renderImage]; 
     [self saveImage]; //this do works, since I get an image, but the image only contains the red color I used to clear 
    } 

    return self; 
} 

-(void)setUpEffect 
{ 
    _baseEffect = [[GLKBaseEffect alloc] init]; 
    _baseEffect.useConstantColor = GL_TRUE; 
    _baseEffect.constantColor = GLKVector4Make(0.0f, 0.0f, 1.0f, 1.0f); 
} 

//this code is from apples document 
-(void)setupOffscreenBuffer 
{ 
    glGenFramebuffers(1, &_framebuffer); 
    glBindFramebuffer(GL_FRAMEBUFFER, _framebuffer); 

    glGenRenderbuffers(1, &_colorRenderbuffer); 
    glBindRenderbuffer(GL_RENDERBUFFER, _colorRenderbuffer); 
    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, WIDTH_IN_PIXEL, HEIGHT_IN_PIXEL); 
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _colorRenderbuffer); 

    glGenRenderbuffers(1, &_depthRenderbuffer); 
    glBindRenderbuffer(GL_RENDERBUFFER, _depthRenderbuffer); 
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, WIDTH_IN_PIXEL, HEIGHT_IN_PIXEL); 
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthRenderbuffer); 

    GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER) ; 
    if(status != GL_FRAMEBUFFER_COMPLETE) { 
     NSLog(@"failed to make complete framebuffer object %x", status); 
    } 
} 

- (void) renderImage 
{ 
    GLenum error = GL_NO_ERROR; 

    glClearColor(1, 0, 0, 1); //red clear color, this can be seen 
    glClear(GL_COLOR_BUFFER_BIT); 

    glEnable(GL_DEPTH_TEST); 

    [_baseEffect prepareToDraw]; 

    glGenBuffers(1, &_vertexBufferID); 
    glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferID); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); 
    error = glGetError(); 
    if (error != GL_NO_ERROR) { 
     NSLog(@"error happend, error is %d, line %d",error,__LINE__); 
    } 

    glEnableVertexAttribArray(GLKVertexAttribPosition); 
    glVertexAttribPointer(GLKVertexAttribPosition,3,GL_FLOAT, GL_FALSE, sizeof(SceneVertex), NULL);     
    glDrawArrays(GL_TRIANGLES,0,3); 
    error = glGetError(); 
    if (error != GL_NO_ERROR) { 
     NSLog(@"error happend, error is %d, line %d",error,__LINE__); 
    } 

    glFinish(); 
    error = glGetError(); 
    if (error != GL_NO_ERROR) { 
     NSLog(@"error happend, error is %d, line %d",error,__LINE__); 
    } 
} 

-(void)saveImage 
{ 
    GLenum error = GL_NO_ERROR; 

    NSInteger x = 0, y = 0; 
    NSInteger dataLength = WIDTH_IN_PIXEL * HEIGHT_IN_PIXEL * 4; 
    GLubyte *data = (GLubyte*)malloc(dataLength * sizeof(GLubyte)); 

    glPixelStorei(GL_PACK_ALIGNMENT, 4); 
    glReadPixels(x, y, WIDTH_IN_PIXEL, HEIGHT_IN_PIXEL, GL_RGBA, GL_UNSIGNED_BYTE, data); 
    NSData *pixelsRead = [NSData dataWithBytes:data length:dataLength]; 

    error = glGetError(); 
    if (error != GL_NO_ERROR) { 
     NSLog(@"error happend, error is %d, line %d",error,__LINE__); 
    } 

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


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

    NSData *d = UIImageJPEGRepresentation(image, 1); 
    NSString *documentDirPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0]; 
    static NSInteger imageNO = 1; 
    imageNO++; 
    NSString *savingPath = [documentDirPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%d.jpg",imageNO]]; 
    BOOL succ = [d writeToFile:savingPath atomically:NO]; //is succeeded 

    UIGraphicsEndImageContext(); 

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

@end 
+0

なぜpixelsReadという名前のNSDataオブジェクトを作成したのですか? –

+0

あなたのコードを共有できますか?実際にあなたのイメージオブジェクトをこのクラスにどのように渡しますか? RendererGLクラスのスーパークラスは何ですか? –

+0

glkviewで描画するにはどうすればいいですか? –

答えて

1

eglSwapBuffers()の呼び出しはありません。 Renderbufferにレンダリングした場合でも、PowerVRでフレームのレンダリングを開始するためにはこれが必要です。で、サンプルコードを参照してください: - いくつかの線を描画し、UIImageを取得する

http://processors.wiki.ti.com/index.php/Render_to_Texture_with_OpenGL_ES

+0

彼はそれをユーザーに見せたくないので、どうして彼はスワップする必要がありますか? –

+1

PowerVRには遅延レンダリングデザインがあります。これは基本的に、eglSwapBuffers()が呼び出されるまでフレームのレンダリングを開始しないことを意味します。これは、統合できるglDrawArrays()への追加の呼び出しがある場合に備えて行われます。 EGLドライバは、RenderBufferがダブルバッファではないことを理解していますが、PVRShellのように既に別の場所で実行されていない限り、呼び出す必要があります。 – ClayMontgomery

+0

@ClayMontgomery OpenGL ES 2.0にはeglSwapBuffers()などのメソッドがないようですが、どうすればいいですか? – CarmeloS

6

私は非常によく似た問題を抱えていました。 OpenGL ES 1.1とマルチサンプリングを使用しました。私は、レンダリングといくつかのOpenGLエラーチェックを参照していない追加のコードをいくつか削除しました。完全なコードはOSPRendererGLです。また、私の1対1のすべての方法には申し訳ありません。

@interface OSPRendererGL 
{ 
    EAGLContext* myContext; 
    GLuint framebuffer; 
    GLuint colorRenderbuffer; 
    GLuint depthRenderbuffer; 
    GLuint _vertexArray; 
    GLuint _vertexBuffer; 
    GLuint resolveFramebuffer; 
    GLuint msaaFramebuffer, msaaRenderbuffer, msaaDepthbuffer; 

    int width; 
    int height; 
} 

@implementation OSPRendererGL 

- (id) init 
{ 
    self = [super init]; 
    if (self) 
    { 
     myContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1]; 
     [EAGLContext setCurrentContext:myContext]; 
     [self setupOpenGL]; 
     [EAGLContext setCurrentContext:nil]; 
     width = 256; 
     height = 256; 
    } 
    return self; 
} 

-(void) setupOpenGL 
{ 
    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); 

    glGenFramebuffersOES(1, &msaaFramebuffer); 
    glGenRenderbuffersOES(1, &msaaRenderbuffer); 

    glBindFramebufferOES(GL_FRAMEBUFFER_OES, msaaFramebuffer); 
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, msaaRenderbuffer); 

    glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER_OES, 4, GL_RGBA8_OES, width, height); 
    glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, msaaRenderbuffer); 

    glGenRenderbuffersOES(1, &msaaDepthbuffer); 
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, msaaDepthbuffer); 
    glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER_OES, 4, GL_DEPTH_COMPONENT16_OES, width, height); 
    glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, msaaDepthbuffer); 

} 

-(UIImage *) renderImageAtZoom:(int)zoom 
{ 
    CGRect b = CGRectMake(0, 0, width, height); 
    OSPCoordinateRect r = OSPRectForMapAreaInRect([self mapArea], b); 

    double_scale = b.size.width/r.size.x; 
    double scale = 1.0/_scale; 

    [EAGLContext setCurrentContext:myContext]; 

    glBindFramebuffer(GL_FRAMEBUFFER_OES, msaaFramebuffer); 
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, msaaRenderbuffer); 

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

    glPushMatrix(); 

    glScalef(_scale, _scale, 1); 
    glTranslatef(-r.origin.x, -r.origin.y, 0); 

    glEnableClientState(GL_VERTEX_ARRAY); 
    glEnableClientState(GL_TEXTURE_COORD_ARRAY); 
    glEnable(GL_LINE_SMOOTH); 
    glEnable(GL_POINT_SMOOTH); 
    glEnable(GL_BLEND); 

    glClearColor(1, 1, 1, 1); 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

    // rendering here 

    glPopMatrix(); 

    // msaa 

    glBindFramebufferOES(GL_READ_FRAMEBUFFER_APPLE, msaaFramebuffer); 
    glBindFramebufferOES(GL_DRAW_FRAMEBUFFER_APPLE, framebuffer); 

    glResolveMultisampleFramebufferAPPLE(); 

    glBindFramebuffer(GL_FRAMEBUFFER_OES, framebuffer); 
    glBindRenderbufferOES(GL_RENDERBUFFER, colorRenderbuffer); 

    // grabbing image from FBO 

    GLint backingWidth, backingHeight; 

    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth); 
    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight); 

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

    [EAGLContext setCurrentContext:nil]; 

    return image; 
} 
関連する問題