OpenGL - 索引缓冲区对象(IBO)渲染不正确

时间:2016-10-04 20:32:54

标签: c++ opengl indexing rendering vbo

我最近编写了一个与C ++集成的.obj模型加载器。到目前为止,我已经成功地设法调整文件中的数据,获取其四种属性类型(v,vn,vt和f),以便为IBO结构设置顶点和索引。问题是,顶点位置似乎不止一次交叉,导致一组顶点散布在模型的形式内。

(示范显示在下面的图片链接中。)

Click me to view the current result!

我已经多次彻底调试,仍然无法确定这个问题。 请记住我将每个法线和纹理坐标值设置为零(暂时)以进行测试。此外,剔除被禁用,因此根本不能成为正常的问题。

无论如何,到达代码 - 我首先有一个Vertex结构存储位置,法线和tex-coords的所有属性数据:

struct  Vertex
    {
        CBfloat v1, v2, v3;
        CBfloat vn1, vn2, vn3;
        CBfloat vt1, vt2;

        Vertex(vec3 _position, vec3 _normal, vec2 _texCoord)
        {
            v1 = _position[0];
            v2 = _position[1];
            v3 = _position[2];
            vn1 = _normal[0];
            vn2 = _normal[1];
            vn3 = _normal[2];
            vt1 = _texCoord[0];
            vt2 = _texCoord[1];
        }
    };

我使用这些容器来收集呈现IBO所需的所有数据:

   std::vector <Vertex>     _vertices;
   std::vector <CBuint>     _indices;

然后,在我的loadOBJ函数中,我从.obj中检索数据并将其分配给包含顶点位置,顶点法线和顶点纹理坐标的四个临时矢量列表:

        // Assign vertex data
        std::vector <vec3>  _v;
        std::vector <vec3>  _vn;
        std::vector <vec2>  _vt;
        std::vector <Face>  _f;
        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);
                    _vn.push_back(vec3(x, y, z));
                }
                if ((line[i])[1] == 't')
                {
                    sscanf_s((&line[i])[0].c_str(), "vt %f %f", &x, &y);
                    _vt.push_back(vec2(x, y));
                }
                else if ((line[i])[1] == ' ')
                {
                    sscanf_s((&line[i])[0].c_str(), "v %f %f %f", &x, &y, &z);
                    _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));

                // Assign new material to element
                if (_material_element.size() > 1)
                    _f[_f.size() - 1].mat_id = _material_element.size();

                _material_element.push_back(material_element);
                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]);

                // Faces (IGNORE!)
                _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]));

                // Indices
                _indices.push_back(v_i[0] - 1);
                _indices.push_back(vt_i[0] - 1);
                _indices.push_back(vn_i[0] - 1);

                _indices.push_back(v_i[1] - 1);
                _indices.push_back(vt_i[1] - 1);
                _indices.push_back(vn_i[1] - 1);

                _indices.push_back(v_i[2] - 1);
                _indices.push_back(vt_i[2] - 1);
                _indices.push_back(vn_i[2] - 1);

                break;
            }
        }

接下来,我根据顶点位置的数量分配顶点(用于测试目的的临时方法):

        // Optimise vertices (TEMP!!)
        for (CBuint i = 0; i < _v.size(); i++)
        {
            if (i <= _vn.size() - 1 && i <= _vt.size() - 1)
                _vertices.push_back(Vertex(_v[i], _vn[i], _vt[i]));
            else if (i > _vn.size() - 1 && i <= _vt.size() - 1)
                _vertices.push_back(Vertex(_v[i], vec3(0.0f, 0.0f, 0.0f), _vt[i]));
            else
                _vertices.push_back(Vertex(_v[i], vec3(0.0f, 0.0f, 0.0f), vec2(0.0f, 0.0f)));
        }

最后,缓冲区。我首先定义&#34; BUFFER_OFFSET&#34;为:

#define BUFFER_OFFSET(i) ((char *)NULL + (i))

然后按如下方式设置其他所有内容:

            glGenVertexArrays(1, &_vao);
            glBindVertexArray(_vao);

            // Generate
            glGenBuffers(1, &vbo);
            glGenBuffers(1, &ebo);

            // Bind
            glBindBuffer(GL_ARRAY_BUFFER, vbo);
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);

            // Buffer
            glBufferData(GL_ARRAY_BUFFER, _vertices.size() * sizeof(Vertex), &_vertices[0], GL_STATIC_DRAW);
            glBufferData(GL_ELEMENT_ARRAY_BUFFER, _indices.size() * sizeof(CBuint), &_indices[0], GL_STATIC_DRAW);

            // Set attribs
            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(0));
            glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(sizeof(CBfloat) * 3));
            glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(sizeof(CBfloat) * 6));

            // Enable attribs
            glEnableVertexAttribArray(0);
            glEnableVertexAttribArray(1);
            glEnableVertexAttribArray(2);

            // Clean up
            glBindVertexArray(0);

然后当然导致渲染阶段:

virtual void render()
    {
        glUniformMatrix4fv(_u_model, 1, GL_FALSE, _model);

        _materials[0]->bind();

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

为了好奇,我正在测试的cube.obj文件包含以下来源:

v  -0.5000 -0.5000 0.5000
v  -0.5000 -0.5000 -0.5000
v  0.5000 -0.5000 -0.5000
v  0.5000 -0.5000 0.5000
v  -0.5000 0.5000 0.5000
v  0.5000 0.5000 0.5000
v  0.5000 0.5000 -0.5000
v  -0.5000 0.5000 -0.5000
# 8 vertices

vn 0.0000 -1.0000 -0.0000
vn 0.0000 1.0000 -0.0000
vn 0.0000 0.0000 1.0000
vn 1.0000 0.0000 -0.0000
vn 0.0000 0.0000 -1.0000
vn -1.0000 0.0000 -0.0000
# 6 vertex normals

vt 1.0000 0.0000 0.0000
vt 1.0000 1.0000 0.0000
vt 0.0000 1.0000 0.0000
vt 0.0000 0.0000 0.0000
# 4 texture coords

g Box001
s 2
f 1/1/1 2/2/1 3/3/1 
f 3/3/1 4/4/1 1/1/1 
s 4
f 5/4/2 6/1/2 7/2/2 
f 7/2/2 8/3/2 5/4/2 
s 8
f 1/4/3 4/1/3 6/2/3 
f 6/2/3 5/3/3 1/4/3 
s 16
f 4/4/4 3/1/4 7/2/4 
f 7/2/4 6/3/4 4/4/4 
s 32
f 3/4/5 2/1/5 8/2/5 
f 8/2/5 7/3/5 3/4/5 
s 64
f 2/4/6 1/1/6 5/2/6 
f 5/2/6 8/3/6 2/4/6 
# 12 faces

如果有人对导致此顶点/索引渲染错误的内容有任何想法,我非常感谢您的启发。

谢谢你, 威廉。

0 个答案:

没有答案