2013-02-12 93 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, ...);