计算与加载 OpenGL 的法线

Posted

技术标签:

【中文标题】计算与加载 OpenGL 的法线【英文标题】:Calculating vs loading normals for OpenGL 【发布时间】:2014-02-01 20:28:21 【问题描述】:

嗯,你好。我正在尝试编写一个 OpenGL 游戏引擎/游戏(一个特定于我想要的游戏引擎:P)。我正在使用 .obj 模型,但它似乎效率很低。所有这些 atof 操作加上无法快速保留存储数据的向量大小,我想这会使整个事情稍微慢一些,所以我得出结论,我可能想尝试使用我自己的模型格式。我如何在不牺牲灵活性的情况下实现它,我想知道,以这种自定义二进制对象格式存储法线还是在加载时生成法线更好?它肯定会节省空间,但我还不确定它可能对性能产生的影响(如果有的话)。有什么建议吗?

基本总结:保存法线,还是在加载时生成它们?

谢谢你^.^

【问题讨论】:

不好的问题。保存法线,或在加载时或在 GPU 上计算它们 - 完全取决于您的需求、您加载的模型等。 这里的性能影响通常可以忽略不计 - 从硬盘驱动器加载文件需要更多时间(IO 成本很高),而不是通过交叉乘以向量对来计算法线 如今解析基于文本的模型并非闻所未闻。在 Doom/Quake 时代,二进制格式是存储/加载时间限制的必要条件。 《毁灭战士 3》实际上将其所有关卡都存储为解析后的文本,其中包括切线空间基向量之类的内容。大量浪费空间,但它避免了字节顺序问题并致力于浮点数的二进制表示(这使得像 0.1 这样看似简单的东西无法表示)。实际上,您可以将 0.1 精确地存储为文本,但无论您向其扔多少位,您都无法在二进制 FP 中做到这一点。 对格式错误的问题道歉...在加载时计算它们!我想这将是计算它们的最佳选择。并且有趣的是二进制表示的局限性......我会想象到最后,因为它们无论如何都会被转换为二进制,所以可能没有太大区别。 最好的选择是使用比 OBJ 更好的格式(几乎所有其他格式都更好)并在内容管道中使用 Assimp 将数据(包括法线)转换为可用的内存中二进制形式.然后将该二进制数据转储到磁盘并在需要时重新加载。当一个比你能写的任何东西都好得多的加载器已经免费存在时,无需浪费时间编写加载器。 【参考方案1】:

过早的优化。您将只加载一次模型。而且atof一开始并不是一个很复杂的操作(它基本上只是一个char const *c = instring; while(isdigit(*c)) v *= 10; v += *c - '0'; c++;

的循环

我想知道,最好以这种自定义二进制对象格式存储法线,还是在加载时生成它们?

加载它们。法线是您希望建模艺术家能够微调的东西。

【讨论】:

嗯,请问,艺术家微调法线的可能优势是什么?我无法准确猜测,除非我不完全理解它们是如何工作的,这很可能。我个人从未调整过它们,除非在我不知情的情况下间接调整过。而且我知道它们只会加载一次,但主要是为了节省一些空间:P 我对多边形数量并不太保守,如果生成法线不会有任何影响,那么我会欢迎压缩。 一个优点是您可以同时拥有硬边和软边,另一个优点是在相同的顶点/三角形数量下可以获得更高的细节层次。在法线上节省空间(或加载时间)是荒谬的。它们占用的空间量可以忽略不计,与初始访问时间相比,对加载时间的影响为零。如果您担心法线的内存消耗,请不要使用任何纹理! 只是我不知道加载它们的好处! :P 嗯,我想我确实应该保留它们。我承认提高质量足以保证使用一些额外的浮点值。谢谢^.^ 加载法线为您提供最高的灵活性。简单易行。

以上是关于计算与加载 OpenGL 的法线的主要内容,如果未能解决你的问题,请参考以下文章

计算顶点法线OpenGL

重新计算规则网格表面的法线 (C++/OpenGL)

通过 OpenGL Assimp 加载的对象有时会反转法线

OpenGL在给定点列表的情况下计算正确的法线

如何在OpenGL中计算三角形网格的顶点法线?

OpenGL 计算三角形法线 C++