【问题标题】:The simplest, minimalistic, opengl 3.2 cocoa project最简单、极简的opengl 3.2 cocoa项目
【发布时间】:2014-03-15 18:12:21
【问题描述】:

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

【问题讨论】:

  • 问题是您至少需要 2 个基本着色器。我也会考虑使用 GLFW/GLEW 而不是 NSOpenGLView(使用 GLFW 让我的事情变得容易多了)。
  • 谢谢!我刚刚想出了一个具有基本顶点着色器和基本片段着色器的示例。这根本不是一个好的编码示例,但它确实帮助我更好地理解了所有部分是如何组合在一起的......

标签: cocoa opengl opengl-3


【解决方案1】:

这是基于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 #import #import @interface MyOpenGLView : NSOpenGLView { GLuint着色器程序; GLuint 顶点数组对象; GLuint 顶点缓冲区; GLint positionUniform; 闪烁颜色属性; GLint 位置属性; } @结尾

这是MyOpenGLView.m的代码:

#import "MyOpenGLView.h" @implementation MyOpenGLView - (id)initWithFrame:(NSRect)frame { // 1. 创建一个opengl像素格式的上下文 NSOpenGLPixelFormatAttribute pixelFormatAttributes[] = { NSOpenGLPFAOpenGLProfile,NSOpenGLProfileVersion3_2Core, NSOpenGLPFAColorSize , 24 , NSOpenGLPFAAlphaSize , 8 , NSOpenGLPFADoubleBuffer , NSOpenGLPFA加速, NSOpenGLPFNoRecovery , 0 }; NSOpenGLPixelFormat *pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:pixelFormatAttributes]; self = [super initWithFrame:frame pixelFormat:pixelFormat]; // 2. 使上下文成为当前的 [[self openGLContext] makeCurrentContext]; // 3. 定义和编译顶点和片段着色器 胶粘剂与; GLuint fs; const char *vss="#version 150\n\ 统一 vec2 p;\ 在 vec4 位置;\ 在 vec4 颜色;\ 出 vec4 colourV;\ 无效的主要(无效)\ {\ 颜色V = 颜色;\ gl_Position = vec4(p, 0.0, 0.0) + 位置;\ }"; const char *fss="#version 150\n\ 在 vec4 colourV 中;\ 出 vec4 fragColour;\ 无效的主要(无效)\ {\ fragColor = 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. 附加着色器 shaderProgram = glCreateProgram(); glAttachShader(shaderProgram, vs); glAttachShader(shaderProgram, fs); glBindFragDataLocation(shaderProgram, 0, "fragColour"); glLinkProgram(shaderProgram); // 5. 获取指向制服和属性的指针 positionUniform = glGetUniformLocation(shaderProgram, "p"); colourAttribute = glGetAttribLocation(shaderProgram, "color"); positionAttribute = glGetAttribLocation(shaderProgram, "position"); glDeleteShader(vs); glDeleteShader(fs); printf("positionUniform: %i, colourAttribute: %i, positionAttribute: %i\n",positionUniform, colourAttribute,positionAttribute); // 6. 上传顶点(连续第一个四个值)和颜色(跟随四个值) 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 { [超级drawRect:dirtyRect]; glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); glUseProgram(着色器程序); GLfloat p[]={0,0}; glUniform2fv(positionUniform, 1, (const GLfloat *)&p); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); [[self openGLContext] flushBuffer]; } @结尾

【讨论】:

  • 由于某种原因,initWithFrame 函数似乎根本没有被调用。当我按照尼克的回答建议做时,它开始工作了。
【解决方案2】:

https://stackoverflow.com/a/22502999/4946861

在 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

【讨论】:

  • 您能否edit 提供指向其他答案的链接以及您所做更改的完整结果?
猜你喜欢
  • 2016-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-17
相关资源
最近更新 更多