使用 C 和 Cocoa 建立 OpenGL 4.1
注意:在這個例子中會有一些 Objective-c。在這個例子中我們將為 C++做一個包裝器,所以不用擔心它。
首先啟動 Xcode 並建立一個專案。
並選擇一個 Cocoa 應用程式
刪除除 Info.plist 檔案以外的所有來源。(如果沒有它,你的應用程式將無法執行)
建立 4 個新的原始檔:Objective-c ++檔案和標題(我稱之為我的 MacApp)一個 C++類(我稱之為我的(應用程式)
在左上角(帶有專案名稱),單擊它並新增連結的框架和庫。新增:OpenGL.Framework AppKit.Framework GLKit.Framework
你的專案可能看起來像這樣:
NSApplication 是你在建立 MacOS 應用程式時使用的主要類。它允許你註冊視窗和捕獲事件。
我們想要將(我們自己的)視窗註冊到 NSApplication。首先在 objective-c ++標頭檔案中建立一個 Objective-c 類,它繼承自 NSWindow 並實現 NSApplicationDelegate NSWindow 需要一個指向 C++應用程式的指標,一個 openGL 檢視和一個用於繪製迴圈的計時器
//Mac_App_H
#import <Cocoa/Cocoa.h>
#import "Application.hpp"
#import <memory>
NSApplication* application;
@interface MacApp : NSWindow <NSApplicationDelegate>{
std::shared_ptr<Application> appInstance;
}
@property (nonatomic, retain) NSOpenGLView* glView;
-(void) drawLoop:(NSTimer*) timer;
@end
我們稱之為主要的
int main(int argc, const char * argv[]) {
MacApp* app;
application = [NSApplication sharedApplication];
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
//create a window with the size of 600 by 600
app = [[MacApp alloc] initWithContentRect:NSMakeRect(0, 0, 600, 600) styleMask:NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask backing:NSBackingStoreBuffered defer:YES];
[application setDelegate:app];
[application run];
}
我們的視窗的實現實際上非常簡單首先我們宣告合成我們的 glview 並在視窗關閉時新增一個全域性的 objective-c 布林值。
#import "MacApp.h"
@implementation MacApp
@synthesize glView;
BOOL shouldStop = NO;
現在為建構函式。我的偏好是使用 initWithContentRect。
-(id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)aStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag{
if(self = [super initWithContentRect:contentRect styleMask:aStyle backing:bufferingType defer:flag]){
//sets the title of the window (Declared in Plist)
[self setTitle:[[NSProcessInfo processInfo] processName]];
//This is pretty important.. OS X starts always with a context that only supports openGL 2.1
//This will ditch the classic OpenGL and initialises openGL 4.1
NSOpenGLPixelFormatAttribute pixelFormatAttributes[] ={
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
NSOpenGLPFAColorSize , 24 ,
NSOpenGLPFAAlphaSize , 8 ,
NSOpenGLPFADoubleBuffer ,
NSOpenGLPFAAccelerated ,
NSOpenGLPFANoRecovery ,
0
};
NSOpenGLPixelFormat* format = [[NSOpenGLPixelFormat alloc]initWithAttributes:pixelFormatAttributes];
//Initialize the view
glView = [[NSOpenGLView alloc]initWithFrame:contentRect pixelFormat:format];
//Set context and attach it to the window
[[glView openGLContext]makeCurrentContext];
//finishing off
[self setContentView:glView];
[glView prepareOpenGL];
[self makeKeyAndOrderFront:self];
[self setAcceptsMouseMovedEvents:YES];
[self makeKeyWindow];
[self setOpaque:YES];
//Start the c++ code
appInstance = std::shared_ptr<Application>(new Application());
}
return self;
}
好吧……現在我們實際上有一個可執行的應用程式..你可能會看到黑屏或閃爍。
讓我們開始繪製一個很棒的三角形。(在 c ++中)
我的應用標題
#ifndef Application_hpp
#define Application_hpp
#include <iostream>
#include <OpenGL/gl3.h>
class Application{
private:
GLuint program;
GLuint vao;
public:
Application();
void update();
~Application();
};
#endif /* Application_hpp */
實施:
Application::Application(){
static const char * vs_source[] =
{
"#version 410 core \n"
" \n"
"void main(void) \n"
"{ \n"
" const vec4 vertices[] = vec4[](vec4( 0.25, -0.25, 0.5, 1.0), \n"
" vec4(-0.25, -0.25, 0.5, 1.0), \n"
" vec4( 0.25, 0.25, 0.5, 1.0)); \n"
" \n"
" gl_Position = vertices[gl_VertexID]; \n"
"} \n"
};
static const char * fs_source[] =
{
"#version 410 core \n"
" \n"
"out vec4 color; \n"
" \n"
"void main(void) \n"
"{ \n"
" color = vec4(0.0, 0.8, 1.0, 1.0); \n"
"} \n"
};
program = glCreateProgram();
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, fs_source, NULL);
glCompileShader(fs);
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, vs_source, NULL);
glCompileShader(vs);
glAttachShader(program, vs);
glAttachShader(program, fs);
glLinkProgram(program);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
}
void Application::update(){
static const GLfloat green[] = { 0.0f, 0.25f, 0.0f, 1.0f };
glClearBufferfv(GL_COLOR, 0, green);
glUseProgram(program);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
Application::~Application(){
glDeleteVertexArrays(1, &vao);
glDeleteProgram(program);
}
現在我們只需要反覆呼叫更新(如果你想要移動的東西)在 objective-c 類中實現
-(void) drawLoop:(NSTimer*) timer{
if(shouldStop){
[self close];
return;
}
if([self isVisible]){
appInstance->update();
[glView update];
[[glView openGLContext] flushBuffer];
}
}
並在你的 objective-c 類的實現中新增此方法:
- (void)applicationDidFinishLaunching:(NSNotification *)notification {
[NSTimer scheduledTimerWithTimeInterval:0.000001 target:self selector:@selector(drawLoop:) userInfo:nil repeats:YES];
}
這將一遍又一遍地呼叫你的 c ++類的更新函式(準確地說每個 0.000001 秒)
為了完成,我們在按下關閉按鈕時關閉視窗:
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication{
return YES;
}
- (void)applicationWillTerminate:(NSNotification *)aNotification{
shouldStop = YES;
}
恭喜,現在你有一個很棒的視窗,有一個沒有任何第三方框架的 OpenGL 三角形。