在较新的 OpenGL 中,没有矩阵堆栈。我正在开发一个简单的显示引擎,我将实现转换堆栈。
这里的常见策略是什么?我应该构建一个推送/弹出堆栈,并将它与代表我的模型的树一起使用吗?我想这是“旧”方法,在较新的 OpenGL 版本中已弃用。也许那时它不是最好的解决方案(由于某种原因它被删除了,我不知道)
在较新的 OpenGL 中,没有矩阵堆栈。我正在开发一个简单的显示引擎,我将实现转换堆栈。
这里的常见策略是什么?我应该构建一个推送/弹出堆栈,并将它与代表我的模型的树一起使用吗?我想这是“旧”方法,在较新的 OpenGL 版本中已弃用。也许那时它不是最好的解决方案(由于某种原因它被删除了,我不知道)
(由于某种原因被删除了)
它被删除了,因为在现代 3D 应用程序中,整个 OpenGL 矩阵操作功能是高度冗余的。无论如何,任何现代 3D 应用程序都需要处理矩阵,并且由于 OpenGL 不是一个合适的矩阵数学库,因此您无论如何都会使用诸如 Eigen oder GSL 之类的东西或自制的东西。
堆栈仍然是一种非常可行的结构。
我在这方面不是特别有经验,但我已经做了相当多的图形/游戏开发。我有更多的想法而不是答案。在我看来,glPushMatrix
and的glPopMatrix
东西已被弃用,因为许多开发人员希望完全控制转换,而不是 OpenGL 为他们处理这些。所以我的想法是它们不会被弃用,因为矩阵堆栈不是要走的路,而是因为 GL 开发人员应该自己处理矩阵,或者使用另一个库来为他们做这件事。
换句话说,矩阵堆栈可能仍然是要走的路,你只需要自己做,使用不推荐使用的功能,或者使用外部库。
固定管道功能已被弃用,因为本质上它是固定的。
为了支持新的技巧,通常需要新的 OpenGL 函数,而且很明显,持续支持请求的特性意味着增加 OpenGL API 的大小并使其越来越笨拙。
与此同时,硬件变得越来越复杂和强大,并且没有被 OpenGL 充分利用。因此,可编程流水线被构思出来。
对于 OpenGL3,Kronos 小组“弃用”了固定的管道功能。这引起了轩然大波,因为有如此多的代码和如此多的人才投资于完善的固定管道,所以他们部分地放弃了他们的决定,引入了“核心”和“兼容性”配置文件。内核配置文件包含新的可编程管道模型,兼容性配置文件包括内核以及大部分/所有固定功能,允许应用程序使用任一模型。
我们现在升级到 OpenGL 4.2,兼容性配置文件仍然存在,并且没有消失的迹象。
简而言之,弃用的原因不是因为旧模型不适合应用程序程序员;而是因为旧模型不适合应用程序员。相反,这对实施者来说是一个更重的负担。实际模型非常合理,许多使用可编程功能的应用程序/开发人员发现自己重新实现了固定功能的基本部分(glBegin、glEnd、矩阵堆栈、转换调用等)。
所以继续,实现你自己的矩阵堆栈。但是,如果您想出更好的主意,请与我们分享 :)
不确定它是否对您有用,但我为此实现了两件事。第一个是具有所有常用方法的简单矩阵堆栈类,第二个是基于堆栈的 RAII 结构,它允许我使用大括号来确定矩阵变化的范围,即在构造时它存储对矩阵堆栈的引用,在销毁时它恢复矩阵堆栈回到之前的状态。所以你可以写:
MatrixStack stack;
stack.push(rotate...)
stack.push(translate...)
{
MatrixScope(stack);
stack.push(rotate...)
}
... back to previous stack state.
And to add to this, it's just for convenience with certain kinds of transforms. Generally for models composed of a tree structure of meshes, all transformed relative to one another, I will combine the matrices from the root node down before I do anything with the model. So each mesh has a local transform and a global transform, the global transform being the actual transform for that mesh relative to the root node. So no need to use a matrix stack there.
It's a bit different if you want to animate a part of the mesh independently of the rest, so that's why I also store the local transform rather than throwing it away.