OpenGLES-01 渲染第一步

作者: _清墨 | 来源:发表于2017-11-06 18:31 被阅读167次

    若文章读完,请多练习文章里函数的写法。
    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-

    相关文章

      网友评论

        本文标题:OpenGLES-01 渲染第一步

        本文链接:https://www.haomeiwen.com/subject/qrgtmxtx.html