Last active
August 29, 2015 14:16
-
-
Save possan/5d044b3d418fee414b18 to your computer and use it in GitHub Desktop.
Minimal self container OpenGL Example on OSX
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Minimal self container OpenGL Example | |
// | |
// Compile with: | |
// xcrun gcc -o test -framework Foundation -framework OpenGL -framework CoreGraphics -framework AppKit main.m | |
// | |
#import <Foundation/Foundation.h> | |
#import <CoreGraphics/CoreGraphics.h> | |
#import <OpenGL/OpenGL.h> | |
#import <OpenGL/gl.h> | |
#import <Carbon/Carbon.h> | |
#import <CoreFoundation/CoreFoundation.h> | |
#import <AppKit/AppKit.h> | |
#include <math.h> | |
@class MyWindow; | |
@interface MyRunner : NSObject | |
@property (nonatomic, readwrite) float time; | |
@property (nonatomic, readwrite) NSOpenGLContext *ctx; | |
@property (nonatomic, readwrite) MyWindow *window; | |
- (id)init; | |
- (void)doTick: (NSTimer*)timer; | |
@end | |
@interface MyWindow : NSWindow | |
@property (nonatomic, readwrite) MyRunner *runner; | |
@end | |
@implementation MyWindow | |
#define KEY_F 3 | |
#define KEY_ESCAPE 53 | |
#define KEY_RETURN 36 | |
#define KEY_TAB 48 | |
#define KEY_SPACE 49 | |
#define KEY_Q 12 | |
- (void) postCreate { | |
[self setLevel:NSMainMenuWindowLevel+1]; | |
[self setOpaque:YES]; | |
[self makeKeyAndOrderFront:nil]; | |
CGLEnable((CGLContextObj)[self.runner.ctx CGLContextObj], kCGLCEMPEngine); | |
[self.runner.ctx setView:self.contentView]; | |
[self.runner.ctx makeCurrentContext]; | |
} | |
- (void) keyDown: (NSEvent*)ev { | |
if ([ev isARepeat]) | |
return; | |
NSLog(@"key down: %d", [ev keyCode]); | |
if ([ev keyCode] == KEY_F || [ev keyCode] == KEY_RETURN) { | |
// | |
// Toggle fullscreen with 'F' or Return | |
// | |
if (self.styleMask & NSTitledWindowMask) { | |
NSLog(@"Go fullscreen..."); | |
[self setStyleMask: NSFullScreenWindowMask ]; | |
[self makeKeyAndOrderFront:nil]; | |
NSRect viewRect = NSMakeRect(0.0, 0.0, self.screen.frame.size.width, self.screen.frame.size.height); | |
[self setFrame:viewRect display:YES]; | |
[self.contentView setFrame:viewRect]; | |
[self.runner.ctx setView:self.contentView]; | |
[self.runner.ctx update]; | |
} else { | |
NSLog(@"Go windowed..."); | |
[self setStyleMask: NSTitledWindowMask | NSResizableWindowMask | NSClosableWindowMask ]; | |
NSRect viewRect = NSMakeRect(0.0, 0.0, 800, 600); | |
[self setFrame:viewRect display:YES]; | |
[self.contentView setFrame:viewRect]; | |
[self.runner.ctx setView:self.contentView]; | |
[self makeKeyAndOrderFront:nil]; | |
[self center]; | |
[self.runner.ctx update]; | |
} | |
} | |
if ([ev keyCode] == KEY_ESCAPE || [ev keyCode] == KEY_Q) { | |
// | |
// quit with 'Q' or Escape | |
// | |
[NSApp stop:nil]; | |
[NSApp postEvent: [NSEvent otherEventWithType:NSApplicationDefined location:NSZeroPoint modifierFlags:0 timestamp:0.0 windowNumber:0 context:NULL subtype:0 data1:0 data2:0] atStart:NO]; | |
} | |
if ([ev keyCode] == KEY_SPACE) { | |
self.runner.time = (float) (rand() % 10000); | |
} | |
} | |
@end | |
@implementation MyRunner | |
- (id) init { | |
self = [super init]; | |
self.time = .0f; | |
NSOpenGLPixelFormatAttribute attrs[] = { | |
NSOpenGLPFADoubleBuffer, | |
NSOpenGLPFAScreenMask, | |
(NSOpenGLPixelFormatAttribute)CGDisplayIDToOpenGLDisplayMask(CGMainDisplayID()), | |
NSOpenGLPFADepthSize, | |
(NSOpenGLPixelFormatAttribute)16, | |
(NSOpenGLPixelFormatAttribute)0 | |
}; | |
NSOpenGLPixelFormat *fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes: attrs]; | |
self.ctx = [[NSOpenGLContext alloc] initWithFormat: fmt shareContext: nil]; | |
NSRect viewRect = NSMakeRect(0, 0, 800, 600); | |
unsigned style = NSTitledWindowMask | NSMiniaturizableWindowMask | NSClosableWindowMask; | |
self.window = [[MyWindow alloc] initWithContentRect: viewRect styleMask:style backing:NSBackingStoreBuffered defer:YES]; | |
self.window.runner = self; | |
[self.window postCreate]; | |
[self.window center]; | |
ProcessSerialNumber psn = { 0, kCurrentProcess }; | |
TransformProcessType(&psn, kProcessTransformToForegroundApplication); | |
[NSTimer scheduledTimerWithTimeInterval: 1.0f / 60.0f target:self selector: @selector(doTick:) userInfo: nil repeats: YES]; | |
return self; | |
} | |
- (void) doTick: (NSTimer*)timer { | |
float T = self.time; | |
self.time += 1.0 / 60.0f; | |
GLint value = 1; | |
[self.ctx setValues: &value | |
forParameter: NSOpenGLCPSwapInterval]; | |
NSRect viewRect = ((NSView *)self.window.contentView).frame; | |
glViewport(0,0, viewRect.size.width,viewRect.size.height); | |
glClearColor(0.1f + 0.1f * sin(T * 2.0f), 0.1f + 0.1f * sin(T * 3.0f), 0.1f, 1.0f); | |
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); | |
glEnable(GL_BLEND); | |
glBlendFunc(GL_ONE, GL_ONE); | |
glBegin(GL_LINES); | |
glColor3f(0.1, 0.1, 0.1); | |
glVertex3f(-1,-1,0); | |
glVertex3f(1,1,0); | |
glVertex3f(1,-1,0); | |
glVertex3f(-1,1,0); | |
for(int k=0; k<30; k++) { | |
float z = (float)(k - 10 + fmod(T, 1.0)) / 10.0f; | |
glVertex3f(-1,z,0); | |
glVertex3f(1,z,0); | |
glVertex3f(z,-1,0); | |
glVertex3f(z,1,0); | |
} | |
for(int k=0; k<100; k++) { | |
float z = (float)k / 100.0; | |
glColor3f(z,z,z); | |
float x, y; | |
float T2 = T + (float)k / 100.0; | |
float C1 = T / 333.0; | |
float C2 = T / 100.0 + (float)k / 430.0; | |
x = sin(T2 * 3.1 + C2) * cos(T2 * 2.4 + C1); | |
y = cos(T2 * 3.9 + C2) * sin(T2 * 2.2 + C2); | |
glVertex3f(x,y,0); | |
x = sin(T2 * 3.7 + C1) * cos(T2 * 1.3 + C2); | |
y = cos(T2 * 3.6 + C1) * sin(T2 * 1.1 + C2); | |
glVertex3f(x,y,0); | |
} | |
glEnd(); | |
[self.ctx flushBuffer]; | |
} | |
@end | |
int main(int argc, const char * argv[]) { | |
@autoreleasepool { | |
[NSApplication sharedApplication]; | |
[MyRunner new]; | |
[NSApp run]; | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment