iphone - iOS OpenGL ES 2.0: Offscreen render and save the result to an UIImage -
i'm using opengl es render special effects, don't want show user, want save result uiimage, can please me?
this code i'm using, can image contains red clear color use, no geometry drawing shown.
#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 works, since image, image contains red color used 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 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 make complete framebuffer object %x", status); } } - (void) renderimage { glenum error = gl_no_error; glclearcolor(1, 0, 0, 1); //red clear color, can 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 %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 %d, line %d",error,__line__); } glfinish(); error = glgeterror(); if (error != gl_no_error) { nslog(@"error happend, error %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 %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
i had similar problem - render lines , uiimage. used opengl es 1.1 , multisampling. removed additional code not refers rendering , opengl error checks. can find full code here: osprenderergl. also, sorry one-for-all method.
@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 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; }
Comments
Post a Comment