OpenGL ES for iOS学习笔记(一)

几个基本概念:

  • 帧缓存:内存中用于储存渲染结果的地方,可以有任意数量,分为前帧缓存后帧缓存,渲染结果被保存在后帧缓存中,需要显示的时候变为前帧缓存,显示完成后前帧缓存又会再次变为后帧缓存。在iOS中前后帧缓存的切换是由系统控制的,用户无法操作。

  • 图层:在Core Animation中,同一时刻可以存在任意数量的图层,一幅图对应的帧缓存由多个图层混合而成。

GLKit是iOS基于openGL实现的一个框架,目的在于简化OpenGL的操作,其提供了GLKViewGLKViewController,openGL相关的操作需要在这两个类中的子类中完成。下面的例子将展示如何使用OpenGl在屏幕中绘制一个三角形,流程如下:

  1. 生成上下文 EAGLContext
  2. 设置清理颜色和渲染颜色,清理颜色(画布颜色) glClearColor,渲染颜色由 GLKBaseEffect 管理
  3. 为GPU分配缓存,并将数据从CPU管理内存复制到GPU缓存
    3.1 生成标识符 glGenBuffers
    3.2 将标识符绑定内存 glBindBuffer
    3.3 复制数据 glBufferData
  4. 绘制在 glkView:drawInRect 中完成
    4.1 清理颜色 glClear
    4.2 渲染 glEnableVertexAttribArray -> glVertexAttribPointer->glDrawArrays
  5. 清理上下文 glDeleteBuffers

声明文件:OpenGLESViewController.h

#import <GLKit/GLKit.h>
@interface OpenGLESViewController : GLKViewController{
    //存放了缓存标识符
   GLuint vertexBufferID;
}
//openGL ES的对外接口,里面处理了openGL各个版本的不同,并提供简易操作
@property (strong, nonatomic) GLKBaseEffect *baseEffect;
@end

实现文件:OpenGLESViewController.m

#import "OpenGLES_Ch2_1ViewController.h"

@implementation OpenGLES_Ch2_1ViewController

//告诉编译器使用baseEffect,而不是加了下划线的_baseEffect
@synthesize baseEffect;

static const GLKVector3 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
};

- (void)viewDidLoad
{
   [super viewDidLoad];
   
   // 验证view的类型
   GLKView *view = (GLKView *)self.view;
   NSAssert([view isKindOfClass:[GLKView class]],
      @"View controller's view is not a GLKView");
   
    //opengl 是基于c语言的,这就意味着需要上下文来保存一些状态
    //kEAGLRenderingAPIOpenGLES2 表示使用opengl es 2.0
   view.context = [[EAGLContext alloc] 
      initWithAPI:kEAGLRenderingAPIOpenGLES2];
   
   //将view.context设为接下来运算所要用到的上下文
   [EAGLContext setCurrentContext:view.context];
   
   //opengl各个版本有明显的不同,这里GLKBaseEffect帮我们做了统一的处理
   //GLKBaseEffect在这个例子中用于颜色渲染
   self.baseEffect = [[GLKBaseEffect alloc] init];
   self.baseEffect.useConstantColor = GL_TRUE;
    
    //这里返回GLKVector4结构体
   self.baseEffect.constantColor = GLKVector4Make(
      1.0f, // Red
      1.0f, // Green
      1.0f, // Blue
      1.0f);// Alpha
   
    //清除颜色,清理帧缓存的时候,将其全部设置为这种颜色
    //buffer对应的是整块屏幕,屏幕中并不是所有部分都会被渲染,这里相当于设置画布的颜色
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // background color
   
    //下面三步:生成GPU专用缓存
    /*1:为缓存生成一个独一无二的标识符,储存在vertexBufferID中
        第一个参数表示要生成的标识符的数量*/
    glGenBuffers(1,&vertexBufferID);
    
    //2:将标识符绑定缓存
    glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID);
    
    //3:复制数据到该缓存中 cpu->gpu
    glBufferData(                  // STEP 3
      GL_ARRAY_BUFFER,  //GL_ARRAY_BUFFER表示一个顶点数组,还有个选项GL_ELEMENT_ARRAY_BUFFER
      sizeof(vertices), // 需要复制的字节数
      vertices,         // 指向数组的指针
      GL_STATIC_DRAW);  // 缓存在未来的运算中会如何使用,这里表示这段缓存修改较少,GL_DYNAMIC_DRAW表示修改较多
}

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
   [self.baseEffect prepareToDraw];
   
   // 之前调用glClearColor设置了清理颜色,这里进行颜色清理
   glClear(GL_COLOR_BUFFER_BIT);
   
   // 启用顶点缓存渲染操作
   //告诉opengl使用多维数组保存数据
   glEnableVertexAttribArray(GLKVertexAttribPosition);

	//多维数组渲染顶点时,数据的读取方式
   glVertexAttribPointer(
      GLKVertexAttribPosition, //告诉opengl当前缓存包含每个顶点的位置信息
      3,                   // 每个顶点用三维向量表示
      GL_FLOAT,            // 向量的每个值是float类型
      GL_FALSE,            // 小数点固定数据是否可以被改变
      sizeof(GLKVector3), // “步幅”,每个顶点需要多少字节保存,这样opengl就知道读取一个顶点后需要跳过多少字节到下一个顶点,使用 sizeof(SceneVertex) 表示缓存中没有额外字节,顶点与顶点之间没有间隔
      NULL);               // 从缓存的开始位置访问
                                   
   // 开始渲染
   glDrawArrays(GL_TRIANGLES,      // 如何处理顶点缓存内的顶点数据,这里告诉opengl去渲染三角形
      0,  // 所需渲染的第一个顶点的位置
      3); // 需要渲染顶点的数量
}

- (void)viewDidUnload
{
   [super viewDidUnload];
   GLKView *view = (GLKView *)self.view;
   [EAGLContext setCurrentContext:view.context];
   if (0 != vertexBufferID){
      glDeleteBuffers (1,&vertexBufferID);
       
    //设置为0是为了避免缓存被删除后还使用其无效的标识符
      vertexBufferID = 0;
   }
   
   // Stop using the context created in -viewDidLoad
   ((GLKView *)self.view).context = nil;
    
    //清除缓存,缓存引用计数为0
   [EAGLContext setCurrentContext:nil];
}

@end

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值