• CAEAGLLayer


    CAEAGLLayer

    当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的复杂性,提供了一个叫做CLKViewUIView的子类,帮你处理大部分的设置和绘制工作。前提是各种各样的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
    View Code

    图6.15 用OpenGL渲染的CAEAGLLayer图层

    在一个真正的OpenGL应用中,我们可能会用NSTimerCADisplayLink周期性地每秒钟调用-drawRrame方法60次,同时会将几何图形生成和绘制分开以便不会每次都重新生成三角形的顶点(这样也可以让我们绘制其他的一些东西而不是一个三角形而已),不过上面这个例子已经足够演示了绘图原则了。

  • 相关阅读:
    C++解析-外传篇(3):动态内存申请的结果
    C++解析-外传篇(2):函数的异常规格说明
    C++解析-外传篇(1):异常处理深度解析
    C++解析(31):自定义内存管理(完)
    Fisherfaces 算法的具体实现源码
    Philipp Wagner
    人脸识别中截取面部的实现方法
    OpenCV Haar AdaBoost源码改进据说是比EMCV快6倍
    win10系统下载地址
    人脸识别中的检测(在Opencv中加入了QT)
  • 原文地址:https://www.cnblogs.com/EchoHG/p/7623846.html
Copyright © 2020-2023  润新知