2014-08-29 116 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

相關問題