本文原始地址:OpenCV for Ios 学习笔记(8)-用OPENGL渲染AR场景1
创建OpenGL渲染层
为了在你的应用中使用opengl函数,你必须为你的应用添加一个图形画板,它给用户呈现被渲染的场景。
为了封装opengl画板初始化逻辑,我们介绍EAGLView类:
// // EAGLView.h // OpenCvDemo // // Created by apple on 13-4-24. // Copyright (c) 2013年 hxy. All rights reserved. // #import <UIKit/UIKit.h> #import <OpenGLES/ES1/gl.h> #import <OpenGLES/ES1/glext.h> #import <OpenGLES/ES2/gl.h> #import <OpenGLES/ES2/glext.h> @class EAGLContext; @interface EAGLView : UIView { @private GLuint defaultFrameBuffer,colorRenderBuffer,depthRenderBuffer; } @property (nonatomic, retain) EAGLContext *context; @property (readonly) GLint frameBufferWidth,frameBufferHeight; //初始化画板 - (void)initContext; //设置帧缓存 - (void)setFrameBuffer; //呈现帧缓存 - (void)presentFrameBuffer; @end
// // EAGLView.m // OpenCvDemo // // Created by apple on 13-4-24. // Copyright (c) 2013年 hxy. All rights reserved. // #import "EAGLView.h" @interface EAGLView (Private) //创建帧缓存 - (void)createFrameBuffer; //删除所有的缓存 - (void)deleteFrameBuffer; @end @implementation EAGLView @synthesize context,frameBufferHeight,frameBufferWidth; - (void)dealloc { [self deleteFrameBuffer]; if ([EAGLContext currentContext] == context) { [EAGLContext setCurrentContext:nil]; } [super dealloc]; } + (Class)layerClass { return [CAEAGLLayer class]; } - (void)layoutSubviews { //在下一次设置帧缓存时,帧缓存将会重新创建 [self deleteFrameBuffer]; } - (void)initContext { if (!context) { EAGLRenderingAPI api = kEAGLRenderingAPIOpenGLES2; context = [[EAGLContext alloc] initWithAPI:api]; if (!context) { NSLog(@"画布都创建失败,还运行个闯闯!"); exit(1); return; } if (![EAGLContext setCurrentContext:context]) { NSLog(@"悲剧了塞!"); exit(1); return; } } } - (void)setContext:(EAGLContext *)newcontext { if (context != newcontext) { [self deleteFrameBuffer]; context = newcontext; [EAGLContext setCurrentContext:nil]; } } - (CAEAGLLayer *)myLayer { return (CAEAGLLayer *)self.layer; } - (id)initWithCoder:(NSCoder *)aDecoder { if (self = [super initWithCoder:aDecoder]) { CAEAGLLayer *layer = [self myLayer]; layer.opaque = TRUE; layer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:FALSE],kEAGLDrawablePropertyRetainedBacking,kEAGLColorFormatRGBA8,kEAGLDrawablePropertyColorFormat, nil]; [self initContext]; } return self; } - (void)setFrameBuffer { if (context) { [EAGLContext setCurrentContext:context]; if (!depthRenderBuffer) { [self createFrameBuffer]; } glBindFramebuffer(GL_FRAMEBUFFER, defaultFrameBuffer); glViewport(0, 0, frameBufferWidth, frameBufferHeight); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); } } - (void)presentFrameBuffer { BOOL success = FALSE; if (context) { [EAGLContext setCurrentContext:context]; glBindRenderbuffer(1, colorRenderBuffer); success = [context presentRenderbuffer:GL_RENDERBUFFER]; } } - (void)createFrameBuffer { //还未设置默认帧缓存 if (context && !defaultFrameBuffer) { [EAGLContext setCurrentContext:context]; //创建默认帧缓存对象 glGenFramebuffers(1, &(defaultFrameBuffer)); glBindFramebuffer(GL_FRAMEBUFFER, defaultFrameBuffer); //创建颜色缓存,分配内存 glGenRenderbuffers(1, &colorRenderBuffer); glBindRenderbuffer(GL_RENDERBUFFER, colorRenderBuffer); [context renderbufferStorage:GL_RENDERBUFFER fromDrawable:[self myLayer]]; glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &frameBufferWidth); glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &frameBufferHeight); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRenderBuffer); //生成深度缓存 glGenRenderbuffers(1, &depthRenderBuffer); glBindRenderbuffer(GL_RENDERBUFFER, depthRenderBuffer); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, frameBufferWidth, frameBufferHeight); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderBuffer); //检查状态 if (glCheckFramebufferStatus(GL_FRAMEBUFFER)!= GL_FRAMEBUFFER_COMPLETE) { NSLog(@"Failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER)); } } } - (void)deleteFrameBuffer { if (context) { [EAGLContext setCurrentContext:context]; if (defaultFrameBuffer) { glDeleteFramebuffers(1, &defaultFrameBuffer); defaultFrameBuffer = 0; } if (colorRenderBuffer) { glDeleteRenderbuffers(1, &colorRenderBuffer); colorRenderBuffer = 0; } if (depthRenderBuffer) { glDeleteRenderbuffers(1, &depthRenderBuffer); depthRenderBuffer = 0; } } } @end
在上面的EAGLView并不包括任何的3维物体虚拟化的方法,当然,我们是故意的。EAGLView的任务是提供渲染的画板,将各个类的职责区别开有利于我们在接下来改变虚拟化过程的逻辑。
为了实现增强现实的虚拟化,我们将会创建一个单独的类VisualizationController:
@interface SimpleVisualizationController : NSObject { EAGLView * m_glview; GLuint m_backgroundTextureId; std::vector<Transformation> m_transformations; CameraCalibration m_calibration; CGSize m_frameSize; } -(id) initWithGLView:(EAGLView*)view calibration:(CameraCalibration) calibration frameSize:(CGSize) size; //把ar渲染到EAGLView目标视图上去 -(void) drawFrame; -(void) updateBackground:(BGRAVideoFrame) frame; -(void) setTransformationList:(const std::vector<Transformation>&) transformations; @end
未完