这是基于中代码的答案https://github.com/beelsebob/Cocoa-GL-Tutorial https://github.com/beelsebob/Cocoa-GL-Tutorial我更改了这些内容: (1) openGL 上下文是在自定义 NSOpenGLView 中创建的,而不是直接附加到窗口。 (2) 我将所有初始化都放在一个函数中。 (3)我把错误验证码全部删除了。这不是你应该为产品做的事情,但我发现更容易理解代码,并且更少的混乱......(查看 Cocoa-GL-Tutorial 以进行正确的错误处理)。
步骤(使用 Xcode 5.1 测试):
- 制作新的可可应用程序
- 将自定义视图添加到界面生成器中的应用程序窗口
- 添加一个 Objective-C 类,子类化 NSOpenGLView,我将其命名为 MyOpenGLView
- 在界面构建器中,选择 CustomView,选择 Identity Inspector(右上角的图标之一),然后在 Custom Class 中选择 MyOpenGLView
- 现在,这是代码
MyOpenGLView.h
:
#import <Cocoa/Cocoa.h>
#import <OpenGL/OpenGL.h>
#import <OpenGL/gl3.h>
@interface MyOpenGLView : NSOpenGLView
{
GLuint shaderProgram;
GLuint vertexArrayObject;
GLuint vertexBuffer;
GLint positionUniform;
GLint colourAttribute;
GLint positionAttribute;
}
@end
这是代码MyOpenGLView.m
:
#import "MyOpenGLView.h"
@implementation MyOpenGLView
- (id)initWithFrame:(NSRect)frame
{
// 1. Create a context with opengl pixel format
NSOpenGLPixelFormatAttribute pixelFormatAttributes[] =
{
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
NSOpenGLPFAColorSize , 24 ,
NSOpenGLPFAAlphaSize , 8 ,
NSOpenGLPFADoubleBuffer ,
NSOpenGLPFAAccelerated ,
NSOpenGLPFANoRecovery ,
0
};
NSOpenGLPixelFormat *pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:pixelFormatAttributes];
self = [super initWithFrame:frame pixelFormat:pixelFormat];
// 2. Make the context current
[[self openGLContext] makeCurrentContext];
// 3. Define and compile vertex and fragment shaders
GLuint vs;
GLuint fs;
const char *vss="#version 150\n\
uniform vec2 p;\
in vec4 position;\
in vec4 colour;\
out vec4 colourV;\
void main (void)\
{\
colourV = colour;\
gl_Position = vec4(p, 0.0, 0.0) + position;\
}";
const char *fss="#version 150\n\
in vec4 colourV;\
out vec4 fragColour;\
void main(void)\
{\
fragColour = colourV;\
}";
vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, &vss;, NULL);
glCompileShader(vs);
fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, &fss;, NULL);
glCompileShader(fs);
printf("vs: %i, fs: %i\n",vs,fs);
// 4. Attach the shaders
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vs);
glAttachShader(shaderProgram, fs);
glBindFragDataLocation(shaderProgram, 0, "fragColour");
glLinkProgram(shaderProgram);
// 5. Get pointers to uniforms and attributes
positionUniform = glGetUniformLocation(shaderProgram, "p");
colourAttribute = glGetAttribLocation(shaderProgram, "colour");
positionAttribute = glGetAttribLocation(shaderProgram, "position");
glDeleteShader(vs);
glDeleteShader(fs);
printf("positionUniform: %i, colourAttribute: %i, positionAttribute: %i\n",positionUniform,colourAttribute,positionAttribute);
// 6. Upload vertices (1st four values in a row) and colours (following four values)
GLfloat vertexData[]= { -0.5,-0.5,0.0,1.0, 1.0,0.0,0.0,1.0,
-0.5, 0.5,0.0,1.0, 0.0,1.0,0.0,1.0,
0.5, 0.5,0.0,1.0, 0.0,0.0,1.0,1.0,
0.5,-0.5,0.0,1.0, 1.0,1.0,1.0,1.0};
glGenVertexArrays(1, &vertexArrayObject;);
glBindVertexArray(vertexArrayObject);
glGenBuffers(1, &vertexBuffer;);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, 4*8*sizeof(GLfloat), vertexData, GL_STATIC_DRAW);
glEnableVertexAttribArray((GLuint)positionAttribute);
glEnableVertexAttribArray((GLuint)colourAttribute );
glVertexAttribPointer((GLuint)positionAttribute, 4, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), 0);
glVertexAttribPointer((GLuint)colourAttribute , 4, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (char*)0+4*sizeof(GLfloat));
return self;
}
- (void)drawRect:(NSRect)dirtyRect
{
[super drawRect:dirtyRect];
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
GLfloat p[]={0,0};
glUniform2fv(positionUniform, 1, (const GLfloat *)&p;);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
[[self openGLContext] flushBuffer];
}
@end