PDA

View Full Version : OpenGL 3.0+ context setup in XCode4 using Lion



geeksweep
01-15-2012, 11:10 PM
I am trying to set up an OpenGL 3.0+ context within XCode 4.

The apple developer website has some vague functionality changes(last updated 6/6/2011). Their shader examples are also listed as OpenGL 2.0. They do have a section but it really only gives you a table of extension changes and the old extensions that have been removed in the core.

I am trying to port all of my windows code using glut but I just haven't been able to find examples of how to go into XCode4 and make everything work seamlessly. I actually have the 3rd edition of the Hillegass Mac OSX programming book but there is one section only about OpenGL and his code uses the fixed functionality pipeline.

I would appreciate it if anyone has any links that is dedicated on setting up an opengl context within Xcode 4 using OpenGL 3.0+.

McLeary
01-16-2012, 05:28 AM
I use the same code for both windows and mac (of course, checking for OpenGL version) and the context setup is pretty much the same.

I think XCode has nothing to do with the context setup since it is "just" an IDE.

What exactly are the problems you're getting?

Ragnemalm
01-16-2012, 07:54 AM
I use the same code for both windows and mac (of course, checking for OpenGL version) and the context setup is pretty much the same.

"Pretty much the same"? Really? What interface are you using? CGL? NSOpenGL is hardly identical to MS Windows.

There is at least one 3.2 demo from Apple, NSOpenGL-based. Hard to find though, but I can return with info about it once I get to the computer where I tested it. It worked but was too xib-dependent for my taste.

geeksweep
01-16-2012, 09:33 AM
@Ragne - would appreciate the think to that demo when you get back. thanks! I really don't understand apples lack of interest in opengl in general.

Alfonse Reinheart
01-16-2012, 10:57 AM
It's not so much "lack of interest in OpenGL" as "lack of interest in MacOS". When you're making enough money to swim through Scrooge McDuck style on iPhones and iPads, what happens on your desktop platform just isn't that important.

geeksweep
01-16-2012, 12:04 PM
@Alfonse - do you have a link somewhere out there that deals with setting up opengl 3.0 context? that is NSOpenGLView based. not glut or glew or freeglut. thanks...

Alfonse Reinheart
01-16-2012, 01:19 PM
It would be easier to download GLFW (GLEW is a function loading library) and just read it's source code to figure out how it works.

Ragnemalm
01-16-2012, 02:26 PM
@Ragne - would appreciate the think to that demo when you get back. thanks! I really don't understand apples lack of interest in opengl in general.
It wasn't Apple's, it was a third party demo:

https://github.com/beelsebob

It did run, but I didn't like that it was xib based. I made my own instead, nibless. Here is a preliminary version, with quite a bit of remains of two other demos (one of my own, one of someone else):


// Based on the Cocoa variant of the "minimal animation" demo
// Working, reasonably simple 3.2 demo!!!
// Preliminary demo by Ingemar Ragnemalm 2012
// for the 3.2 update of my course book.
// Partially based on other GL3.2 demos, especially that demo with two triangles.
// (Should be referenced I guess but I can't do that right now.)
// Later versions appears in my book.

#import <Cocoa/Cocoa.h>
#include <OpenGL/gl3.h>

#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <string.h>

// Globals
// Data would normally be read from files
GLfloat vertices[] = { -1.0f,0.0f,0.0f,
0.0f,1.0f,0.0f,
0.0f,0.0f,0.0f };
GLfloat colours[] = { 1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f };
GLfloat vertices2[] = { 0.0f,0.0f,0.0f,
0.0f,-1.0f,0.0f,
1.0f,0.0f,0.0f };

// two vertex array objects, one for each object drawn
unsigned int vertexArrayObjID[2];
// three vertex buffer objects in this example
unsigned int vertexBufferObjID[3];

// Note: free data afterwards.
char* loadFile(char *filename, GLint *fSize)
{
char * data;
FILE *theFile;
char c;
long howMuch;

// Get file length
theFile = fopen(filename, "rb");
if (theFile == NULL)
{
printf("%s not found\n", filename);
return NULL;
}
howMuch = 0;
c = 0;
while (c != EOF)
{
c = getc(theFile);
howMuch++;
}
fclose(theFile);

printf("%ld bytes\n", howMuch);

// Read it again
data = (char *)malloc(howMuch);
theFile = fopen(filename, "rb");
fread(data, howMuch-1,1,theFile);
fclose(theFile);
data[howMuch-1] = 0;

printf("\n--- Shader source %s ---\n%s\n-- end of %s --\n", filename, data, filename);
printf("%s loaded from disk\n", filename);
*fSize = howMuch;

return data;
}

void dumpInfo(void)
{
printf ("Vendor: %s\n", glGetString (GL_VENDOR));
printf ("Renderer: %s\n", glGetString (GL_RENDERER));
printf ("Version: %s\n", glGetString (GL_VERSION));
printf ("GLSL: %s\n", glGetString (GL_SHADING_LANGUAGE_VERSION));
checkError ("dumpInfo");
}

/* report GL errors, if any, to stderr */
void checkError(const char *functionName)
{
GLenum error;
while (( error = glGetError() ) != GL_NO_ERROR)
{
fprintf (stderr, "GL error 0x%X detected in %s\n", error, functionName);
}
}

// printShaderInfoLog
// From OpenGL Shading Language 3rd Edition, p215-216
// Display (hopefully) useful error messages if shader fails to compile
void printShaderInfoLog(GLint shader)
{
GLint infoLogLen = 0;
GLsizei charsWritten = 0;
GLchar *infoLog;

glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &amp;infoLogLen);

// should additionally check for OpenGL errors here

if (infoLogLen > 0)
{
infoLog = (GLchar *)malloc(infoLogLen); //new GLchar[infoLogLen];
// error check for fail to allocate memory omitted
glGetShaderInfoLog(shader,infoLogLen, &amp;charsWritten, infoLog);
printf("Infolog: %s\n", infoLog);
free(infoLog);
}
else
printf("No infolog\n");

// should additionally check for OpenGL errors here
}


void init(void)
{
// GL inits
glClearColor(0.2,0.2,0.5,0);
glEnable(GL_DEPTH_TEST);
checkError("GL inits");

// Would load objects from file here - but using globals in this example

// Allocate Vertex Array Objects
glGenVertexArrays(2, &amp;vertexArrayObjID[0]);
// Setup first Vertex Array Object
glBindVertexArray(vertexArrayObjID[0]);
glGenBuffers(2, vertexBufferObjID);

// VBO for vertex data
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObjID[0]);
glBufferData(GL_ARRAY_BUFFER, 9*sizeof(GLfloat), vertices, GL_STATIC_DRAW);
glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);

// VBO for colour data
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObjID[1]);
glBufferData(GL_ARRAY_BUFFER, 9*sizeof(GLfloat), colours, GL_STATIC_DRAW);
glVertexAttribPointer((GLuint)1, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);

// Setup second Vertex Array Object
glBindVertexArray(vertexArrayObjID[1]);
glGenBuffers(1, &amp;vertexBufferObjID[2]);

// VBO for vertex data
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObjID[2]);
glBufferData(GL_ARRAY_BUFFER, 9*sizeof(GLfloat), vertices2, GL_STATIC_DRAW);
glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);

glBindVertexArray(0);

checkError("init");
}



void initShaders(void)
{
GLuint p, f, v;

char *vs,*fs;

v = glCreateShader(GL_VERTEX_SHADER);
f = glCreateShader(GL_FRAGMENT_SHADER);

// load shaders & get length of each
GLint vlen;
GLint flen;
vs = loadFile("minimal.vert", &amp;vlen);
fs = loadFile("minimal.frag", &amp;flen);

const char * vv = vs;
const char * ff = fs;

glShaderSource(v, 1, &amp;vv, NULL); // &amp;vlen);
glShaderSource(f, 1, &amp;ff, NULL); // &amp;flen);

GLint compiled;

glCompileShader(v);
glGetShaderiv(v, GL_COMPILE_STATUS, &amp;compiled);
if (!compiled)
{
printf("Vertex shader not compiled.\n");
printShaderInfoLog(v);
}

glCompileShader(f);
glGetShaderiv(f, GL_COMPILE_STATUS, &amp;compiled);
if (!compiled)
{
printf("Fragment shader not compiled.\n");
printShaderInfoLog(f);
printf("-----\n");
}

p = glCreateProgram();

glBindAttribLocation(p,0, "in_Position");
glBindAttribLocation(p,1, "in_Color");

glAttachShader(p,v);
glAttachShader(p,f);

glLinkProgram(p);
glUseProgram(p);

free(vs); // dont forget to free allocated memory
free(fs); // we allocated this in the loadFile function...

checkError("init shader");
}

void display(void)
{
checkError("pre display");

// clear the screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glBindVertexArray(vertexArrayObjID[0]); // First VAO
glDrawArrays(GL_TRIANGLES, 0, 3); // draw first object

glBindVertexArray(vertexArrayObjID[1]); // select second VAO
glVertexAttrib3f((GLuint)1, 1.0, 0.0, 0.0); // set constant color attribute
glDrawArrays(GL_TRIANGLES, 0, 3); // draw second object

glBindVertexArray(0);

checkError("display");
}

void reshape(int w, int h)
{
glViewport(0,0,(GLsizei)w,(GLsizei)h);
}



// -----------

// Globals (was in GLViewDataPtr)
NSOpenGLContext *m_context;
float lastWidth, lastHeight;
NSView *theView;

void MakeContext(NSView *view)
{
// NSWindow *w;
NSOpenGLPixelFormat *fmt;

NSOpenGLPixelFormatAttribute attrs[] =
{
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
NSOpenGLPFADoubleBuffer,
NSOpenGLPFADepthSize, 32,
0
};

// Create custom data pointer
theView = view;

// Init GL context
fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes: &amp;attrs];

m_context = [[NSOpenGLContext alloc] initWithFormat: fmt shareContext: nil];
[fmt release];
[m_context makeCurrentContext];

checkError("makeCurrentContext");
}



// -------------------- View ------------------------

@interface TestView : NSView { }
-(void)drawRect:(NSRect)rect;
@end

float loop;

#define Pi 3.1415

@implementation TestView

-(void)drawRect:(NSRect)rect
{
if (([theView frame].size.width != lastWidth) || ([theView frame].size.height != lastHeight))
{
lastWidth = [theView frame].size.width;
lastHeight = [theView frame].size.height;

// Only needed on resize:
[m_context clearDrawable];

reshape([theView frame].size.width, [theView frame].size.height);
}

[m_context setView: theView];
[m_context makeCurrentContext];

// Draw
display();

[m_context flushBuffer];
[NSOpenGLContext clearCurrentContext];

loop = loop + 0.1;
}

-(void)windowWillClose:(NSNotification *)note
{
[[NSApplication sharedApplication] terminate:self];
}
@end


// -------------------- Timer ------------------------

// Mini-mini class for the timer
@interface TimerController : NSObject { }
-(void)timerFireMethod:(NSTimer *)t;
@end

NSTimer *gTimer;
TimerController *myTimerController;
NSView *view;

// Timer!
@implementation TimerController
-(void)timerFireMethod:(NSTimer *)t;
{
[view setNeedsDisplay: YES];
}
@end

// home()

#include <Carbon/Carbon.h>
#include <stdio.h>

void home()
{
CFBundleRef mainBundle = CFBundleGetMainBundle();
CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(mainBundle);
char path[PATH_MAX];
if (!CFURLGetFileSystemRepresentation(resourcesURL, TRUE, (UInt8 *)path, PATH_MAX))
{
// error!
return;
}
CFRelease(resourcesURL);

chdir(path);
printf("Current Path: %s\n", path);
}

// ------------------ Main program ---------------------

NSApplication *myApp;
NSView *view;
NSAutoreleasePool *pool;
NSWindow *window;

int main(int argc, const char *argv[])
{
pool = [NSAutoreleasePool new];
myApp = [NSApplication sharedApplication];
home();

NSRect frame = NSMakeRect(10., 1000., 400., 400.);

window = [NSWindow alloc];
[window initWithContentRect:frame
styleMask:NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask
backing:NSBackingStoreBuffered
defer:false];
[window setTitle:@"Minimal OpenGL animation (Cocoa)"];

view = [TestView alloc];
[view initWithFrame: frame];

// OpenGL init!
MakeContext(view);

init ();
initShaders();
dumpInfo ();

[window setContentView: view];
[window setDelegate: view];
[window makeKeyAndOrderFront: nil];

// Timer
myTimerController = [TimerController alloc];
gTimer = [NSTimer
scheduledTimerWithTimeInterval: 0.02
target: myTimerController
selector: @selector(timerFireMethod:)
userInfo: nil
repeats: YES];

// Main loop
[myApp run];
[pool release]; // Free;
return( EXIT_SUCCESS );
}


Vertex Shader


#version 150

in vec3 in_Position;
in vec3 in_Color;
out vec3 ex_Color;

void main(void)
{
ex_Color = in_Color;
gl_Position = vec4(in_Position, 1.0);
}


Fragment Shader


#version 150

in vec3 ex_Color;
out vec4 out_Color;

void main(void)
{
out_Color = vec4(ex_Color,1.0);
}


This should run pretty nicely. It does for me. Any problems, I can fix them.

Ragnemalm
01-18-2012, 12:44 AM
Nobody tried it yet?