2014-02-23 115 views
1

我試圖用着色器使用VAO的+ VBO + IBO,但沒有繪製任何對象。我不知道我錯過了什麼。我對C++和GLSL相當陌生,所以我不確定我是否總是用C++搞砸了某些東西,或者如果我無法正確處理OpenGL上下文?VAO + IBO與GLSL着色器的使用

主要功能(用於處理窗口創建代碼丟失。如果你認爲你可能需要檢查它爲好,只是讓我知道。):

int main(int argc, char *argv[]) 
{ 

    //INIT SDL 
    SDL_Init(SDL_INIT_VIDEO); 
    SDL_CreateWindowAndRenderer(400, 300, SDL_WINDOW_OPENGL, &displayWindow, &displayRenderer); 
    SDL_GetRendererInfo(displayRenderer, &displayRendererInfo); 

    /*TODO: Check that we have OpenGL */ 
    if ((displayRendererInfo.flags & SDL_RENDERER_ACCELERATED) == 0 || (displayRendererInfo.flags & SDL_RENDERER_TARGETTEXTURE) == 0) {} 

    SDL_GL_CreateContext(displayWindow); 
    //SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); 

    glewInit(); 
    int error = glGetError(); 
    if (error != GL_NO_ERROR){ std::cout << "Error during glewInit call: " << error << "\n"; }; 

    //glEnable(GL_DEBUG_OUTPUT); 

    Display_InitGL(); 
    error = glGetError(); 
    if (error != GL_NO_ERROR){ std::cout << "Error during Display init: " << error << "\n"; }; 

    Display_SetViewport(400, 300); 
    error = glGetError(); 
    if (error != GL_NO_ERROR){ std::cout << "Error during Display Set Viewport Issue: " << error << "\n"; }; 

    // SET UP TEST OBJ 
    MainChar *player = new MainChar(); 
    player->MainChar_VBO_Func(); 
    GLushort size = player->MainChar_VBO_IndexBuffer_Func(); 
    float count = 0.0; 
    // END SET UP OF TEST OBJ 

    GLint *length = new GLint; 
    const char* vertShdr = readFile("C:\\Users\\JRFerrell\\Documents\\Visual Studio 2013\\Projects\\GLEW Practice\\vertShader.vs", *length); 

    std::cout << vertShdr; 

    GLuint vertShaderId = glCreateShader(GL_VERTEX_SHADER); 

    glShaderSource(vertShaderId, 1, &vertShdr, length); 
    std::cout << "\n\nLength: " << *length; 

    glCompileShader(vertShaderId); 

    GLint *length2 = new GLint; 
    const char* fragShdr = readFile("C:\\Users\\JRFerrell\\Documents\\Visual Studio 2013\\Projects\\GLEW Practice\\fragShader.fs", *length2); 

    GLint fragShaderId = glCreateShader(GL_FRAGMENT_SHADER); 

    glShaderSource(fragShaderId, 1, &fragShdr, length2); 

    glCompileShader(fragShaderId); 

    GLuint shaderProgram = glCreateProgram(); 

    glAttachShader(shaderProgram, vertShaderId); 
     error = glGetError(); 
     if (error != GL_NO_ERROR){ std::cout << "Error during glAttachShader: " << error << "\n"; }; 

    glAttachShader(shaderProgram, fragShaderId); 
     error = glGetError(); 
     if (error != GL_NO_ERROR){ std::cout << "Error during glAttachShader: " << error << "\n"; }; 

    glBindAttribLocation(shaderProgram, 0, "in_Position"); 
    glBindAttribLocation(shaderProgram, 1, "in_Normal"); 

    glLinkProgram(shaderProgram); 
     error = glGetError(); 
     if (error != GL_NO_ERROR){ std::cout << "Error during glLinkProgram: " << error << "\n"; }; 

    // END SHADER PROGRAM DEFINITION 

    //Check info log for errors: 

    int Len = 0; 

    char *Buffer = nullptr; 
    glGetShaderiv(vertShaderId, GL_INFO_LOG_LENGTH, &Len); 
    Buffer = new char[Len]; 
    glGetShaderInfoLog(vertShaderId, Len, &Len, Buffer); 
    std::cout << "Vertex Log:" << std::endl << Buffer << std::endl; 
    delete[] Buffer; 

    glGetShaderiv(fragShaderId, GL_INFO_LOG_LENGTH, &Len); 
    Buffer = new char[Len]; 
    glGetShaderInfoLog(fragShaderId, Len, &Len, Buffer); 
    std::cout << "Fragment Log:" << std::endl << Buffer << std::endl; 
    delete[] Buffer; 

    glGetProgramiv(shaderProgram, GL_INFO_LOG_LENGTH, &Len); 
    Buffer = new char[Len]; 
    glGetProgramInfoLog(shaderProgram, Len, &Len, Buffer); 
    std::cout << "Shader Log:" << std::endl << Buffer << std::endl; 
    delete[] Buffer; 

    // Create VAO. Don't forget to enable all necessary states because the VAO starts with default state, cleaning all states prev called to do so. 
    GLuint VaoId; 
    glGenVertexArrays(1, &VaoId); 
    glBindVertexArray(VaoId); 

    // Bind buffers & set-up VAO vertex pointers 
    glBindBuffer(GL_ARRAY_BUFFER, player->vboID); 
    error = glGetError(); 
    if (error != GL_NO_ERROR){ std::cout << "Error glBindBuffer-vboID: " << error << "\n"; } 
    glEnableClientState(GL_VERTEX_ARRAY); 
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * GL_FLOAT, (const GLvoid *)0); 
    glEnableVertexAttribArray(0); 

    // Set-up VAO normal pointers 
    error = glGetError(); 
    if (error != GL_NO_ERROR){ std::cout << "Error glBindBuffer-vbo init: " << error << "\n"; } 
    glEnableClientState(GL_NORMAL_ARRAY); 
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * GL_FLOAT, (void*)(3 * sizeof(GL_FLOAT))); 
    glEnableVertexAttribArray(1); 

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, player->vboIndexID); 

    GLint maxLength, nAttribs; 
    glGetProgramiv(shaderProgram, GL_ACTIVE_ATTRIBUTES, &nAttribs); 
    glGetProgramiv(shaderProgram, GL_ACTIVE_ATTRIBUTES, &maxLength); 

    //std::cout << "\nmax length: " << maxLength << "\nnAttribs: " << nAttribs; 

    glBindVertexArray(0); 
    error = glGetError(); 
    if (error != GL_NO_ERROR){ std::cout << "Error glBindVertexArray: " << error << "\n"; }; 
    // End VAO init 

    while (1){ 

     glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 
     error = glGetError(); 
     if (error != GL_NO_ERROR){ std::cout << "Error glClearColor: " << error << "\n"; }; 

     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
     error = glGetError(); 
     if (error != GL_NO_ERROR){ std::cout << "Error in glClear: " << error << "\n"; }; 

     glLoadIdentity(); 

     glUseProgram(shaderProgram); 
     glBindVertexArray(VaoId); 

     glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_SHORT, 0); 

        glUseProgram(0); 
     glBindVertexArray(0); 

     SDL_GL_SwapWindow(displayWindow); 

     count -= .1; 

    } 

    SDL_Delay(5000); 

    SDL_Quit(); 

    return 0; 

} 

::着色器代碼::

頂點着色器:

#version 400 

in vec3 in_Position; 
in vec3 in_Normal; 

void main() 
{ 

gl_Position = vec4(in_Position, 1.0); 

} 

片段着色器:

#version 400 

out vec4 FragColor; 

void main() 
{ 

FragColor = vec4(0.0f, 0.5f, 1.0f, 1.0f); 

} 

我的確在這裏看過類似的問題,他們確實幫我解決了一些可能的問題,但到目前爲止,他們顯然沒有證明可以幫助我啓動代碼。我還問了一些其他人在gamedev.net實時聊天,但他們似乎無法看到我出錯的地方。我修正了一個聲明glDoubles而不是浮點的可能的問題,但是實際上沒有vao和着色器,所以這不是(也不可能是)整個或部分問題。

回答

1

快速查看您的代碼我正在努力尋找您將BufferData發送到GPU的位置。

  1. 生成並綁定新的緩衝區

  2. 初始化緩衝區取數據。使用glBufferSubData

  3. 發送數據......對於元件陣列

  4. 重複步驟1至3。

  5. 生成並綁定頂點數組對象。

  6. 設置VertexAttribArray指針並將它們綁定到着色器。

  7. 再次綁定元素緩衝區。使用glBindVertexArray

  8. 解除綁定頂點數組(0)

這是我如何設置使用OpenTK我的緩衝區,則代碼應該是在任何情況下,相當可以理解的和有用的:

// Generate Vertex Buffer Object and bind it so it is current. 
GL.GenBuffers(1, out bufferHandle);   
GL.BindBuffer(BufferTarget.ArrayBuffer, bufferHandle); 


// Initialise storage space for the Vertex Buffer. 
GL.BufferData(BufferTarget.ArrayBuffer, bufferSize, IntPtr.Zero, BufferUsageHint.StaticDraw); 
// Send Position data. 
GL.BufferSubData<Vector3>(
      BufferTarget.ArrayBuffer, noOffset, new IntPtr(sizeOfPositionData), bufferObject.PositionData); 
// Send Normals data, offset by size of Position data. 
GL.BufferSubData<Vector3>(
      BufferTarget.ArrayBuffer, new IntPtr(sizeOfPositionData), new IntPtr(sizeOfNormalsData), bufferObject.NormalsData); 

// Generate Element Buffer Object and bind it so it is current.   
GL.GenBuffers(1, out bufferHandle); 
GL.BindBuffer(BufferTarget.ElementArrayBuffer, bufferHandle); 
GL.BufferData(
      BufferTarget.ElementArrayBuffer, new IntPtr(sizeof(uint) *  bufferObject.IndicesData.Length), bufferObject.IndicesData, BufferUsageHint.StaticDraw); 

GL.BindBuffer(BufferTarget.ArrayBuffer, bufferObject.VboID); 
GL.BindBuffer(BufferTarget.ElementArrayBuffer, bufferObject.IboID); 

// Generate Vertex Array Object and bind it so it is current. 
GL.GenVertexArrays(1, out bufferHandle); 
GL.BindVertexArray(bufferHandle); 

bufferHandle = GL.GetAttribLocation(program, "in_position"); 
GL.EnableVertexAttribArray(bufferHandle); 
GL.BindBuffer(BufferTarget.ArrayBuffer, bufferObject.VboID); 
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, true, Vector3.SizeInBytes, 0); 
GL.BindAttribLocation(program, bufferHandle, "in_position"); 

bufferHandle = GL.GetAttribLocation(program, "in_normal"); 
GL.EnableVertexAttribArray(bufferHandle); 
GL.BindBuffer(BufferTarget.ArrayBuffer, bufferObject.VboID); 
GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, true, Vector3.SizeInBytes, sizeOfPositionData); 
GL.BindAttribLocation(program, bufferHandle, "in_normal"); 

GL.BindBuffer(BufferTarget.ElementArrayBuffer, bufferObject.IboID); 

// IMPORTANT: vertex array needs unbinding here to avoid rendering incorrectly 
GL.BindVertexArray(0); 
1

我不知道是否有以下的將解決您的問題,但我確實看到在你的代碼的一些問題:

glEnableClientState(GL_VERTEX_ARRAY);

你混合這裏過時且不適用內置頂點atttributes與通用頂點屬性。您不需要任何這些glEnableClientState調用 - 您的着色器不使用內置屬性。 glLoadIdentity也是完全不需要的,並且在覈心配置文件上下文無效。

我看到的第二件事是你沒有指定屬性索引,所以GL可以自由映射它們。您也不會查詢它們,但假設它們爲in_Position爲0,in_Normal爲1 - 這絕不是保證是這種情況。在頂點着色器中聲明輸入屬性以實際定義映射時使用layout(location=)限定符,或使用glBindAttribLocation

+0

是的......我對glLoadIdentity調用有一個偷偷摸摸的懷疑,但我認爲這個啓用是我看到的其他tut所必需的。我一直試圖通過查看示例來學習,但顯然我需要更好地瞭解我正在使用的規範。其次,我確實使用glBindAttribLocation。我在連接着色器後立即這樣做,並在將它們鏈接到我的程序之前:glBindAttribLocation(shaderProgram,0,「in_Position」); glBindAttribLocation(shaderProgram,1,「in_Normal」); – JRFerrell

+0

此外,無論出於何種原因,我的上下文都返回了一個警告,告訴我佈局限定符已被棄用,因此我將其取出,並用bindattribloc調用替換它。 – JRFerrell

+0

另外,如果我在glVertexAttribPointer之前或之後調用glEnableVertexAttribArray,只要我最終調用它,這有什麼關係嗎?我看到了混合樣本,有人說他們的版本工作,所以我只是想檢查。 – JRFerrell

0

好,在坐下閱讀4.0版本的文檔之後,我瞭解到,我通過將不正確的步幅和指針傳遞給緩衝區數據的開始,從而搞砸了我的attrib指針。我的想法是,步幅是元素類型的大小乘以屬性元素的數量,所以你會得到你正在尋找的下一個屬性。顯然這不是你應該做的。我改變它爲零,因爲我的屬性是背靠背:

「glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,6 * GL_FLOAT,(void *)(3 * sizeof(GL_FLOAT)));」

- >

「glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,0,(無效*)(3 *的sizeof(GL_FLOAT)));」

然後,我嘗試處理幾乎相同的指針的指針。應該有一個空指針指向第一個緩衝區attrib位置:

「glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,0,(void *)(3 * sizeof(GL_FLOAT)));」

- >

「glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,0,(GLubyte *)NULL);」

一旦我真正坐下來仔細閱讀文檔,我就明白了實際上屬於哪裏。現在着色器正在工作,我可以在很酷的東西上工作......:P感謝大家努力回答我的問題。 :)