正确更新顶点缓冲区对象 [英] Properly update vertex buffer objects

查看:49
本文介绍了正确更新顶点缓冲区对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个用 winapi 编写的训练应用所以,我已经在那里初始化了 GL 并且我有基于节点的系统,可以用几个类来描述

I've got a training app written in winapi So, I've got GL initialized there and I've got node-based system, that can be described by couple of classes

class mesh
{
GLuint vbo_index; //this is for having unique vbo
float *vertex_array;
float *normal_array;
unsigned int vertex_count;

etc.. //all those mesh things.
....
}

class node
{
bool is_mesh; //the node may or may not represent a mesh
mesh * mesh_ptr; //if it does then this pointer is a valid address
}

我还有 2 个全局变量来记录可渲染网格..

I've also got 2 global variables for keeping record of renderable mesh..

mesh **mesh_table;
unsigned int mesh_count;

现在我正在试验 2 个对象.所以我创建了 2 个 mesh::cube 类型的节点,可自定义数量的 x y 和 z 段.我的应用程序的预期行为是让用户在 CUBE0、CUBE1 中的 2 个节点之间单击并显示它们的可自定义属性 - 段 x、段 y、段 z.用户调整两个对象的参数,它们在线框模式下彼此叠加渲染,因此我们可以实时看到它们的拓扑变化.

Right now I'm experimenting on 2 objects. So I create 2 nodes of type mesh::cube with customizable number of x y and z segments. Expected behaviour of my app is let the user click between 2 of the nodes CUBE0, CUBE1 and show their customizable attributes - segments x, segments y, segments z. The user tweaks both objecs' parameters and they are being rendered out on top of each other in wireframe mode, so we can see the changing in their topology in real time.

第一次创建节点时,如果节点类型为mesh,则生成mesh对象并将其mesh_ptr写入mesh_tablemesh_count 递增.之后,我的 opengl 窗口类为新网格创建了一个唯一的顶点缓冲区对象,并将其索引存储在 mesh_ptr.vbo_index

When the node is being created for the first time, if the node type is mesh, then the mesh object is generated and it's mesh_ptr is written into the mesh_table and mesh_count increments. After that my opengl window class creates a unique vertex buffer object for the new mesh and stores it's index in the mesh_ptr.vbo_index

void window_glview::add_mesh_to_GPU(mesh* mesh_data)
{
    glGenBuffers(1,&mesh_data->vbo_index);
    glBindBuffer(GL_ARRAY_BUFFER ,mesh_data->vbo_index);
    glBufferData(GL_ARRAY_BUFFER ,mesh_data->vertex_count*3*4,mesh_data->vertex_array,GL_DYNAMIC_DRAW);
    glVertexAttribPointer(5,3,GL_FLOAT,GL_FALSE,0,NULL);//set vertex attrib (0)
    glEnableVertexAttribArray(5);
}

之后,用户可以调整参数,每次参数值更改时,都会根据新的参数值重新评估对象的网格信息,同时仍然是相同的网格实例,之后 VBO 数据正在被由

After that the user is able to tweak the parameters and each time the parameter value changes the object's mesh information is being re-evaluated based on the new parameter values, while still being the same mesh instance, after that VBO data is being updated by

void window_glview::update_vbo(mesh *_mesh)
{
    glBindBuffer(GL_ARRAY_BUFFER,_mesh->vbo_vertex);
    glBufferData(GL_ARRAY_BUFFER,_mesh->vertex_count*12,_mesh->vertex_array,GL_DYNAMIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER,0);
}

整个场景由

for (unsigned short i=0;i<mesh_count;i++)
    draw_mesh(mesh_table[i],GL_QUADS,false);
SwapBuffers(hDC);

单个网格的函数是

bool window_glview::draw_mesh(mesh* mesh_data,unsigned int GL_DRAW_METHOD,bool indices)
{
    glUseProgram(id_program);
    glBindBuffer(GL_ARRAY_BUFFER,mesh_data->vbo_index);
    GLuint id_matrix_loc = glGetUniformLocation(id_program, "in_Matrix");
    glUniformMatrix4fv(id_matrix_loc,1,GL_TRUE,cam.matrixResult.get());
    GLuint id_color_loc=glGetUniformLocation(id_program,"uColor");

    glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
    glUniform3f(id_color_loc,mesh_color[0],mesh_color[1],mesh_color[2]);
    glDrawArrays(GL_DRAW_METHOD,0,mesh_data->vertex_count);
    glBindBuffer(GL_ARRAY_BUFFER,0);
    glUseProgram(0);
    return true;
}

问题是只有堆栈中的最后一个对象是这样绘制的,而另一个对象的点都在 0 0 0 中,因此在视口中它渲染了一个具有适当参数的立方体和一个立方体作为 DOT

The problem is that only the last object in stack is being drawn that way, and the other object's points are all in 0 0 0, so in the viewport it's rendered one cube with proper parameters and one cube just as a DOT

问题:我哪里出错了?

推荐答案

在你的画中 glBindBuffer(GL_ARRAY_BUFFER,mesh_data->vbo_index); 实际上没有做任何事情;有关顶点属性的信息根本不绑定到缓冲区.它在 glVertexAttribPointer(5,3,GL_FLOAT,GL_FALSE,0,NULL); 调用中设置,每次上传新网格时都会被覆盖.

in your draw glBindBuffer(GL_ARRAY_BUFFER,mesh_data->vbo_index); doesn't actually do anything; the information about the vertex attribute is not bound to the buffer at all. it is set in the glVertexAttribPointer(5,3,GL_FLOAT,GL_FALSE,0,NULL); call which gets overwritten each time a new mesh is uploaded.

要么创建并使用 VAO,要么将该调用从 add_mesh_to_GPU 移动到 draw_mesh:

either create and use a VAO or move that call from add_mesh_to_GPU to draw_mesh:

对于 VAO,你会这样做:

for the VAO you would do:

void window_glview::add_mesh_to_GPU(mesh* mesh_data)
{
    glGenVertexArrays(1, &mesh_data->vao_index);//new GLInt field
    glBindVertexArray(mesh_data->vao_index);
    glGenBuffers(1,&mesh_data->vbo_index);
    glBindBuffer(GL_ARRAY_BUFFER ,mesh_data->vbo_index);
    glBufferData(GL_ARRAY_BUFFER ,mesh_data->vertex_count*3*4,mesh_data->vertex_array,GL_DYNAMIC_DRAW);
    glVertexAttribPointer(5,3,GL_FLOAT,GL_FALSE,0,NULL);//set vertex attrib (0)
    glEnableVertexAttribArray(5);
    glBindVertexArray(0);
}

bool window_glview::draw_mesh(mesh* mesh_data,unsigned int GL_DRAW_METHOD,bool indices)
{
    glBindVertexArray(mesh_data->vao_index);
    glUseProgram(id_program);
    GLuint id_matrix_loc = glGetUniformLocation(id_program, "in_Matrix");
    glUniformMatrix4fv(id_matrix_loc,1,GL_TRUE,cam.matrixResult.get());
    GLuint id_color_loc=glGetUniformLocation(id_program,"uColor");

    glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
    glUniform3f(id_color_loc,mesh_color[0],mesh_color[1],mesh_color[2]);
    glDrawArrays(GL_DRAW_METHOD,0,mesh_data->vertex_count);
    glUseProgram(0);
    glBindVertexArray(0);
    return true;
}

这篇关于正确更新顶点缓冲区对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆