Opengl EBO / IBO无效

时间:2016-09-23 13:05:40

标签: c++ opengl indexing

我们似乎在使用OBJ模型的索引渲染EBO时遇到了麻烦。如下所示,我们首先通过迭代OBJ中的每个关键字来加载和分配顶点数据,并复制它们的值:

CBint                   current_material = -1;
std::vector <vec3>      temp_v;
std::vector <vec3>      temp_vn;
std::vector <vec2>      temp_vt;
for (unsigned int i = 0; i < line.size(); i++)
{
    switch ((line[i])[0])
    {
    case '#':
        continue;
    case '\0':
        continue;
    case 'm':
        char mtl_url[128];
        sscanf_s((&line[i])[0].c_str(), "mtllib %s", mtl_url, sizeof(mtl_url));
        _mtl_url = mtl_url;
        _materialised = true;
        break;
    case 'v':
        float x, y, z;
        if ((line[i])[1] == 'n')
        {
            sscanf_s((&line[i])[0].c_str(), "vn %f %f %f", &x, &y, &z);
            temp_vn.push_back(vec3(x, y, z));
        }
        if ((line[i])[1] == 't')
        {
            sscanf_s((&line[i])[0].c_str(), "vt %f %f", &x, &y);
            temp_vt.push_back(vec2(x, y));
        }
        else
        {
            sscanf_s((&line[i])[0].c_str(), "v %f %f %f", &x, &y, &z);
            temp_v.push_back(vec3(x, y, z));
        }
        break;
    case 'u':
        char material_element[128];
        sscanf_s((&line[i])[0].c_str(), "usemtl %s", &material_element, sizeof(material_element));

        if (_material_elements.size() > 1)
            _f[_f.size() - 1].mat_id = _material_elements.size();

        _material_elements.push_back(material_element);

        current_material++;
        break;
    case 'f':
        CBuint v_i[3];
        CBuint vn_i[3];
        CBuint vt_i[3];

        sscanf_s((&line[i])[0].c_str(), "f %d/%d/%d %d/%d/%d %d/%d/%d", &v_i[0], &vt_i[0], &vn_i[0], &v_i[1], &vt_i[1], &vn_i[1], &v_i[2], &vt_i[2], &vn_i[2]);
        _f.push_back(Face(v_i[0], vt_i[0], vn_i[0], v_i[1], vt_i[1], vn_i[1], v_i[2], vt_i[2], vn_i[2]));
        break;
    }

然后我们通过遍历每个面来优化索引,同时迭代每个属性,然后将这些属性分配给&#34; _indices&#34;容器:

for (CBuint i = 0; i < _f.size(); i++)
        {
            for (CBuint j = 0; j < 3; j++)
            {
                CBuint v =  _f[i].v[j];
                CBuint vt = _f[i].vt[j];
                CBuint vn = _f[i].vn[j];

                out_v.push_back(temp_v[v - 1]);
                out_vt.push_back(temp_vt[vt - 1]);
                out_vn.push_back(temp_vn[vn - 1]);

                _indices.push_back(v);
                _indices.push_back(vt);
                _indices.push_back(vn);
            }
        }

&#34; _f&#34;是&#34; Face&#34;的矢量列表的标识符,它是一个包含以下内容的简单结构:

CBuint v[3];
CBuint vt[3];
CBuint vn[3];
CBuint mat_id;

这是我们使用的另一个结构(&#34; Mesh&#34;),用于创建由OBJ中检测到的每种材料定义的多个子网格(&#34; usemtl default__0&#34;)。我们这样做,因此我们可以使用合法的材料在模型中渲染多个子网格。

Mesh(std::vector <CBuint>& i, std::vector <vec3>& v, std::vector <vec3>& vn, std::vector <vec2>& vt)
        {
            glGenBuffers(1, &vbo_v);
            glEnableVertexAttribArray(0);
            glBindBuffer(GL_ARRAY_BUFFER, vbo_v);
            glBufferData(GL_ARRAY_BUFFER, v.size() * sizeof(Math::vec3), &v[0], GL_STATIC_DRAW);
            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0);

            glGenBuffers(1, &vbo_vn);
            glEnableVertexAttribArray(1);
            glBindBuffer(GL_ARRAY_BUFFER, vbo_vn);
            glBufferData(GL_ARRAY_BUFFER, vn.size() * sizeof(vec3), &vn[0], GL_STATIC_DRAW);
            glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0);

            glGenBuffers(1, &vbo_vt);
            glEnableVertexAttribArray(2);
            glBindBuffer(GL_ARRAY_BUFFER, vbo_vt);
            glBufferData(GL_ARRAY_BUFFER, vt.size() * sizeof(vec2), &vt[0], GL_STATIC_DRAW);
            glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0);

            glGenBuffers(1, &ebo);
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
            glBufferData(GL_ELEMENT_ARRAY_BUFFER, i.size() * sizeof(CBuint), &i[0], GL_STATIC_DRAW);
        }

在优化索引数组(&#34; f x / x / x x / x / x x / x / x&#34;)之后,我们遍历每个材质元素并推送每个材质的网格:

CBuint next_element = 0;
glGenVertexArrays(1, &_vao);
glBindVertexArray(_vao);
if (_materials.size() > 1)
{
    for (CBuint i = 0; i < _f.size(); i++)
    {
        if (_f[i].mat_id == next_element)
        {
            _meshes.push_back(new Mesh(_indices, out_v, out_vn, out_vt));
            next_element++;
        }
    }
}
else
    _meshes.push_back(new Mesh(_indices, out_v, out_vn, out_vt));
glBindVertexArray(0);

然后最后我们调用glDrawElements而不是glDrawArrays来节省渲染时间的1/3:

glUniformMatrix4fv(_u_model, 1, GL_FALSE, _model);

_materials[0]->bind();

glBindVertexArray(_vao);
glDrawElements(GL_TRIANGLES, _indices.size(), GL_UNSIGNED_SHORT, 0);
glBindVertexArray(0); 

不幸的是,当使用glDrawElements时,我们得到以下结果:

http://s11.postimg.org/5qbsf2uzn/Untitled_1.jpg

然而,当使用glDrawArrays时,结果是完美的:

http://postimg.org/image/7wrq8icn3/

有谁能告诉我们我们做错了什么?此外,这是我们的顶点着色器位置代码:

layout(location = 0) in vec3 position;
layout(location = 1) in vec3 normal;
layout(location = 2) in vec2 texCoord;

如果有人有任何想法,我们会很感激。谢谢! DrStrange。

0 个答案:

没有答案