发送太多数据时OpenGL什么都没画?

时间:2013-06-11 04:26:32

标签: c++ opengl shader

我似乎遇到了一个与OpenGL有关的奇怪问题。我的课程一切正常,直到我让地图太大(大约800x800是最大值),然后OpenGL不会绘制任何东西。我已经调用了glGetBufferSubData,据我所知,数据在顶点和索引缓冲区中看起来都是正确的,但是没有任何东西被绘制出来?起初我在我的代码中假设溢出,但根据std :: numeric_limits,我的顶点和索引迭代器似乎没有接近(有符号)int的最大大小。我在OpenGL对象周围使用了很多包装类,但它们非常简单,通常是对其OpenGL等效的内联调用。基本类型周围的“M_”typedef也是如此。下面是我渲染的主循环,我相信问题所在的类,以及输出的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);
}

1 个答案:

答案 0 :(得分:0)

我认为你是running out of stack memory

通过在堆上分配数据,您可以使用进程可用的所有内存,而堆栈限制为1MB。

换句话说:将main范围之外的对象分配移动到global范围。

Memento::TextureAtlas * atlas1;//("atlas/cat_image.png", "atlas/cat_source.xml");
Memento::BufferGameMap * map1;//("tryagain.tmx", atlas1);

int main(){

    atlas1 =    new Memento::TextureAtlas("atlas/cat_image.png", "atlas/cat_source.xml");
    map1 =      new Memento::BufferGameMap("tryagain.tmx", atlas1);

    //.... acess with ->

}

或者如果这不会导致编译器错误:

Memento::TextureAtlas atlas1("atlas/cat_image.png", "atlas/cat_source.xml");
Memento::BufferGameMap map1("tryagain.tmx", atlas1);

int main(){
    //.... acess with .

}