本文原始地址: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
渲染AR情境
在上面的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
未完