2014-02-21 91 views
1

我有一個包含位置(3),紋理(2)和頂點法線(3)的頂點數據類型。我使用glVertexAttribPointer將這些傳遞給vertex shader(請參閱here)。glVertexAttribPointer:繪製法線而不是頂點

不幸的是,無論我裝入什麼樣的模型,它都給了我死星 - 基本上是一個頂點球體,只有當我切換到線框渲染時纔可見。

我試着從我的模塊中刪除了一堆頂點,最終到達了一個部分構建的死星。在這一點上,很明顯它正在繪製法線,就好像它們是頂點一樣。我不知道頂點正在被繪製。

我通過drawing two additional triangles確認了我的假設 - 一個表示頂點應該是而另一個表示法線。我也用1.1來縮放它們,以便它們可以與對象本身區分開來。是的,它絕對是繪製法線而不是頂點。

有沒有人有任何想法爲什麼?我嘗試切換着色器中屬性的順序,但這並沒有幫助(奇怪)。

Here's the complete minimum working example以及兩個測試對象(complete,n20r4_d5.obj;以及非常偏,test11.obj)。

回答

4

您正在使用OpenGL 2.1,因此您必須使用glGetAttribLocation()來提取屬性索引。你不能只是希望GLSL編譯穿0頂點和texcoords上2

void render(Shader* shader_program = NULL) 
{ 
    if (shader_program) 
     shader_program->bind(); 

    GLint position_loc = glGetAttribLocation(shader_program->id(), "position"); 
    GLint tex_loc = glGetAttribLocation(shader_program->id(), "tex"); 
    GLint normal_loc = glGetAttribLocation(shader_program->id(), "normal"); 

    glEnableVertexAttribArray(position_loc); 
    glEnableVertexAttribArray(normal_loc); 
    glEnableVertexAttribArray(tex_loc); 

    for (size_t i = 0; i < entries.size(); ++i) 
    { 
     glBindBuffer(GL_ARRAY_BUFFER, entries[i].vb); 

     // I think this tells it where to look for the vertex information we've loaded. 
     glVertexAttribPointer(position_loc, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0); 
     glVertexAttribPointer(normal_loc, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)12); // starts at 12 because 3 floats for position before 2 floats for normal 
     glVertexAttribPointer(tex_loc, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)20); // makes room for 5 floats 
     ... 

你也可以告訴 OpenGL的情況下把他們(glBindAttribLocation())你鏈接您的着色器,但你有事情的方式之前,設置會讓這個有點麻煩。

在OpenGL 3.1+中,您可以強制編譯器通過layout qualifier將特性放在特定索引上。

+1

佈局限定符上的優點。如果你有一組使用一致佈局的着色器,你可以在你的C/C++代碼中創建一個枚舉,並且更直觀地引用這些屬性 – Jherico

+0

呵呵。爲什麼着色器程序以不同於聲明方式的方式排序?這對我來說很不直觀。 –

相關問題