0

我正在尝试在我的程序中创建自己的顶点和片段着色器(这基本上是一个非常简单的程序,用 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);
}
4

1 回答 1

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 支持不提供此扩展。

所以你需要用老式的方式来做:用glBindAttribLocation. 在链接您的程序之前使用此功能


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

这不仅是不必要的,而且对您要完成的工作具有积极的破坏性,因为它会在您尝试渲染时导致生成 OpenGL 错误。

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


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

sizeof(data)是数组的字节大小。data在大多数机器上,这将是 36 个。您不是在渲染 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);

在编译着色器链接程序后,您应该始终 检查错误。


您的代码似乎是从各种来源复制并粘贴在一起的,以形成某种科学怪人计划。您的大多数问题都源于不同的代码位,它们的作用方式与您计划使用它们的方式不同。你真的应该研究一下这些东西是如何工作的;这样,您就不会遇到这些问题。

于 2012-04-21T16:52:55.470 回答