OpenGLES-01 渲染第一步

若文章读完,请多练习文章里函数的写法。 1.创建你的项目并新建MyGLView

新建MyGLView.png

2.修改你创建的MyGLView添加如下变量(变量后面会有介绍)

@interface MyGLView ()
{
    CAEAGLLayer *_eaglLayer;  //OpenGL内容只会在此类layer上描绘
    EAGLContext *_context;    //OpenGL渲染上下文
    GLuint _renderBuffer;     //
    GLuint _frameBuffer;      //

}

3.在 MyGLView.m 中添加如下函数:

+(Class)layerClass{
    //OpenGL内容只会在此类layer上描绘
    return [CAEAGLLayer class];
}

因为OpenGLES的描绘必须在CAEAGLLayer上才能显示出来,所以我们需要重写这个函数,修改view默认的layer返回类型

4.设置_eaglLayer的属性,添加如下函数:

- (void)setupLayer
{
    _eaglLayer = (CAEAGLLayer*) self.layer;
    
    // CALayer 默认是透明的,透明对性能影响大,设置为不透明对性能最好
    _eaglLayer.opaque = YES;
    
    // 设置描绘属性,在这里设置不维持渲染内容以及颜色格式为 RGBA8
    _eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
                                     [NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
}

5.设置渲染上下文 _context 属性,添加如下函数:

- (void)setupContext {
    // 指定 OpenGLES 渲染API的版本,在这里我们使用OpenGLES 3.0,由于3.0兼容2.0并且功能更强,为何不用更好的呢
    //注:在iOS上,可以支持opengles3.0的最低环境是iphone5s ios7.0.
    EAGLRenderingAPI api = kEAGLRenderingAPIOpenGLES3;
    _context = [[EAGLContext alloc] initWithAPI:api];
    if (!_context) {
        NSLog(@"Failed to initialize OpenGLES 3.0 context");
    }
    
    // 设置为当前上下文
    [EAGLContext setCurrentContext:_context];
}

6.设置 _renderBuffer,添加如下函数:

-(void)setupRenderBuffer{
    glGenRenderbuffers(1, &_renderBuffer); //
    glBindRenderbuffer(GL_RENDERBUFFER, _renderBuffer);
    [_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:_eaglLayer];
}

7.设置 _frameBuffer,添加如下函数:

-(void)setupFrameBuffer{
    glGenFramebuffers(1, &_frameBuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffer);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _renderBuffer);
}

8.buffer介绍

1). buffer分为frame buffer和render buffer两大类,其中frame buffer相当于render buffer的管理者,frame buffer object即称为FBO,常用于做离屏渲染缓冲等。render buffer则又可分为三类,color buffer / depth buffer / stencil buffer。

2). 生成frame buffer object的API函数:
 glGenFramebuffers(1, &framebuffer);
 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
生成render buffer的API函数,render buffer的生成函数是一样的,buffer句柄类型只有在进行分配buffer空间的时候才会确定:
glGenRenderbuffers(1, &renderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);

3). frame buffer仅仅是管理者,不需要分配空间;render buffer的存储空间的分配,对于不同的render buffer,使用不同的API进行分配,而只有分配空间的时候,render buffer句柄才确定其类型
(1). 最基本的是color buffer,调用EGALContext的OC方法为其分配空间
/* Attaches an EAGLDrawable as storage for the OpenGL ES renderbuffer object bound to <target> */
- (BOOL)renderbufferStorage:(NSUInteger)target fromDrawable:(id<EAGLDrawable>)drawable;
(2). 而depth buffer则可以直接调用openGL本身的API进行分配
glRenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH_COMPONENT16, width, height);

4). 上面(1)(2)函数是用于生成render buffer的存储空间,生成空间之后,则需要将renderbuffer跟framebuffer进行绑定,调用glFramebufferRenderbuffer函数进行绑定,后面的绘制才能起作用

5). 接下来可以调用OpenGL的函数进行绘制处理,最后则需要调用EGALContext的OC方法进行最终的渲染绘制,这里渲染的是color buffer,这个方法会讲buffer渲染到CALayer上面
- (BOOL)presentRenderbuffer:(NSUInteger)target;

6). 还有一个需要注意的地方是在退出的时候,需要调用glDelegateFramebuffers或者glDeleteRenderbuffers函数删除frame
 buffer或者render buffer

9.开始渲染,添加如下函数:

-(void)render
{
    //设置清屏颜色,默认是黑色,如果你的运行结果是黑色,问题就可能在这儿
    glClearColor(0.3, 0.5, 0.8, 1.0);
    /*
    glClear指定清除的buffer
    共可设置三个选项GL_COLOR_BUFFER_BIT,GL_DEPTH_BUFFER_BIT和GL_STENCIL_BUFFER_BIT
    也可组合如:glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    这里我们只用了color buffer,所以只需清除GL_COLOR_BUFFER_BIT
     */
    glClear(GL_COLOR_BUFFER_BIT);
    
    [_context presentRenderbuffer:_renderBuffer];
}

10.重写 initWithFrame 方法,并调用上述函数:

-(instancetype)initWithFrame:(CGRect)frame{
    if (self==[super initWithFrame:frame]) {
        [self setupLayer];
        [self setupContext];
        [self setupRenderBuffer];
        [self setupFrameBuffer];
        [self render];
    }
    
    return self;
}

11.使用与运行结果: 在你的ViewController中导入MyGLView头文件并在viewDidLoad方法中添加如下代码:

MyGLView *openGLView = [[MyGLView alloc]initWithFrame:self.view.bounds];
    self.view = openGLView;
//    [self.view addSubview:openGLView];

运行结果如下:

运行结果.png

接下来的文章会使用到OpenGLES的坐标点,这里先介绍下在OpenGL里,它的坐标表现:

坐标系.png

它的x、y、z的范围都在-1到1之间,坐标原点在图中正方体的中心。如图画的一个白色三角形,它的三个坐标分别是:(-0.5,0.5,0.0)、(-0.5,-0.5,0.0)和(0.5,-0.5,0.0),请对着图好好理解理解.

所有教程代码在此 : https://github.com/qingmomo/iOS-OpenGLES-

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏码匠的流水账

聊聊eureka client的serviceUrl

eureka-client-1.8.8-sources.jar!/com/netflix/discovery/DiscoveryClient.java

29510
来自专栏菩提树下的杨过

Silverlight Telerik控件学习:RadTransitionControl

如果展示类似这种比较cool的图片轮换效果,用RadTransitionControl控件就对了,它提供的过渡效果非常cool! 原理并不复杂,可参见以前写的 ...

24470
来自专栏非典型技术宅

iOS实践:一步步实现星级评分1. 创建星星2. 优化3. 灵异事件

19640
来自专栏王磊的博客

javascript数字格式化通用类——accounting.js使用

简介 accounting.js 是一个非常小的JavaScript方法库用于对数字,金额和货币进行格式化。并提供可选的Excel风格列渲染。它没有依赖任何JS...

73560
来自专栏码匠的流水账

聊聊spring cloud gateway的LoadBalancerClientFilter

本文主要研究一下spring cloud gateway的LoadBalancerClientFilter

18410
来自专栏Albert陈凯

2018-09-04 Java Code Examples for com.ibm.icu.text.Transliterator 汉字转拼音 全角转半角

https://www.programcreek.com/java-api-examples/?api=com.ibm.icu.text.Translitera...

17410
来自专栏陈满iOS

iOS开发·runtime原理与实践: 关联对象篇(Associated Object)(应用场景:为分类添加“属性”,为UI控件关联事件Block体,为了不重复获得某种数据)

分类(category)与关联对象(Associated Object)作为objective-c的扩展机制的两个特性:分类,可以通过它来扩展方法;Associ...

51820

.NET中的密钥加密

本教程将演示如何通过System.Security.Cryptography在.NET Framework 1.1中实现对称加密/密钥加密。

64180
来自专栏搞前端的李蚊子

js实现活动倒计时

33820
来自专栏林冠宏的技术文章

GreenDao 工具类 --- 使用 Json 快速生成 Bean、表及其结构,"炒鸡"快!

作者:林冠宏 / 指尖下的幽灵 腾讯云+社区:https://cloud.tencent.com/developer/user/1148436/activi...

55090

扫码关注云+社区

领取腾讯云代金券