2016-06-09 134 views
-1

我在MacOSX 10.10上使用OpenGL和SDL2。我一直在嘗試在現代OpenGL中使用VAO和VBO,但我無法讓它們繪製。我的着色器非常簡單,但根據我一直試圖遵循的教程,他們應該工作。我沒有收到任何錯誤,但仍然無法正常工作。我收到的只是一個完全黑色的窗口。如果有人能夠幫助我瞭解我的問題在哪裏以及如何解決問題,我將不勝感激。我希望我不重複先前的問題,但是我已經搜索和搜索,沒有找到任何解決這個問題的方法。這裏是我的代碼:OpenGL - 無法獲取頂點陣列對象和頂點緩衝區對象繪製

vertexShader.glsl:

#version 330 core 

layout(location = 0) in vec3 vertexPosition_modelspace; 

void main(){ 
    gl_Position.xyz = vertexPosition_modelspace; 
    gl_Position.w = 1.0; 
} 

fragmentShader.glsl

#version 330 core 

out vec4 color; 

void main(){ 
    color = vec4(1.0, 1.0, 0.0, 1.0); 
} 

這裏是我的加載着色器代碼,裏面有工作,沒有提供任何錯誤:

//Note: PXConsole is a util class for printing to the console. 
GLuint loadShaders(std::string vertexPath, std::string fragmentPath){ 

const char* vertexShaderPath = vertexPath.c_str(); 
const char* fragmentShaderPath = fragmentPath.c_str(); 
// Create the shaders 
GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER); 
GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER); 

// Read the Vertex Shader code from the file 
std::string VertexShaderCode; 
std::ifstream VertexShaderStream(vertexShaderPath, std::ios::in); 
if(VertexShaderStream.is_open()){ 
    std::string Line = ""; 
    while(getline(VertexShaderStream, Line)) 
     VertexShaderCode += "\n" + Line; 
    VertexShaderStream.close(); 
}else{ 
    std::string error ="Could not open vertex shader at \"" + vertexPath +"\". Is the the path written correctly? "; 
    PXConsole::err(error); 
    return 0; 
} 

// Read the Fragment Shader code from the file 
std::string FragmentShaderCode; 
std::ifstream FragmentShaderStream(fragmentShaderPath, std::ios::in); 
if(FragmentShaderStream.is_open()){ 
    std::string Line = ""; 
    while(getline(FragmentShaderStream, Line)) 
     FragmentShaderCode += "\n" + Line; 
    FragmentShaderStream.close(); 
}else{ 
    std::string error ="Could not open fragment shader at \"" + fragmentPath +"\". Is the the path written correctly? "; 
    PXConsole::err(error); 
    return 0; 
} 

GLint Result = GL_FALSE; 
int InfoLogLength; 


// Compile Vertex Shader 
PXConsole::info("Compiling Vertex Shader at: " + vertexPath); 
char const * VertexSourcePointer = VertexShaderCode.c_str(); 
glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL); 
glCompileShader(VertexShaderID); 

// Check Vertex Shader 
glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result); 
glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength); 
if (InfoLogLength > 0){ 
    std::vector<char> VertexShaderErrorMessage(InfoLogLength+1); 
    glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]); 
    PXConsole::err(&VertexShaderErrorMessage[0]); 
} 



// Compile Fragment Shader 
PXConsole::info("Compiling Fragment Shader at: " + fragmentPath); 
char const * FragmentSourcePointer = FragmentShaderCode.c_str(); 
glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL); 
glCompileShader(FragmentShaderID); 

// Check Fragment Shader 
glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result); 
glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength); 
if (InfoLogLength > 0){ 
    std::vector<char> FragmentShaderErrorMessage(InfoLogLength+1); 
    glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]); 
    PXConsole::err(&FragmentShaderErrorMessage[0]); 
} 



// Link the program 
PXConsole::info("Linking Shader Program!"); 
GLuint ProgramID = glCreateProgram(); 
glAttachShader(ProgramID, VertexShaderID); 
glAttachShader(ProgramID, FragmentShaderID); 
glLinkProgram(ProgramID); 

// Check the program 
glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result); 
glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength); 
if (InfoLogLength > 0){ 
    std::vector<char> ProgramErrorMessage(InfoLogLength+1); 
    glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]); 
    PXConsole::err(&ProgramErrorMessage[0]); 
} 


glDetachShader(ProgramID, VertexShaderID); 
glDetachShader(ProgramID, FragmentShaderID); 

glDeleteShader(VertexShaderID); 
glDeleteShader(FragmentShaderID); 

return ProgramID; 

這是我用SDL2創建的OpenGL上下文:

SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); 
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); 
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); 
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); 
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); 
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); 

appWindow = SDL_CreateWindow("Window Title", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_OPENGL); 

if (!application->appWindow) { 
    PXConsole::err("Couldn't Initialize Window!!"); 
    endApp(); 
} 

appGLContext = SDL_GL_CreateContext(appWindow); 

而且最後這裏是我的渲染功能,這是一個循環:

void render(){  

    GLuint vaoID; 
    GLuint posVBO; 

    GLfloat positions[] = {-0.5f, -0.5f, 1.0f, 
     0.5f, -0.5f, 1.0f, 
     0.5f, 0.5f, 1.0f, 
     -0.5f, 0.5f, 1.0f}; 


    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

    //shaderProgramID = the function mentioned above in an initializating function and has no errors finding the shader files 

    glUseProgram(shaderProgramID); 

    glColor4f(1.0, 1.0, 0.0, 1.0); 

    glGenVertexArrays(1, &vaoID); 
    glBindVertexArray(vaoID); 

    glGenBuffers(1, &posVBO); 
    glBindBuffer(GL_ARRAY_BUFFER, posVBO); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW); 

    glEnableVertexAttribArray(0); 

    glBindBuffer(GL_ARRAY_BUFFER, posVBO); 
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); 
    glColor4f(1.0, 0.0, 0.0, 1.0); 
    glDrawArrays(GL_QUADS, 0, 4); 
    glDisableVertexAttribArray(0); 

    SDL_GL_SwapWindow(appWindow); 
} 

我希望這是足夠的代碼,以便能夠確定問題。謝謝你的幫助!

回答

1

一個VAO基本上存儲由glVertexAttribPointer設置的屬性綁定。爲了存儲它們,必須在VAO綁定時設置它們。就你而言,你首先解除綁定,然後設置屬性綁定。

此外,一個應該永不在每個幀中生成緩衝區或vaos。這是在初始化期間必須完成的事情。

既然你在問題中說你沒有得到任何錯誤:每幀至少有三個。你如何檢查錯誤?

  • glColor4f已從OpenGL 3.3 Core Profile中移除。調用此應該會導致錯誤。 (2x)
  • GL_QUADS在覈心配置文件中不是有效的drawing mode,還應該生成錯誤。

一個修正版本可能看起來像這樣

初始化

glGenVertexArrays(1, &vaoID); 
glBindVertexArray(vaoID); 

glGenBuffers(1, &posVBO); 
glBindBuffer(GL_ARRAY_BUFFER, posVBO); 
glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW); 
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); 

glEnableVertexAttribArray(0); 

渲染

glBindVertexArray(vaoID); 
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 

更新

當您想在每個幀中使用新的座標時,仍然會生成緩衝區並在初始化中設置VAO。你在每一幀做的是新的數據上傳到像這樣的緩衝區(假設頂點的數量保持不變):

glBindBuffer(GL_ARRAY_BUFFER, posVBO); 
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(positions), positions); 

這將覆蓋緩衝區的數據,而無需分配新的GPU內存。請注意,您必須在初始化時使用正確大小調用glBufferData一次,但使用nullptr作爲數據指針來爲緩衝區分配內存。

+0

非常感謝您的幫助和建議!我更新以正確的方式使用OpenGL。我在每幀中生成緩衝區的原因是因爲我習慣於改變對象的位置以使其移動,而不是使用OpenGL相機。我不認爲我正在檢查OpenGL錯誤。我應該怎麼做?而且你的解決方案几乎可以完美工作,除了調用glDisableVertexAttribArray(0)只允許形狀出現在一個框架上,然後消失。我應該在節目結束時打電話嗎?但真的,再次感謝您的幫助和建議! – Gyo

+0

嗯,對不起。那一個溜走了。你不必這麼叫。這隻有在不使用VAO時纔有意義。在解決問題時,可以在'glDeleteVertexArray'方法中完成。 – BDL

+0

對於位置更新:請參閱答案中的更新。 – BDL

相關問題