ios Rendering
ios Architektur
UIKit (Cocoa Touch) A composable, reusable, declarative, real-world inspired animation, and interaction system Framework für ios Apps Objective C Model View Controller Pattern
Core Graphics (Quartz)
Core Graphics vom GUI Toolkit verwendet. 2D Grafik Engine, die leichtgewichtiges Rendern unabhängig von Auflösung und Device nutzt einen Grafikkontext (CGContextRef), der Zusatzinformationen kapselt, um Bilder für Geräte wie PDF Dateien, Bitmap, Fenster, Layer oder Display zu malen. Ein Kontext kann wie eine drawing destination verstanden werden Painters Model
Demo Core Graphics
CG - Step by Step Ein neues Projekt erzeugen 1.In der XCode Entwicklungsumgebung ein neues Projekt erzeugen. 2.Auswahl der Single View Application option 3.Zum Beispiel als Projektname und Klassen-prefix: draw2d. Eine UIView abgeleitete Klasse erzeugen 1.Um Grafik auf einer View zu malen, brauchen wir eine Subklasse der UIView-Klasse. 2.Dort wird die drawrect-methode überschrieben. 3.Im ProjektNavigator wird im draw2d folder NewFile ausgewählt. 4.Im NewFile Fenster das Objective-C class icon auswählen, dann Next. 5.Im nächsten Options-Screen wird Subclass von menue in UIView geändert. 6.Speichern der Subclass als draw2d. 7.Im draw2dviewcontroller.xib file die UIView Komponente im View object auswählen. 8.Aufruf des Identity Inspector (View -> Utilities -> Show Identity Inspector), dort Class von UIView in unseren Klassennamen draw2d ändern.
CG - Step by Step #import "draw2d.h" @implementation draw2d - (id)initwithframe:(cgrect)frame { if (self = [super initwithframe:frame]) { // Initialization code } return self; } - (void)drawrect:(cgrect)rect { // Drawing code }.. @end
CG - Step by Step - (void)drawrect:(cgrect)rect { CGContextRef context = UIGraphicsGetCurrentContext(); Die Linienbreite wird für den Kontext schon mal gesetzt. CGContextSetLineWidth(context, 2.0); Eine Referenz-Farbe (hier opaque blue) wird definiert (RGBA).: CGFloat components[] = {0.0, 0.0, 1.0, 1.0}; CGColorRef color = CGColorCreate(colorspace, components); Diese Farbe wird für Linien in diesem Kontext verwendet. CGContextSetStrokeColorWithColor(context, color); Startpunkt der Linie, links oben: CGContextMoveToPoint(context, 0, 0); Der Endpunkt soll bei 300, 400 sein. CGContextAddLineToPoint(context, 300, 400); Nun kann die Linie gezeichnet werden. Anschließend werden colorspace und color Objekte freigegeben. CGContextStrokePath(context); CGColorSpaceRelease(colorspace); CGColorRelease(color); }
CG - Das Ergebnis
3D in ios
OpenGL ES in ios Framebuffer Object(FBO) als Render Target ios spezifische Anpassung der FBOs Allocation und Verwendung spezieller Layer
Core Animation
Core Animation Layer basiertes zeichnen Compositor mit HW Unterstützung
Layer in ios OpenGL ES verwaltet seine States in Render Kontexten Umschalten zwischen Apps somit möglich EAGL ist die ios Implementierung einer OpenGL ES Render Context
Layer in ios
Framebuffer Objects Extension in OpenGL Einfaches rendern von Puffern, die nicht vom Windowing System zur Verfügung gestellt werden Off Screen Rendering FBO mehrfach verwendbar in GL Kontexten FBO kann als Input für weiteres Zeichnen verwendet werden
Framebuffer Objects
Beispiel OpenGL ES OffScreen
1. Generieren und Binden des FBO // Anlegen der Framebuffer-Referenz GLuint framebuffer; // glgenframebuffers generiert Framebuffer Object Namen. // void glgenframebuffers(glsizei n, GLuint *ids); // n = Anzahl der Objekt Namen // *ids = Array zur Speicherung der Namen glgenframebuffers(1, &framebuffer); // glbindframbuffer bindet einen Framebuffer an ein Framebuffer Target, // welches es ermöglicht Schreib- und Lese-Operationen getrennt voneinander zu verarabeiten. // void glbindframebuffer(glenum target, GLuint framebuffer); // target = Framebuffer Target: GL_FRAMEBUFFER {GL_DRAW_FRAMEBUFFER & GL_READ_FRAMEBUFFER} glbindframebuffer(gl_framebuffer, framebuffer);
2. Generieren und Binden eines Images // Anlegen der DepthRenderbufferreferenz GLuint depthrenderbuffer; // glgenrenderbuffers generiert Renderbuffer Object Namen. // void glgenrenderbuffers(glsizei n, GLuint *renderbuffers); // n = Anzahl der Objekt Namen // *renderbuffers = Array zur Speicherung der Namen glgenrenderbuffers(1, &depthrenderbuffer); // glbindframbuffer bindet einen Framebuffer an ein Renderbuffer Target. // void glbindrenderbuffer(glenum target, GLuint renderbuffer); // target = Renderbuffer Target ist immer: GL_RENDERBUFFER glbindrenderbuffer(gl_renderbuffer, depthrenderbuffer);
3. Erstellen des Renderbuffer Speichers // glrenderbufferstorage erstellt und initialisiert ein Renderbuffer Object Store. // Da in diesem Beispiel ein Depth-Renderbuffer erzeugt wird, muss auch das // Pixelformat entsprechend gewählt werden. // void glrenderbufferstorage(glenum target, GLenum internalformat, // GLsizei width, GLsizei height); // target = Renderbuffer Target immer GL_RENDERBUFFER // internalformat = Gibt das Pixelformat an. Folgende Konstanten sind möglich: // GL_RGBA4, GL_RGB565, GL_RGB5_A1,GL_DEPTH_COMPONENT16, or GL_STENCIL_INDEX8 // width/heigth = Maße des Buffers in Pixel glrenderbufferstorage(gl_renderbuffer, GL_DEPTH_COMPONENT16, width, height); // glframebufferrenderbuffer hängt den Renderbuffer an ein Framebuffer Object // void glframebufferrenderbuffer(glenum target, GLenum attachment, // GLenum renderbuffertarget, GLuint renderbuffer); // target = Renderbuffer Target immer GL_FRAMEBUFFER // attachment = Gibt den Einhängepunkt an. // Je nach Buffertyp sind hier folgende Konstanten möglich: // GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT // renderbuffer = Referenz auf Renderbuffer Objekt glframebufferrenderbuffer(gl_framebuffer, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthrenderbuffer);
4. Vollständigkeitsprüfung // glcheckframebufferstatus Prüft ob das Framebuffer Object vollständig ist. // Nach erfolgreicher Prüfung kann dieses dann verwendet werden GLenum status = glcheckframebufferstatus(gl_framebuffer) ; if(status = GL_FRAMEBUFFER_COMPLETE) { NSLog(@"failed to make complete framebuffer object %x", status); } return YES; }
Beispiel + Demo OpenGL ES OnScreen
+ (Class) layerclass { return [CAEAGLLayer class]; } 1. UIView
2. Layer und Context CAEAGLLayer *eagllayer = (CAEAGLLayer *)self.layer; // Konfiguration als undurchlässig aus Performancegründen eagllayer.opaque = TRUE; // Konfigurieren des Layers. Dies bezieht sich auf das Farbformat // -> keaglcolorformatrgba8 und ob die gerenderten Daten verworfen // werden sollen // nachdem sie angezeigt wurden -> keagldrawablepropertyretainedbacking eagllayer.drawableproperties = [NSDictionary dictionarywithobjectsandkeys: [NSNumber numberwithbool:false], keagldrawablepropertyretainedbacking, keaglcolorformatrgba8, keagldrawablepropertycolorformat, nil]; // Beispiel zum Allokieren eines OpenGL ES2.0 Kontextes. EAGLContext* mycontext = [[EAGLContext alloc] initwithapi:keaglrenderingapiopengles2]; // Um später die gerenderten Bilder anzeigen zu können muss der Kontext // noch aktiviert werden. [EAGLContext setcurrentcontext: mycontext];
3. ColorRenderBuffer GLuint colorrenderbuffer; glgenrenderbuffers(1, &colorrenderbuffer); glbindrenderbuffer(gl_renderbuffer, colorrenderbuffer); // Verknüpfung des Renderbuffer Objektes mit dem OpenGL ES2.0 Kontext und // dem Core Animation Layer auf den gerendert werden soll. [mycontext renderbufferstorage:gl_renderbuffer fromdrawable:eagllayer]; glframebufferrenderbuffer(gl_framebuffer,gl_color_attachment0,gl_renderb UFFER, colorrenderbuffer);
3. ColorRenderBuffer - (void)render { //... // Initialisiere Beispieldaten //... // Setzen des EAGL Kontextes [EAGLContext setcurrentcontext:mycontext]; //... glclearcolor(0.5f, 0.4f, 0.5f, 1.0f); glclear(gl_color_buffer_bit); //... // Initialisieren und Aktivieren von Vertexarrays //... glenablevertexattribarray(attrib_color); // Tatsächliches Zeichnen der Arrays gldrawarrays(gl_triangle_strip, 0, 4); // Erneutes Binden des ColorRenderBuffers in den aktuellen Kontext } glbindrenderbuffer(gl_renderbuffer, colorrenderbuffer); // Propagieren des ColorRenderBuffers um seine Anzeige auf dem Screen zu triggern [context presentrenderbuffer:gl_renderbuffer];
Bildschirminhalt auslesen GLint backingwidth, backingheight; glbindrenderbufferoes(gl_renderbuffer_oes, colorrenderbuffer); glgetrenderbufferparameterivoes(gl_renderbuffer_oes,gl_renderbuffer_width_oes, &backingwidth); glgetrenderbufferparameterivoes(gl_renderbuffer_oes,gl_renderbuffer_height_oes, &backingheight); NSInteger x = 0, y = 0; NSInteger width = backingwidth; NSInteger height = back ngheight; 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);