2013-02-12 88 views
-1

我跟隨lazyfoo.net OpenGL教程,我在使紋理着色器渲染時遇到問題。過去幾天我試圖解決這個問題,我需要一些幫助,因爲我不知道接下來要做什麼。我目前正在使用GLSL 1.2的OpenGL 2.1,我也嘗試過使用GLSL 1.5的OpenGL 3.2。使用glVertexAttribPointer的OpenGL着色器

從我所知道的問題出發圍繞着glVertexAttribPointer函數及其與着色器的通信。當我拿出glVertexAttribPointer並使用glVertexPointer和GL_VERTEX_ARRAY(gl_Vertex代替着色器中的position屬性)時,我能夠獲取原始形狀進行渲染。紋理能夠在沒有着色器的情況下渲染,我只是想能夠使用它們。

這裏是我的着色器程序:

Texture2DProgram::Texture2DProgram() 
{ 
    _vertex_position_2d_location = 0; 
    _texture_coordinate_location = 0; 

    _projection_matrix_location = 0; 
    _model_view_matrix_location = 0; 
    _texture_color_location = 0; 
    _texture_unit_location = 0; 
} 

bool Texture2DProgram::load_program() 
{ 
    //Generate program 
    _program_id = glCreateProgram(); 

    std::string vertex_shader_string = (std::string)("#version 120\n") + 
    "uniform mat4 projection_matrix;\n" + 
    "uniform mat4 model_view_matrix;\n" + 
    "attribute vec2 vertex_position;\n" + 
    "attribute vec2 texture_coordinate;\n" + 
    "varying vec2 texCoord;\n" + 
    "void main() {\n" + 
     "texCoord = texture_coordinate;\n" + 
     "gl_Position = projection_matrix * model_view_matrix * vec4(vertex_position.x, vertex_position.y, 0.0, 1.0);\n" + 
    "}\n"; 

    //Load vertex shader 
    GLuint vertex_shader = load_shader_from_string(vertex_shader_string, GL_VERTEX_SHADER); 

    //Check for errors 
    if(vertex_shader == 0) 
    { 
     glDeleteProgram(_program_id); 
     _program_id = 0; 
     return false; 
    } 

    //Attach vertex shader to program 
    glAttachShader(_program_id, vertex_shader); 

    std::string fragment_shader_string = (std::string)("#version 120\n") + 
    "uniform vec4 texture_color;\n" + 
    "uniform sampler2D texture_unit;\n" + 
    "varying vec2 texCoord;\n" + 
    "void main() { \n" + 
     "gl_FragColor = texture2D(texture_unit,texCoord) * texture_color;\n" + 
    "}\n"; 

    //Create fragment shader 
    GLuint fragment_shader = load_shader_from_string(fragment_shader_string, GL_FRAGMENT_SHADER); 

    //Check for errors 
    if(fragment_shader == 0) 
    { 
     glDeleteProgram(_program_id); 
     _program_id = 0; 
     return false; 
    } 

    //Attach fragment shader to program 
    glAttachShader(_program_id, fragment_shader); 

    //Link program 
    glLinkProgram(_program_id); 

    //Check for errors 
    GLint programSuccess = GL_TRUE; 
    glGetProgramiv(_program_id, GL_LINK_STATUS, &programSuccess); 

    if(programSuccess != GL_TRUE) 
    { 
     printf("Error linking program %d!\n", _program_id); 
     print_program_log(_program_id); 
     glDeleteProgram(_program_id); 
     _program_id = 0; 
     return false; 
    } 

    //Get variable locations 
    _vertex_position_2d_location = glGetAttribLocation(_program_id, "vertex_position"); 
    if(_vertex_position_2d_location == -1) 
    { 
     printf("%s is not a valid glsl program variable!\n", "vertex_position"); 
    } 

    _texture_coordinate_location = glGetAttribLocation(_program_id, "texture_coordinate"); 
    if(_texture_coordinate_location == -1) 
    { 
     printf("%s is not a valid glsl program variable!\n", "texture_coordinate"); 
    } 

    _texture_color_location = glGetUniformLocation(_program_id, "texture_color"); 
    if(_texture_color_location == -1) 
    { 
     printf("%s is not a valid glsl program variable!\n", "texture_color"); 
    } 

    _texture_unit_location = glGetUniformLocation(_program_id, "texture_unit"); 
    if(_texture_unit_location == -1) 
    { 
     printf("%s is not a valid glsl program variable!\n", "texture_unit"); 
    } 

    _projection_matrix_location = glGetUniformLocation(_program_id, "projection_matrix"); 
    if(_projection_matrix_location == -1) 
    { 
     printf("%s is not a valid glsl program variable!\n", "projection_matrix"); 
    } 

    _model_view_matrix_location = glGetUniformLocation(_program_id, "model_view_matrix"); 
    if(_model_view_matrix_location == -1) 
    { 
     printf("%s is not a valid glsl program variable!\n", "model_view_matrix"); 
    } 

    return true; 
} 

void Texture2DProgram::set_vertex_pointer(GLsizei stride, const GLvoid* data) 
{ 
    glVertexAttribPointer(_vertex_position_2d_location, 2, GL_FLOAT, GL_FALSE, stride, data); 
} 

void Texture2DProgram::set_texture_coordinate_pointer(GLsizei stride, const GLvoid* data) 
{ 
    glVertexAttribPointer(_texture_coordinate_location, 2, GL_FLOAT, GL_FALSE, stride, data); 
} 

void Texture2DProgram::enable_vertex_pointer() 
{ 
    glEnableVertexAttribArray(_vertex_position_2d_location); 
} 

void Texture2DProgram::disable_vertex_pointer() 
{ 
    glDisableVertexAttribArray(_vertex_position_2d_location); 
} 

void Texture2DProgram::enable_texture_coordinate_pointer() 
{ 
    glEnableVertexAttribArray(_texture_coordinate_location); 
} 

void Texture2DProgram::disable_texture_coordinate_pointer() 
{ 
    glDisableVertexAttribArray(_texture_coordinate_location); 
} 

void Texture2DProgram::update_projection_matrix() 
{ 
    glUniformMatrix4fv(_projection_matrix_location, 1, GL_FALSE, glm::value_ptr(_projection_matrix)); 
} 

void Texture2DProgram::update_model_view_matrix() 
{ 
    glUniformMatrix4fv(_model_view_matrix_location, 1, GL_FALSE, glm::value_ptr(_model_view_matrix)); 
} 

void Texture2DProgram::set_texture_color(ColorRGBA color) 
{ 
    glUniform4f(_texture_color_location, color.r(), color.g(), color.b(), color.a()); 
} 

void Texture2DProgram::set_texture_unit(GLuint unit) 
{ 
    glUniform1i(_texture_unit_location, unit); 
} 

這裏就是我初始化我VBO和IBO:

void Texture::init_vbo() 
{ 
    if (_texture_id != 0 && _vbo == 0) 
    { 

     // Texture coords 
     GLfloat top   = 0.0f; 
     GLfloat bottom  = (GLfloat)_image_height/(GLfloat)_texture_height; 
     GLfloat left  = 0.0f; 
     GLfloat right  = (GLfloat)(_image_width/(GLfloat)_texture_width); 

     // vertex coords 
     GLfloat quad_width = _image_width; 
     GLfloat quad_height = _image_height; 

     // vertex data 
     VertexData2D vertex_data[4]; 

     vertex_data[0].texture_coordinate.s = left; 
     vertex_data[0].texture_coordinate.t = top; 

     vertex_data[1].texture_coordinate.s = right; 
     vertex_data[1].texture_coordinate.t = top; 

     vertex_data[2].texture_coordinate.s = right; 
     vertex_data[2].texture_coordinate.t = bottom; 

     vertex_data[3].texture_coordinate.s = left; 
     vertex_data[3].texture_coordinate.t = bottom; 

     vertex_data[0].position.x = 0.0f; 
     vertex_data[0].position.y = 0.0f; 

     vertex_data[1].position.x = quad_width; 
     vertex_data[1].position.y = 0.0f; 

     vertex_data[2].position.x = quad_width; 
     vertex_data[2].position.y = quad_height; 

     vertex_data[3].position.x = 0.0f; 
     vertex_data[3].position.y = quad_height; 

     GLuint index_data[4]; 

     index_data[0] = 0; 
     index_data[1] = 1; 
     index_data[2] = 2; 
     index_data[3] = 3; 

     // create vbo 
     glGenBuffers(1, &_vbo); 
     glBindBuffer(GL_ARRAY_BUFFER, _vbo); 
     glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(GLfloat), vertex_data, GL_DYNAMIC_DRAW); 

     // create ibo 
     glGenBuffers(1, &_ibo); 
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ibo); 
     glBufferData(GL_ELEMENT_ARRAY_BUFFER, 4*sizeof(GLuint), index_data, GL_DYNAMIC_DRAW); 

     //Unbind buffers 
     glBindBuffer(GL_ARRAY_BUFFER, NULL); 
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, NULL); 
    } 
} 

而且這裏是我渲染:

void Texture::render(GLfloat x, GLfloat y, Rect* clip) 
{ 
    if (_texture_id != 0) 
    { 
     _program->model_view_matrix(glm::mat4()); 

     // Move to rendering point 
     _program->multiply_model_view_matrix(glm::translate<float>(glm::mat4(), glm::vec3(x, y, 0.0f))); 
     _program->update_model_view_matrix(); 

     // texture coordinate 
     glBindTexture(GL_TEXTURE_2D, _texture_id); 
     _program->enable_texture_coordinate_pointer(); 
     _program->set_texture_coordinate_pointer(sizeof(VertexData2D), (GLvoid*)offsetof(VertexData2D, texture_coordinate)); 

     // bind vertex array buffer 
     glBindBuffer(GL_ARRAY_BUFFER, _vbo); 
     _program->set_vertex_pointer(sizeof(VertexData2D), (GLvoid*)offsetof(VertexData2D, position)); 
     _program->enable_vertex_pointer(); 

     // draw quad using vertex data and index data 
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ibo); 
     glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_INT, NULL); 

     _program->disable_vertex_pointer(); 
     _program->disable_texture_coordinate_pointer(); 
    } 
} 

編輯

我解決了這個問題,這是一個與被調用的程序有關的問題。

+0

嘗試使用在線GLSL東西[像這樣(http://stackoverflow.com/a/13874526/44729)。 – genpfault 2013-02-12 15:53:24

+0

你在哪裏調用'glUseProgram()'? – genpfault 2013-02-12 16:53:45

+0

對不起,我正在打掃我的豚鼠籠。該代碼的其餘部分在文件PSDisplay.cpp下的分支PumpkinGL中的https://github.com/tmuntan1/pumpkin-spice上。我不想包含所有的代碼,因爲在我的實驗之後它並不是最漂亮的,我還沒有完成將Allegro代碼移植到OpenGL。該程序正在使用,因爲我可以對着色器進行一些小的更改,並使用glVertexPointer來獲取對象。 – tmuntan1 2013-02-12 17:37:37

回答

0

使用頂點緩衝對象(VBO)時,glVertexAttribPointer的最後一個參數是數據的字節偏移量(即字節數),而不是指向它的指針。從OP中,你可能應該傳遞零作爲最後一個參數。

另外,與NULL相比,您確實希望將零傳入glBindBuffer。雖然它們可能等同於相同的事情(取決於誰定義了NULL的值),但NULL不是GLuint。

0

問題是最有可能在這裏:

glBindTexture(GL_TEXTURE_2D, _texture_id); 

當綁定紋理着色器取樣器綁定紋理SLOT紋理當前綁定到。 因此,嘗試這樣的事:

glActiveTexture(GL_TEXTURE0); 
    glBindTexture(GL_TEXTURE_2D,0); 

給glActiveTexture值可以從GL_TEXTURE0什麼GL_TEXTURE0 + GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS(您使用的顯卡定義)。

要獲得GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS調用

glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, ...);