【问题标题】:OpenGL OpenTK - Inconsistent Model loading with AssimpOpenGL OpenTK - 使用 Assimp 加载不一致的模型
【发布时间】:2020-12-26 03:14:51
【问题描述】:

我正在尝试使用 Assimp 将多网格模型 (sponza) 导入到我的 OpenGL 渲染器中。 虽然我有一个工作场景的 obj 文件,但该文件似乎无法正确加载。为简单起见,我省略了所有纹理,即使 UV 仍然被加载,只是将颜色设置为蓝色。

像斯坦福龙这样的单网格高多边形计数对象加载得很好。

这就是我加载对象的方式

if (Path.ToLower().EndsWith(".x"))        
{
                _scene = _context.ImportFile(Path, PostProcessSteps.LimitBoneWeights
                    | PostProcessSteps.Triangulate
                    | PostProcessSteps.ValidateDataStructure
                    | PostProcessSteps.FlipWindingOrder
                    | PostProcessSteps.FixInFacingNormals
                );
}
        

else
{
        _scene = _context.ImportFile(Path, PostProcessSteps.LimitBoneWeights
            | PostProcessSteps.Triangulate
            | PostProcessSteps.ValidateDataStructure
        );
}

for (int i = 0; i < _scene.MeshCount; i++)
{
    for (int j = 0; j < _scene.Meshes[i].Vertices.Count; j++)
    {
        _verts.Add(_scene.Meshes[i].Vertices[j].X);
        _verts.Add(_scene.Meshes[i].Vertices[j].Y);
        _verts.Add(_scene.Meshes[i].Vertices[j].Z);


        _verts.Add(_scene.Meshes[i].HasTextureCoords(0) ? _scene.Meshes[i].TextureCoordinateChannels[0][j].X : 0f);
        _verts.Add(_scene.Meshes[i].HasTextureCoords(0) ? _scene.Meshes[i].TextureCoordinateChannels[0][j].Y : 0f);


        _verts.Add(_scene.Meshes[i].Normals[j].X * InvertNormal.X);
        _verts.Add(_scene.Meshes[i].Normals[j].Y * InvertNormal.Y);
        _verts.Add(_scene.Meshes[i].Normals[j].Z * InvertNormal.Z);

    }
}
float[] _data = _verts.ToArray();
GL.NamedBufferData(VBO, _verts.Count * sizeof(float), _data, BufferUsageHint.StaticDraw);

// Indecis
List<uint> _indecisList = new List<uint>();
for (int i = 0; i < _debugMeshes; i++)
{
    uint[] _tempArr = _scene.Meshes[i].GetUnsignedIndices();
    for (int j = 0; j < _tempArr.Length; j++)
    {
        _indecisList.Add(_tempArr[j]);
    }
}
uint[] _indecis = _indecisList.ToArray();
GL.NamedBufferData(IBO, _indecis.Length * sizeof(uint), _indecis, BufferUsageHint.StaticDraw);
GL.BindVertexArray(Renderer.Forward.OBJ4.VAO);        
{       
    _modelViewMatrix = Matrix4.CreateScale(0.01f) * Matrix4.CreateTranslation(30, 0, 10);
    GL.UniformMatrix4(21, false, ref _modelViewMatrix);

    ColorMode(1);
    GL.BindBuffer(BufferTarget.ElementArrayBuffer, Renderer.Forward.OBJ4.IBO);
    GL.DrawElements(PrimitiveType.Triangles, 786801, DrawElementsType.UnsignedInt, 0); _drawCalls++;
    ColorMode(0);
}

【问题讨论】:

    标签: c# opengl opentk assimp


    【解决方案1】:

    您的代码只是将所有网格组合成一个顶点数组 + 元素数组。但是,每个网格的元素数据是该特定网格中顶点数据的从 0 开始的索引。因此,第一个网格之后的所有内容都将使用引用错误顶点的元素数据。

    如果要解决此问题,则必须将元素索引数据偏移为在当前网格之前添加到顶点数组的网格的所有顶点的总和。

    但是,您的方法似乎值得怀疑。通常,对象被分割成不同的网格是有原因的,比如不同的纹理和材料属性。无论如何,您不能在一次绘制调用中绘制这些(至少不是天真地)。 GL 确实提供了glDrawElementsBaseVertex 之类的功能,适用于您希望从一个组合顶点数组中绘制不同子网格的场景,并在内部为您进行上述偏移。

    另请注意,通过以您的方式组合网格,您也忽略了场景层次结构的转换。

    【讨论】:

    • 好的,所以我现在可以使用glDrawElementsBaseVertex。 (谢谢!)这实际上是在更严肃的项目中完成的方式,还是有其他更好的方法?你谈到将场景分割成不同的网格,这是否意味着我必须为每个网格创建一个 VBO,甚至每帧都将当前网格数据加载到一个 VBO 中?
    • 嗯,这总是取决于。只要您不必添加、删除或更改单个对象,将所有网格放入同一个 VBO 是可行的。从简单开始,稍后再优化,直到您清楚瓶颈所在。
    猜你喜欢
    • 2016-02-01
    • 1970-01-01
    • 2021-07-17
    • 1970-01-01
    • 1970-01-01
    • 2018-07-23
    • 1970-01-01
    • 2018-05-11
    • 2013-08-19
    相关资源
    最近更新 更多