在OS X的openGL編程中,我們有時為了想在自己的OpenGL圖層上再加些自己的某些塗層,必須得用CAOpenGLLayer而不是NSOpenGLView,由於在NSOpenGLView上添加任何子視圖都會變得無效。
其實,在CAOpenGLLayer自定義的子類中要追加支持OpenGL Core Profile很簡單,只需要重寫其
- (CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask
方法即可。如以下代碼所示:
// 重寫父類的方法,提供自己的CGLPixelFormatObj - (CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask { CGLPixelFormatAttribute attribs[] = { kCGLPFADisplayMask, 0, kCGLPFAColorSize, 24, kCGLPFAAccelerated, kCGLPFADoubleBuffer, // Use OpenGL 3.2 Core Profile kCGLPFAOpenGLProfile, (CGLPixelFormatAttribute)kCGLOGLPVersion_3_2_Core, // Use multi-sample kCGLPFAMultisample, kCGLPFASampleBuffers, (CGLPixelFormatAttribute)1, kCGLPFASamples, (CGLPixelFormatAttribute)4, 0 }; // 將kCGLPFADisplayMask設置為傳遞過來的display mask。這個步驟是必須的! attribs[1] = mask; CGLPixelFormatObj pixFormatObj = NULL; GLint numPixFormats = 0; CGLChoosePixelFormat(attribs, &pixFormatObj, &numPixFormats); return pixFormatObj; }
然后,我們可以在自己的子類中添加對CGLContextObj對象的引用來做一些標記。另外,我們必須重寫CAOpenGLLayer的這個方法:
- (void)drawInCGLContext:(CGLContextObj)glContext
pixelFormat:(CGLPixelFormatObj)pixelFormat
forLayerTime:(CFTimeInterval)timeInterval
displayTime:(const CVTimeStamp *)timeStamp
。
比如像以下代碼所示:
- (void)drawInCGLContext:(CGLContextObj)glContext pixelFormat:(CGLPixelFormatObj)pixelFormat forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp { // 這里必須先將傳進來的上下文作為當前OpenGL執行上下文對象,否則后續對OpenGL的狀態設置都將無效 CGLSetCurrentContext(glContext); [self setupContext]; // mContext主要用於判別當前OpenGL上下文是否已經設置好,以及在render方法中的引用 mContext = glContext; [self render]; }
- (void)setupContext是自定義方法,在里面做頂點設置、全局啟用某些OpenGL功能狀態,並設置viewport等等。
- (void)render也是自定義方法,用來做真正的圖形繪制。
如以下代碼所示:
- (void)render { // render glClear(GL_COLOR_BUFFER_BIT); glDrawArrays(GL_LINE_STRIP, 0, 721); glFlush(); CGLFlushDrawable(mContext); }
隨后,我們自己提供shader代碼,並進行加載即可。這些可以放在setupContext自定義方法中實現。
當然,在OS X中要使用OpenGL core profile必須引入<OpenGL/gl3.h>這個頭文件。目前,3.2 core profile以及4.1 core profile都是用此頭文件。