2014-08-29 114 views
0

我跟着this OpenGL example一起进行了一些操作,并且我的代码编译完成了,但它无法正常工作。使用顶点缓冲区对象在OpenGL中进行基本线条渲染

我期望看到一个白色的矩形,但是没有任何东西被渲染,而是清晰的颜色。在我致电glDrawArrays后,glGetError告诉我发生了错误1282。我相信这个问题非常明显,但我不明白我要出错的地方。这里是我的问题的简单的例子:

#include <errno.h> 
#include <stdio.h> 

#include <GLFW/glfw3.h> 
#include <GL/gl.h> 

#define WINDOW_W 300 
#define WINDOW_H 300 

static const GLchar *vertex_shader_src = { 
    "#version 440\n" 
    "in vec4 position;\n" 
    "uniform mat4 projection;\n" 
    "void main()\n" 
    "{\n" 
     "\tgl_Position = projection * position;\n" 
    "}\n" 
}; 

static const GLchar *fragment_shader_src = { 
    "#version 440\n" 
    "uniform vec4 color;\n" 
    "out vec4 outputColor;\n" 
    "void main()\n" 
    "{\n" 
     "outputColor = color;\n" 
    "}\n" 
}; 

static GLuint program = 0; 

static GLuint vao = 0; 

static const GLfloat rect_vertices[] = { 
    5.0f, 5.0f, 
    WINDOW_W - 5.0f, 5.0f, 

    WINDOW_W - 5.0f, 5.0f, 
    WINDOW_W - 5.0f, WINDOW_H - 5.0f, 

    WINDOW_W - 5.0f, WINDOW_H - 5.0f, 
    5.0f, WINDOW_H - 5.0f, 

    5.0f, WINDOW_H - 5.0f, 
    5.0f, 5.0f 
}; 

static GLuint rect_vbo = 0; 

int init_program() 
{ 
    GLint status; 
    GLuint vertexShader; 
    GLuint fragmentShader; 

    // Initialize our vertex shader. 

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

    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status); 

    if(status == GL_FALSE) 
     return -EINVAL; 

    // Initialize our fragment shader. 

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

    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &status); 

    if(status == GL_FALSE) 
     return -EINVAL; 

    // Initialize the program. 

    program = glCreateProgram(); 

    glAttachShader(program, vertexShader); 
    glAttachShader(program, fragmentShader); 

    glLinkProgram(program); 

    glGetProgramiv(program, GL_LINK_STATUS, &status); 

    if(status == GL_FALSE) 
     return -EINVAL; 

    // Detach the shaders, now that the program is linked. 

    glDetachShader(program, vertexShader); 
    glDetachShader(program, fragmentShader); 

    // Done! 

    return 0; 
} 

void ortho_matrix(GLfloat *m, GLfloat l, GLfloat r, 
    GLfloat b, GLfloat t, GLfloat n, GLfloat f) 
{ 
    m[0] = 2.0f/(r - l); 
    m[1] = 0.0f; 
    m[2] = 0.0f; 
    m[3] = 0.0f; 

    m[4] = 0.0f; 
    m[5] = 2.0f/(t - b); 
    m[6] = 0.0f; 
    m[7] = 0.0f; 

    m[8] = 0.0f; 
    m[9] = 0.0f; 
    m[10] = -2.0f/(f - n); 
    m[11] = 0.0f; 

    m[12] = 0.0f; 
    m[13] = 0.0f; 
    m[14] = 0.0f; 
    m[15] = 1.0f; 
} 

int gl_color(GLfloat r, GLfloat g, GLfloat b, GLfloat a) 
{ 
    GLint colorVec; 
    GLfloat color[4] = {r, g, b, a}; 

    colorVec = glGetUniformLocation(program, "color"); 

    if(colorVec == -1) 
     return -EINVAL; 

    glUniform4fv(colorVec, 1, color); 

    return 0; 
} 

int set_uniforms(int width, int height) 
{ 
    int r; 
    GLint orthoMatrix; 
    GLfloat matrix[16]; 

    // Set our orthographic projection uniform. 

    orthoMatrix = glGetUniformLocation(program, "projection"); 

    if(orthoMatrix == -1) 
     return -EINVAL; 

    ortho_matrix(matrix, -0.5f, ((GLfloat) (width - 1)) + 0.5f, 
     ((GLfloat) (height - 1)) + 0.5f, -0.5f, 0.0f, 1.0f); 

    glUniformMatrix4fv(orthoMatrix, 1, GL_FALSE, matrix); 

    // Set our rendering color uniform. 

    r = gl_color(1.0f, 1.0f, 1.0f, 1.0f); 

    if(r < 0) 
     return r; 

    // Done! 

    return 0; 
} 

int init_vbo() 
{ 
    glGenBuffers(1, &rect_vbo); 

    glBindBuffer(GL_ARRAY_BUFFER, rect_vbo); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(rect_vertices), 
     rect_vertices, GL_STATIC_DRAW); 
    glBindBuffer(GL_ARRAY_BUFFER, 0); 

    return 0; 
} 

int render() 
{ 
    GLenum err; 

    glBindBuffer(GL_ARRAY_BUFFER, rect_vbo); 
    glEnableVertexAttribArray(0); 
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0); 

    glDrawArrays(GL_LINES, 0, sizeof(rect_vertices)/sizeof(GLfloat)); 

err = glGetError(); 

while(err != GL_NO_ERROR) 
{ 
    printf("glDrawArrays err: %d\n", err); 
    err = glGetError(); 
} 

    glDisableVertexAttribArray(0); 

    return 0; 
} 

int main(void) 
{ 
    int r; 
    GLFWwindow *window; 

    int width; 
    int height; 

    if(!glfwInit()) 
     return -EINVAL; 

    window = glfwCreateWindow(WINDOW_W, WINDOW_H, 
     "My Window", NULL, NULL); 

    if(!window) 
    { 
     glfwTerminate(); 
     return 1; 
    } 

    glfwMakeContextCurrent(window); 

    r = init_program(); 

    if(r < 0) 
    { 
     glfwTerminate(); 
     return 1; 
    } 

    r = init_vbo(); 

    if(r < 0) 
    { 
     glfwTerminate(); 
     return 1; 
    } 

    while(!glfwWindowShouldClose(window)) 
    { 
     // Initialize the GL viewport. 

     glfwGetFramebufferSize(window, &width, &height); 

     r = set_uniforms(width, height); 

     if(r < 0) 
     { 
      glfwTerminate(); 
      return r; 
     } 

     glViewport(0, 0, width, height); 

     glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 
     glClear(GL_COLOR_BUFFER_BIT); 

     glUseProgram(program); 

     // Call the user-provided rendering function. 

     r = render(); 

     if(r < 0) 
     { 
      glfwTerminate(); 
      return r; 
     } 

     // End GL rendering, swap the buffer, and poll for events. 

     glUseProgram(0); 

     glfwSwapBuffers(window); 
     glfwPollEvents(); 
    } 

    glfwTerminate(); 

    return 0; 
} 

我试图寻找这个错误号码,我发现如this,但我真的不知道有什么方法可以找出特别是出错了。

我在做什么错,或者,我怎么能找到?

回答

0

我真的发现了什么地方出了问题。这个错误实际上比我原先想象的要早得多,我在那里制定了我的制服。 This page有了答案 - 特别是:

glUniform不起作用

你可能没有第一绑定正确的着色器。首先调用glUseProgram(myprogram)。

将我的呼叫移动到set_uniforms的下方,调用glUseProgram可以使渲染正常工作。

+2

我很高兴你想通了!当我遇到一个没有意义的错误时,我经常做的事情就是以二进制搜索模式将调用添加到'glGetError()中,直到碰到实际导致错误的代码行。正因为如此,我从来不喜欢“粘性错误”范例。 – user1118321 2014-08-29 04:36:40

+0

@ user1118321这是非常好的,有一个宏准备好,吐出错误被检测到的行,并抢先洒在他们周围的一些(例如在每个函数的末尾) – 2014-08-29 10:07:34

+0

“下面”我相信你的意思是“后”。是的,根据我所经历的(不知道这是你应该期望的),每个程序都会跟踪它自己的制服状态。因此,如果您使用相同着色器渲染更多几何体,但不更新所有制服,则未更新的制服应具有与上次使用该着色器时留下的值相同的值。相当明智。 – 2014-08-29 16:45:57

1

唯一明显的问题,我看到的是参数glDrawArrays()

glDrawArrays(GL_LINES, 0, sizeof(rect_vertices)/sizeof(GLfloat)); 

的第三个参数是顶点的数量,而在这里传递的值是浮点值的数目。由于在此代码使用每个顶点2 float坐标的顶点,这应该是:

glDrawArrays(GL_LINES, 0, sizeof(rect_vertices)/(2 * sizeof(GLfloat))); 

在一个理想的世界,你会查找可能出现的错误在the official man page的错误部分。不幸的现实是,手册页通常不完整,特别是在涉及错误的情况下。所以这是一个很好的起点,但并不总是最后一个字。

如果手册页看起来有问题,要查看事情的底部,有spec文档。我确实看过那里,坦率地说,还不完全清楚究竟是什么导致你的GL_INVALID_OPERATION。我在这里找到了一个候选人:

如果命令将源数据超出缓冲区对象的末尾,则会生成INVALID_OPERATION错误。

但是,这实际上是在glDrawArraysInstanced(),所以它不是我清楚,如果它也适用于glDrawArrays()

另一种选择是你有一个Core Profile上下文。但是你没有要求,并且从我对GLFW文档的理解中,这不是默认的。在核心配置文件中,您必须使用VAO(顶点数组对象)来设置顶点状态。

+0

'glDrawArrays'需要**索引**的数量,而不是缓冲区的长度,这个提示也非常有帮助。那是我遇到的下一个问题。谢谢! – CmdrMoozy 2014-08-29 04:58:47

相关问题