让GLSL 1.5在Mac OS X上运行

时间:2012-04-21 10:55:43

标签: objective-c macos opengl shader

我正在尝试在我的程序中创建自己的顶点和片段着色器(这基本上是一个用VBO显示三角形的非常简单的程序)。但是,当我尝试运行它时,我总是会看到一个没有任何显示的黑屏。我检查了编译日志,它返回没有错误。我还没有使用我自己的自定义着色器运行程序,这让我想知道我在这里做错了什么。我在OpenGL 3.2和GLSL 1.5上运行我的代码

以下是我正在尝试运行的代码


GLuint vbo;

GLfloat data[] = {0.0, 0.0, -5.0,
                  1.0, 0.0, -5.0,
                  1.0, 1.0, -5.0
};

const char *vertexShader = "\n\
#version 150\n\
\n\
layout (location=0) in vec4 position;\n\
void main()\n\
{\n\
gl_Position = position;\n\
}\n\
";

const char *fragmentShader = "\n\
#version 150\n\
\n\
out vec4 outColor;\n\
\n\
void main()\n\
{\n\
    outColor = vec4(1.0, 0.0, 0.0, 1.0);\n\
}";


- (void)drawRect:(NSRect)dirtyRect
{
    glClear(GL_COLOR_BUFFER_BIT);

    glMatrixMode(GL_MODELVIEW);

    glLoadIdentity();

    glUseProgram(programId);

    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);

    glEnableClientState(GL_VERTEX_ARRAY);

    glVertexPointer(3, GL_FLOAT, 0, 0);

    glDrawArrays(GL_TRIANGLES, 0, sizeof(data));

    glFlush();


    glDisableClientState(GL_VERTEX_ARRAY);

}

-(void)reshape
{
    glViewport(0, 0, w, h);
    gluPerspective(45.0,                  //The camera angle
                   (double)w / (double)h, //The width-to-height ratio
                   1.0,                   //The near z clipping coordinate
                   200.0); 
}

-(void)prepareOpenGL
{
    glEnable(GL_DEPTH_TEST);  

    glGenBuffersARB(1, &vbo);
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);
    glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(data), data, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, 0, 0, 0);


    vertexShaderId = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShaderId, 1, &vertexShader, NULL);

    glCompileShader(vertexShaderId);

    GLint completed;
    glGetShaderiv(vertexShaderId, GL_COMPILE_STATUS, &completed);

    if (!completed)
    {
        GLint length;
        GLchar *log;
        glGetShaderiv(vertexShaderId, GL_INFO_LOG_LENGTH, &length);

        log = (GLchar *)malloc(length);
        glGetShaderInfoLog(vertexShaderId, length, &length, log);
        fprintf(stderr, "Vertex compile log = '%s'\n", log);
    }



    fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShaderId, 1, &fragmentShader, NULL);
    glCompileShader(fragmentShaderId);

    GLint complete;

    glGetShaderiv(fragmentShaderId, GL_COMPILE_STATUS, &complete);

    if (!complete)
    {
        GLint length;
        GLchar *log;
        glGetShaderiv(fragmentShaderId, GL_INFO_LOG_LENGTH, &length);

        log = (GLchar *)malloc(length);
        glGetShaderInfoLog(fragmentShaderId, length, &length, log);
        fprintf(stderr, "fragment compile log = '%s'\n", log);
    }

    programId = glCreateProgram();

    glAttachShader(programId, vertexShaderId);
    glAttachShader(programId, fragmentShaderId);

    glLinkProgram(programId);

    glUseProgram(programId);
}

1 个答案:

答案 0 :(得分:9)

这里有几个问题。从上到下:


GLfloat data[] = {0.0, 0.0, -5.0,
                  1.0, 0.0, -5.0,
                  1.0, 1.0, -5.0
};

此数据不可见,因为Z值超出了查看量[-1,1]。尝试使用0.0代替。


#version 150\n\
\n\
layout (location=0) in vec4 position;

layout(location=0)仅适用于两种情况下的顶点着色器输入:

  1. 您使用的是GLSL 3.30或更高版本。您的着色器显示#version 150
  2. 您正在使用ARB_explicit_attrib_location扩展程序。在这种情况下,您需要#extension声明才能在着色器中激活它。另外,我知道OSX的GL 3.2支持确实提供此扩展。
  3. 所以你需要用老式的方式来做:用glBindAttribLocationUse this function before you link your program


    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(3, GL_FLOAT, 0, 0);
    

    这不仅是不必要的,它还会对您要完成的操作产生主动破坏性,因为它会在您尝试渲染时导致生成OpenGL错误。

    如果您使用的是通用属性,则不需要旧式属性。


    glDrawArrays(GL_TRIANGLES, 0, sizeof(data));
    

    sizeof(data)data数组的字节中的大小。在大多数机器上,那将是36.你渲染36个顶点;你正在渲染三个。所以这应该是:

    glDrawArrays(GL_TRIANGLES, 0, 3);
    

    gluPerspective(45.0,                  //The camera angle
                   (double)w / (double)h, //The width-to-height ratio
                   1.0,                   //The near z clipping coordinate
                   200.0); 
    

    这不是一个完全没有意义的问题。您使用着色器进行渲染,而您没有使用内置矩阵。这确实没有


    glGenBuffersARB(1, &vbo);
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);
    glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(data), data, GL_STATIC_DRAW);
    

    这也可能不是“问题”,但也可能是。以“ARB”结尾的函数和枚举器代表OpenGL扩展。所以你正在使用ARB_vertex_buffer_object扩展所公开的函数。

    此扩展程序自GL 1.4以来一直是核心。实际上,您甚至没有使用一致扩展名(这可能会出现问题)。您正在使用ARB扩展设置缓冲区的数据,但在渲染时使用核心功能。

    放弃ARB扩展程序并使用核心功能。


        log = (GLchar *)malloc(length);
        glGetShaderInfoLog(vertexShaderId, length, &length, log);
        fprintf(stderr, "Vertex compile log = '%s'\n", log);
    

    这不会导致错误,但是......您对free的呼叫在哪里?


    glLinkProgram(programId);
    glUseProgram(programId);
    

    编辑着色器链接程序后,总是 check for errors


    您的代码似乎已经从各种来源复制粘贴,形成某种科学怪人的程序。您的大部分问题源于不同的代码,这些代码与您计划使用它们的方式有所不同。你真的应该调查这些东西是如何运作的;这样,你就不会遇到这些问题。