我似乎遇到了一个奇怪的 OpenGL 问题。我的课程一切正常,直到我使地图太大(大约 800x800 是最大值),然后 OpenGL 不绘制任何东西。我已经调用了 glGetBufferSubData,据我所知,顶点和索引缓冲区中的数据似乎都是正确的,但没有绘制任何内容?起初我假设我的代码中某处发生了溢出,但根据 std::numeric_limits 我的顶点和索引迭代器似乎没有接近(有符号)int的最大大小。我在 OpenGL 对象周围使用了很多包装类,但它们非常简单,通常是对其 OpenGL 等效项的内联调用。与原始类型周围的“M_”类型定义相同。下面是我渲染的主循环,我认为问题所在的类,以及输出的 2 个屏幕截图。
正确输出:http: //i.imgur.com/cvC1T7L.png
空白输出,扩展地图后:http: //i.imgur.com/MmmNgj4.png
主循环:
int main(){
//open window
Memento::MainWindow& main_window = Memento::MainWindow::GetInstance();
Memento::MainWindow::Init();
main_window.SetTitle("Memento");
main_window.Open();
//matrices
glmx_mat4 ortho_matrix = {};
glmx_mat4_ortho(0.0f, 800.0f, 600.0f, 0.0f, 5.0f, 25.0f, ortho_matrix);
glmx_mat4 modelview_matrix = {};
glmx_mat4_identity(modelview_matrix);
glmx_vec3 translate_vec = {0.0f, 0.0f, -10.0f};
glmx_mat4_translate(modelview_matrix, translate_vec, modelview_matrix);
glmx_mat4_multiply(ortho_matrix, modelview_matrix, ortho_matrix);
//shaders
Memento::GLShader default_vert_shader("default.vert", GL_VERTEX_SHADER);
default_vert_shader.Compile();
Memento::GLShader default_frag_shader("default.frag", GL_FRAGMENT_SHADER);
default_frag_shader.Compile();
//program
Memento::GLProgram default_program;
default_program.Create();
default_program.AttachShader(default_vert_shader);
default_program.AttachShader(default_frag_shader);
Memento::GLVertexArray default_vert_array;
default_vert_array.Create();
default_vert_array.Bind();
//BufferGameMap class- where I believe the issue lies
Memento::TextureAtlas atlas1("atlas/cat_image.png", "atlas/cat_source.xml");
Memento::BufferGameMap map1("tryagain.tmx", atlas1);
//bind buffers
map1.GetVertexBuffer().Bind();
map1.GetIndexBuffer().Bind();
//upload vertex attributes
default_vert_array.EnableIndex(0);
default_vert_array.IndexData(0, 2, GL_FLOAT, NULL, 8 * sizeof(Memento::M_float));
default_vert_array.BindIndex(default_program, 0, "map_vert");
//link, validate, and use program
default_program.Link();
default_program.Validate();
default_program.Use();
//upload matrix as uniform
glUniformMatrix4fv(default_program.GetUniformLocation("modelviewprojection_matrix"),
1, GL_FALSE, ortho_matrix);
//main draw loop
while(not glfwGetKey(GLFW_KEY_ESC)){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawElements(GL_TRIANGLES, map1.GetIndexBufferLength(), GL_UNSIGNED_INT, NULL);
glfwSwapBuffers();
}
//close window & exit
main_window.Close();
return (0);
}
BufferGameMap 类(问题可能就在这里!):
Memento::BufferGameMap::BufferGameMap(std::string const& file, const Memento::TextureAtlas& atlas):
TmxMap::GameMap(), background_color_color4(), vertex_buffer(), index_buffer(),
vertex_buffer_len(0), index_buffer_len(0){
Create(file, atlas);
}
Memento::M_void Memento::BufferGameMap::Create(std::string const& file, const Memento::TextureAtlas& atlas){
if(IsCreated())Destroy();
TmxMap::GameMap::CreateFromFile(file);
std::vector<TmxMap::Layer> const& layers = GetLayers();
if(not layers.empty()){
const std::vector<TmxMap::Layer>::const_iterator layers_end = layers.end();
std::vector<TmxMap::Layer>::const_iterator layers_iter = layers.begin();
Memento::M_float* vertex_buffer_data = NULL;
Memento::M_uint* index_buffer_data = NULL;
for(; layers_iter != layers_end; ++layers_iter){
vertex_buffer_len += layers_iter -> GetMapTiles().size() * (4 * (2 +
2 + 2 + 2));
index_buffer_len += layers_iter -> GetMapTiles().size() * 6;
}
vertex_buffer_data = new Memento::M_float[vertex_buffer_len];
index_buffer_data = new Memento::M_uint[index_buffer_len];
//fill data to send to the gl
Memento::M_sizei vertex_buffer_iter = 0, index_buffer_iter = 0, index_buffer_quad_iter = 0;
//map data
const Memento::M_uint map_size_x = GetMapSize().x, map_size_y = GetMapSize().y;
const Memento::M_float map_tile_size_x = GetTileSize().x, map_tile_size_y = GetTileSize().y;
//per layer data
std::vector<TmxMap::MapTile> const* map_tiles = NULL;
std::vector<TmxMap::MapTile>::const_iterator map_tiles_iter, map_tiles_end;
//per tile data
Memento::M_float map_origin_x = 0.0f, map_origin_y = 0.0f;
for(layers_iter = layers.begin(); layers_iter != layers_end; ++layers_iter){
map_tiles = &layers_iter -> GetMapTiles();
for(map_tiles_iter = map_tiles -> begin(), map_tiles_end = map_tiles -> end();
map_tiles_iter != map_tiles_end; ++map_tiles_iter,
vertex_buffer_iter += 4 * (2 + 2 + 2 +
2), index_buffer_iter += 6,
index_buffer_quad_iter += 4){
map_origin_x = static_cast<Memento::M_float>(map_tiles_iter -> map_tile_index /
map_size_y) * map_tile_size_x;
map_origin_y = static_cast<Memento::M_float>(map_tiles_iter -> map_tile_index %
map_size_y) * map_tile_size_y;
vertex_buffer_data[vertex_buffer_iter] = map_origin_x;
vertex_buffer_data[vertex_buffer_iter + 1] = map_origin_y;
//=========================================================
vertex_buffer_data[vertex_buffer_iter + 8] = map_origin_x;
vertex_buffer_data[vertex_buffer_iter + 9] = map_origin_y + map_tile_size_y;
//=========================================================
vertex_buffer_data[vertex_buffer_iter + 16] = map_origin_x + map_tile_size_x;
vertex_buffer_data[vertex_buffer_iter + 17] = map_origin_y + map_tile_size_y;
//=========================================================
vertex_buffer_data[vertex_buffer_iter + 24] = map_origin_x + map_tile_size_x;
vertex_buffer_data[vertex_buffer_iter + 25] = map_origin_y;
//=========================================================
index_buffer_data[index_buffer_iter] = index_buffer_quad_iter;
index_buffer_data[index_buffer_iter + 1] = index_buffer_quad_iter + 1;
index_buffer_data[index_buffer_iter + 2] = index_buffer_quad_iter + 2;
index_buffer_data[index_buffer_iter + 3] = index_buffer_quad_iter;
index_buffer_data[index_buffer_iter + 4] = index_buffer_quad_iter + 2;
index_buffer_data[index_buffer_iter + 5] = index_buffer_quad_iter + 3;
}
}
vertex_buffer.Create(GL_ARRAY_BUFFER, GL_STATIC_DRAW);
vertex_buffer.Bind();
vertex_buffer.AllocateRef(vertex_buffer_len * sizeof(Memento::M_float),
static_cast<const Memento::M_void*>(vertex_buffer_data));
vertex_buffer.Unbind();
index_buffer.Create(GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW);
index_buffer.Bind();
index_buffer.AllocateRef(index_buffer_len * sizeof(Memento::M_uint),
static_cast<const Memento::M_void*>(index_buffer_data));
index_buffer.Unbind();
delete[] vertex_buffer_data;
delete[] index_buffer_data;
}
}
顶点着色器:
#version 140
precision highp float;
uniform mat4 modelviewprojection_matrix;
in vec2 map_vert;
void main(){
gl_Position = modelviewprojection_matrix * vec4(map_vert, 0, 1);
}
片段着色器:
#version 140
precision highp float;
out vec4 frag_color;
void main(){
frag_color = vec4(0.4, 0.2, 0.6, 0.5);
}