OpenGL OpenTK - 使用 Assimp 加载模型不一致

OpenGL OpenTK - Inconsistent Model loading with Assimp

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

像 Stanford Dragon 这样的单网格高多边形对象可以很好地加载。

这是我加载对象的方式

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);
}

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

如果你想解决这个问题,你必须将你的元素索引数据偏移你添加到当前网格之前的顶点数组的所有顶点的总和。

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

另请注意,按照您的方式组合网格,您也会忽略场景层次结构中的变换。