iOS之OpenGL ES【1】:基本认识和理解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Forever_wj/article/details/58081262

一、什么是 OpenGL ES?

iOS上绘制图形的方式很多,UIKit,CoreGraphics,SpriteKit,OpenGL ES,Metal等。OpenGL ES是一套非常底层但使用非常广泛的C语言API,专为移动设备定制,可在不同的手机系统或浏览器上使用,渲染效果很好。

二、iOS的OpenGL ES的使用:

  • 新建一个工程之后,在系统库中需要添加导入OpenGLES.framework和QuartzCore.framework两个库;
  • 新建一个单独实现OpenGL ES的类,命名为OpenGLView,并引入
#import "OpenGLView.h"
#import <QuartzCore/QuartzCore.h>
#import <OpenGLES/ES2/gl.h>
#import <OpenGLES/ES2/glext.h>
  • 在OpenGLView的.m的延展中声明如下实例变量:
@interface OpenGLView () {
    CAEAGLLayer *eaglLayer; //OpenGL context,管理使用openGLES进行绘制的状态,命令及资源
    EAGLContext *eaglContext;
    GLuint      colorRenderBuffer;//渲染缓冲区
    GLuint      frameBuffer;//帧缓冲区
}
  • 继续在.m中实现layerClass方法:
 + (Class)layerClass {
    //为了让 UIView 显示 openGL 内容,必须将默认的layer类型修改为CAEAGLLayer类型
    return [CAEAGLLayer class];
}
  • CAEAGLLayer的配置:默认的 CALayer 是透明的,需要将它设置为 opaque == YES 才能看到在它上面描绘的东西。为此,使用匿名 category 技巧,在 OpenGLView.m的开头(在@interface OpenGLView 的上面)添加匿名 category,并声明私有函数 setupLayer并在implementation中实现:
 + (void)setupLayer {
    eaglLayer = (CAEAGLLayer *)self.layer;
    eaglLayer.opaque = YES;
    // 描绘属性:这里不维持渲染内容
    // kEAGLDrawablePropertyRetainedBacking:若为YES,则使用glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)计算得到的最终结果颜色的透明度会考虑目标颜色的透明度值。
    // 若为NO,则不考虑目标颜色的透明度值,将其当做1来处理。
    // 使用场景:目标颜色为非透明,源颜色有透明度,若设为YES,则使用glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)得到的结果颜色会有一定的透明度(与实际不符)。若未NO则不会(符合实际)。
    eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:NO],kEAGLDrawablePropertyRetainedBacking,kEAGLColorFormatRGBA8,kEAGLDrawablePropertyColorFormat, nil];
}
  • EAGLContext渲染上下文
 - (void)setupContext {
    eaglContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
    if (!eaglContext) {
        exit(1);
    }

    if (![EAGLContext setCurrentContext:eaglContext]) {
        exit(1);
    }
}
  • 创建RenderBuffer:用于存储渲染的内容(OpenGL ES 总共有三大不同用途的color buffer,depth buffer 和 stencil buffer,这里创建私有方法setupRenderBuffer来生成 color buffer;
 - (void)setupRenderBuffer {
    if (colorRenderBuffer) {
        glDeleteBuffers(1, &colorRenderBuffer);
        frameBuffer = 0;
    }
    // 生成一个renderBuffer,id是colorRenderBuffer
    glGenBuffers(1, &colorRenderBuffer);
    // 设置为当前renderBuffer,则后面引用GL_RENDERBUFFER,即指的是colorRenderBuffer
    glBindRenderbuffer(GL_RENDERBUFFER, colorRenderBuffer);
    // 为colorRenderBuffer分配存储空间
    [eaglContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:eaglLayer];
}
  • FrameBuffer:renderBuffer对象本身不能直接使用,不能挂载到GPU上直接输出内容,要使用frameBuffer(OpenGlES的FrameBuffer包含:renderBuffer,depthBuffer,stencilBuffer和accumulationBuffer);
- (void)setupFrameBuffer {
    if (frameBuffer) {
        glGenBuffers(1, &frameBuffer);
        frameBuffer = 0;
    }
    // FBO用于管理colorRenderBuffer,离屏渲染
    glGenFramebuffers(1, &frameBuffer);
    // 设置为当前frameBuffer
    glBindRenderbuffer(GL_FRAMEBUFFER, frameBuffer);
    // 将colorRenderBuffer装配到GL_COLOR_ATTACHMENT0这个装配点上
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRenderBuffer);
}
  • 当 UIView 在进行布局变化之后,由于 layer 的宽高变化,导致原来创建的 renderbuffer不再相符,需要销毁既有的 renderbuffer 和 framebuffer;
 - (void)destoryRenderAndFrameBuffer {
    glDeleteFramebuffers(1, &frameBuffer);
    frameBuffer = 0;
    glDeleteRenderbuffers(1, &colorRenderBuffer);
    colorRenderBuffer = 0;
}
  • 声明一个render方法进行真实描绘:
 - (void)render {
    // 设置清屏颜色
    glClearColor(0, 1.0, 0, 1.0);
    // 用来指定要用清屏颜色来清除由mask指定的buffer,此处是color buffer
    glClear(GL_COLOR_BUFFER_BIT);

    [eaglContext presentRenderbuffer:GL_RENDERBUFFER];
}
  • 最后在实现layoutSubviews方法:
- (void)layoutSubviews {
    [self setupLayer];
    [self setupContext];
    [self destoryRenderAndFrameBuffer];
    [self setupRenderBuffer];
    [self setupFrameBuffer];
    [self render];
}
  • 完成了OpenGLView的基本构造之后,利用OpenGLView在界面上进行渲染:在ViewController中导入#import “OpenGLView.h”,并声明一个OpenGLView的实例属性,在viewDidLoad中调用即可:
    self.glView = [[OpenGLView alloc] init];
    self.glView.frame = self.view.frame;
    [self.view addSubview:self.glView];
    self.view.backgroundColor = [UIColor redColor];

猜你喜欢

转载自blog.csdn.net/Forever_wj/article/details/58081262
今日推荐