标签:glcontext pointer 等等 程序 直接 awr clear gap render
当iOS要处理高性能图形绘制,必要时就是OpenGL。应该说它应该是最后的杀手锏,至少对于非游戏的应用来说是的。因为相比Core Animation和UIkit框架,它不可思议地复杂。
OpenGL提供了Core Animation的基础,它是底层的C接口,直接和iPhone,iPad的硬件通信,极少地抽象出来的方法。OpenGL没有对象或是图层的继承概念。它只是简单地处理三角形。OpenGL中所有东西都是3D空间中有颜色和纹理的三角形。用起来非常复杂和强大,但是用OpenGL绘制iOS用户界面就需要很多很多的工作了。
为了能够以高性能使用Core Animation,你需要判断你需要绘制哪种内容(矢量图形,例子,文本,等等),但后选择合适的图层去呈现这些内容,Core Animation中只有一些类型的内容是被高度优化的;所以如果你想绘制的东西并不能找到标准的图层类,想要得到高性能就比较费事情了。
因为OpenGL根本不会对你的内容进行假设,它能够绘制得相当快。利用OpenGL,你可以绘制任何你知道必要的集合信息和形状逻辑的内容。所以很多游戏都喜欢用OpenGL(这些情况下,Core Animation的限制就明显了:它优化过的内容类型并不一定能满足需求),但是这样依赖,方便的高度抽象接口就没了。
在iOS 5中,苹果引入了一个新的框架叫做GLKit,它去掉了一些设置OpenGL的复杂性,提供了一个叫做CLKView
的UIView
的子类,帮你处理大部分的设置和绘制工作。前提是各种各样的OpenGL绘图缓冲的底层可配置项仍然需要你用CAEAGLLayer
完成,它是CALayer
的一个子类,用来显示任意的OpenGL图形。
大部分情况下你都不需要手动设置CAEAGLLayer
(假设用GLKView),过去的日子就不要再提了。特别的,我们将设置一个OpenGL ES 2.0的上下文,它是现代的iOS设备的标准做法。
尽管不需要GLKit也可以做到这一切,但是GLKit囊括了很多额外的工作,比如设置顶点和片段着色器,这些都以类C语言叫做GLSL自包含在程序中,同时在运行时载入到图形硬件中。编写GLSL代码和设置EAGLayer
没有什么关系,所以我们将用GLKBaseEffect
类将着色逻辑抽象出来。其他的事情,我们还是会有以往的方式。
在开始之前,你需要将GLKit和OpenGLES框架加入到你的项目中,然后就可以实现清单6.14中的代码,里面是设置一个GAEAGLLayer
的最少工作,它使用了OpenGL ES 2.0 的绘图上下文,并渲染了一个有色三角(见图6.15).
清单6.14 用CAEAGLLayer
绘制一个三角形
1 #import "ViewController.h" 2 #import 3 #import 4 5 @interface ViewController () 6 7 @property (nonatomic, weak) IBOutlet UIView *glView; 8 @property (nonatomic, strong) EAGLContext *glContext; 9 @property (nonatomic, strong) CAEAGLLayer *glLayer; 10 @property (nonatomic, assign) GLuint framebuffer; 11 @property (nonatomic, assign) GLuint colorRenderbuffer; 12 @property (nonatomic, assign) GLint framebufferWidth; 13 @property (nonatomic, assign) GLint framebufferHeight; 14 @property (nonatomic, strong) GLKBaseEffect *effect; 15 ? 16 @end 17 18 @implementation ViewController 19 20 - (void)setUpBuffers 21 { 22 //set up frame buffer 23 glGenFramebuffers(1, &_framebuffer); 24 glBindFramebuffer(GL_FRAMEBUFFER, _framebuffer); 25 26 //set up color render buffer 27 glGenRenderbuffers(1, &_colorRenderbuffer); 28 glBindRenderbuffer(GL_RENDERBUFFER, _colorRenderbuffer); 29 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _colorRenderbuffer); 30 [self.glContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:self.glLayer]; 31 glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &_framebufferWidth); 32 glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &_framebufferHeight); 33 34 //check success 35 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { 36 NSLog(@"Failed to make complete framebuffer object: %i", glCheckFramebufferStatus(GL_FRAMEBUFFER)); 37 } 38 } 39 40 - (void)tearDownBuffers 41 { 42 if (_framebuffer) { 43 //delete framebuffer 44 glDeleteFramebuffers(1, &_framebuffer); 45 _framebuffer = 0; 46 } 47 48 if (_colorRenderbuffer) { 49 //delete color render buffer 50 glDeleteRenderbuffers(1, &_colorRenderbuffer); 51 _colorRenderbuffer = 0; 52 } 53 } 54 55 - (void)drawFrame { 56 //bind framebuffer & set viewport 57 glBindFramebuffer(GL_FRAMEBUFFER, _framebuffer); 58 glViewport(0, 0, _framebufferWidth, _framebufferHeight); 59 60 //bind shader program 61 [self.effect prepareToDraw]; 62 63 //clear the screen 64 glClear(GL_COLOR_BUFFER_BIT); glClearColor(0.0, 0.0, 0.0, 1.0); 65 66 //set up vertices 67 GLfloat vertices[] = { 68 -0.5f, -0.5f, -1.0f, 0.0f, 0.5f, -1.0f, 0.5f, -0.5f, -1.0f, 69 }; 70 71 //set up colors 72 GLfloat colors[] = { 73 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 74 }; 75 76 //draw triangle 77 glEnableVertexAttribArray(GLKVertexAttribPosition); 78 glEnableVertexAttribArray(GLKVertexAttribColor); 79 glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 0, vertices); 80 glVertexAttribPointer(GLKVertexAttribColor,4, GL_FLOAT, GL_FALSE, 0, colors); 81 glDrawArrays(GL_TRIANGLES, 0, 3); 82 83 //present render buffer 84 glBindRenderbuffer(GL_RENDERBUFFER, _colorRenderbuffer); 85 [self.glContext presentRenderbuffer:GL_RENDERBUFFER]; 86 } 87 88 - (void)viewDidLoad 89 { 90 [super viewDidLoad]; 91 //set up context 92 self.glContext = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES2]; 93 [EAGLContext setCurrentContext:self.glContext]; 94 95 //set up layer 96 self.glLayer = [CAEAGLLayer layer]; 97 self.glLayer.frame = self.glView.bounds; 98 [self.glView.layer addSublayer:self.glLayer]; 99 self.glLayer.drawableProperties = @{kEAGLDrawablePropertyRetainedBacking:@NO, kEAGLDrawablePropertyColorFormat: kEAGLColorFormatRGBA8}; 100 101 //set up base effect 102 self.effect = [[GLKBaseEffect alloc] init]; 103 104 //set up buffers 105 [self setUpBuffers]; 106 107 //draw frame 108 [self drawFrame]; 109 } 110 111 - (void)viewDidUnload 112 { 113 [self tearDownBuffers]; 114 [super viewDidUnload]; 115 } 116 117 - (void)dealloc 118 { 119 [self tearDownBuffers]; 120 [EAGLContext setCurrentContext:nil]; 121 } 122 @end
图6.15 用OpenGL渲染的CAEAGLLayer
图层
在一个真正的OpenGL应用中,我们可能会用NSTimer
或CADisplayLink
周期性地每秒钟调用-drawRrame
方法60次,同时会将几何图形生成和绘制分开以便不会每次都重新生成三角形的顶点(这样也可以让我们绘制其他的一些东西而不是一个三角形而已),不过上面这个例子已经足够演示了绘图原则了。
标签:glcontext pointer 等等 程序 直接 awr clear gap render
原文地址:http://www.cnblogs.com/EchoHG/p/7623846.html