最简单,最简约的opengl 3.2可可项目

rob*_*rto 8 opengl cocoa opengl-3

多年来我一直使用传统的openGL和cocoa,但我现在正努力转向openGL 3.2.互联网上有几个例子,但它们都太复杂了(很多甚至在XCode 5.1下都不再编译).有人可以写一个最简单,最简单的最小可可代码的例子,只是为了在NSOpenGLView中绘制一个读三角形吗?(没有花哨的着色器,没有displayCallbacks,代码行越少越好).

小智 7

/sf/answers/1575209961/

在xcode 6.3.2中,我得到了在替换之后运行的示例

(id)initWithFrame:(NSRect)frame

(void)awakeFromNib

和更换

self = [super initWithFrame:frame pixelFormat:pixelFormat];

super.pixelFormat=pixelFormat;

和删除
return self;

或详细写出:

#import "MyOpenGLView.h"

@implementation MyOpenGLView


- (void)awakeFromNib
{
    NSLog(@"...was here");
    // 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];

    super.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));

}


- (void)drawRect:(NSRect)dirtyRect {
    [super drawRect:dirtyRect];

    // Drawing code here.

    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
Run Code Online (Sandbox Code Playgroud)


rob*_*rto 6

这是基于https://github.com/beelsebob/Cocoa-GL-Tutorial中的代码的答案 我更改了这些内容:(1)openGL上下文是在自定义NSOpenGLView中创建的,而不是直接附加到窗口.(2)我在一个函数中完成所有初始化.(3)我删除了所有错误验证码.这不是你应该对产品做的事情,但是我发现更容易理解代码而不是那么混乱......(请查看Cocoa-GL-Tutorial以获得正确的错误处理).

步骤(使用Xcode 5.1测试):

  1. 制作一个新的可可应用程序
  2. 在界面构建器中将自定义视图添加到应用程序窗口
  3. 添加一个Objective-C类,继承NSOpenGLView,我称之为MyOpenGLView
  4. 在界面构建器中,选择CustomView,选择Identity Inspector(右上角的一个图标),然后在Custom Class中选择MyOpenGLView
  5. 现在,这是代码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