我跟隨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();
}
}
編輯
我解決了這個問題,這是一個與被調用的程序有關的問題。
嘗試使用在線GLSL東西[像這樣(http://stackoverflow.com/a/13874526/44729)。 – genpfault 2013-02-12 15:53:24
你在哪裏調用'glUseProgram()'? – genpfault 2013-02-12 16:53:45
對不起,我正在打掃我的豚鼠籠。該代碼的其餘部分在文件PSDisplay.cpp下的分支PumpkinGL中的https://github.com/tmuntan1/pumpkin-spice上。我不想包含所有的代碼,因爲在我的實驗之後它並不是最漂亮的,我還沒有完成將Allegro代碼移植到OpenGL。該程序正在使用,因爲我可以對着色器進行一些小的更改,並使用glVertexPointer來獲取對象。 – tmuntan1 2013-02-12 17:37:37