Ios子线程渲染Opengl

1. 介绍
ios并没有像Android glsurfaceview或者Qt QOpenglWidget
那样完整Opengl渲染View封装,官方demo也是主线程创建的CADisplayLink提供的渲染loop来执行Opengl渲染操作,可能会影响到主线程其他view的操作造成卡顿,所以此篇仿照Android GlSurfaceView在子线程渲染Opengl。

2. 封装

  • ios opengl渲染环境和渲染子线程创建
 - (id)initWithFrame:(CGRect)frame {
    if ((self = [super initWithFrame:frame])) {
        self.layer.opaque = YES;
        _playFlag = TRUE;
        _isInitContext = FALSE;
        _isSurfaceChanged = FALSE;
        _layerPtr = (CAEAGLLayer *) self.layer;
        self.layer.opaque = YES;
        self.layer.contentsScale = [[UIScreen mainScreen] scale];
        ((CAEAGLLayer *) self.layer).drawableProperties = @{kEAGLDrawablePropertyRetainedBacking: [NSNumber numberWithBool:YES],};
    }
    _renderLoopThread = [[NSThread alloc] initWithTarget:self selector:@selector(renderThreadFunc) object:nil];
    [_renderLoopThread start];
    [self registerSystemActiveEvent];
    return self;
}
  • 依附于子线程创建Opengl 上下文
 - (void)renderThreadFunc {
    if (!_isInitContext) {
        _context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
        _isInitContext = TRUE;
        [EAGLContext setCurrentContext:_context];
        //glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &_windowWidth);
        //glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &_windowHeight);
    }
    @autoreleasepool {
        _renderTimer = [NSTimer scheduledTimerWithTimeInterval:0.0333 target:self selector:@selector(renderLoop) userInfo:nil repeats:YES];
        [[NSRunLoop currentRunLoop] run];
    }
    [self destroyFrameBuffer];
    [EAGLContext setCurrentContext:nil];
    self.context = nil;
    NSLog(@"this is the render thread destroy!");
}

这里当timer被取消,渲染线程结束,销毁Opengl上下文和相关FrameBuffer

  • 渲染FrameBuffer和帧缓冲区创建
 - (void)renderLoop {
    if (_isInitContext && _isSurfaceChanged) {
        @synchronized (self) {
            [self destroyFrameBuffer];
            [self createFrameBuffer];
            //NSLog(@"onSurfaceSizeChanged:%d, width:%d, height:%d", _multisampleFramebuffer, _windowWidth, _windowHeight);
            _isSurfaceChanged = FALSE;
        }
    }
    if (!_playFlag || !_isInitContext || _multisampleFramebuffer == 0) {
        return;
    }
    [self bindFrameBuffer];
    [self renedeOperation];
    [self presentFrameBuffer];
}

因为创建窗口大小可能会发生改变,这时候需要根据窗口大小变化重新创建附着在多重采样FrameBuffer上的帧缓冲区RenderBuffer,这里创建了两个FrameBuffer执行多重采样用于消除锯齿,如果没有这个需求,只要创建一个FrameBuffer即可。

  • 具体渲染操作
//渲染操作
-(void)renedeOperation {
    NSLog(@"renedeOperation");
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glClearColor(0, 1, 0, 1);
}

3. 结束语
Ios在子线程中渲染Opengl重要的是对Layer的操作,获取Layer需要在主线程获取,请注意该点。Ios对Opengl EGL接口封装的挺多,并没有android来的直接。具体代码见: ios 子线程渲染Opengl

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值