CAEAGLLayer

CAEAGLLayer

当iOS要处理高性能图形绘制,必要时就是OpenGL。应该说它应该是最终的特长,至少对于非游戏的使用来说是的。因为相相比较Core
Animation和UIkit框架,它不堪设想地复杂。

OpenGL提供了Core
Animation的底蕴,它是底层的C接口,直接和One plus,华为平板的硬件通信,极少地抽象出来的情势。OpenGL没有目的可能图层的持续概念。它只是简短地处理三角形。OpenGL中具有东西都是3D空间中有颜色和纹理的三角。用起来卓殊复杂和强有力,不过用OpenGL绘制iOS用户界面就需要广大广大的做事了。

为了可以以高性能使用Core
Animation,你需要看清你需要绘制哪一类内容(矢量图形,例子,文本,等等),但后选取适当的图层去显示那个内容,Core
Animation中唯有部分类此外始末是被低度优化的;所以一旦你想绘制的事物并不能够找到专业的图层类,想要获得高性能就相比费事情了。

因为OpenGL根本不会对您的情节开展假如,它可以绘制得分外快。利用OpenGL,你可以绘制任何你领会必要的汇聚音信和形制逻辑的情节。所以重重游戏都爱不释手用OpenGL(这一个情状下,Core
Animation的界定就明摆着了:它优化过的情节类型并不一定能满意急需),不过如此借助,方便的可观抽象接口就没了。

在iOS
5中,苹果引入了一个新的框架叫做GL基特,它去掉了一部分安装OpenGL的错综复杂,提供了一个名叫CLKViewUIViewC语言,的子类,帮你处理大部分的装置和制图工作。前提是五花八门的OpenGL绘图缓冲的底部可部署项依然需要您用CAEAGLLayer完成,它是CALayer的一个子类,用来展示任意的OpenGL图形。

绝大多数气象下你都不需要手动设置CAEAGLLayer(假诺用GLKView),过去的光景就绝不再提了。特其它,我们将设置一个OpenGL
ES 2.0的上下文,它是现代的iOS设备的业内做法。

即使不需要GL基特也得以成功这一切,可是GL基特(Kit)囊括了许多非凡的行事,比如设置终点和局部着色器,那一个皆以类C语言叫做GLSL自包含在程序中,同时在运作时载入到图片硬件中。编写GLSL代码和安装EAGLayer未曾怎么关联,所以我们将用GLKBaseEffect类将着色逻辑抽象出来。其他的事情,我们仍旧会有过去的措施。

在先河在此之前,你需要将GL基特(Kit)和OpenGLES框架插手到你的序列中,然后就足以兑现清单6.14中的代码,里面是安装一个GAEAGLLayer的足足工作,它利用了OpenGL
ES 2.0 的绘图上下文,并渲染了一个化险为夷三角(见图6.15).

清单6.14 用CAEAGLLayer绘制一个三角形

C语言 1C语言 2

  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

View Code

 

 

图6.15 用OpenGL渲染的CAEAGLLayer图层

在一个当真的OpenGL应用中,我们可能会用NSTimerCADisplayLink周期性地每秒钟调用-drawRrame措施60次,同时会将几何图形生成和制图分开以便不会每趟都重复生成三角形的巅峰(这样也足以让我们绘制其他的部分事物而不是一个三角形而已),不过下面这么些事例已经足足演示了绘图原则了。