手动复制 GL 矩阵运算序列
我正在将玩具 GL ES 1.1 代码库移植到 GL ES 2.0。没有内置的模型视图矩阵操作,因此我尝试用操作替换 glScalef
、glTranslatef
、glRotatef
调用在 4x4“当前矩阵”上。
然而,我的矩阵数学有点粗略,并且乘法排序和行与列主要符号等都发生了一些事情,如果有人能够快速概述我应该放在这里的语义,我会很高兴。
例如,假设我从一个单位矩阵开始,然后(在 ES 1.1 代码中)按顺序执行:
glTranslate(A);
glRotate(B);
glTranslate(C);
...我需要对我的“当前矩阵”执行什么数学运算才能在最终的模型视图矩阵中复制此功能发送到着色器?我尝试保留一个矩阵,并为每个操作创建一个代表它的新矩阵,并将其与当前矩阵相乘。但结果是不正确的,而且我认为我对前/后乘法、-major 等有些东西不明白。
有人愿意在这里就这个理论说几句话吗?谢谢。 (我想在使其变得超级高效之前了解基础知识。)
(这个:在 OpenGL ES 2.0 中实现高效的固定函数管道? 问了一个类似的问题,但答案讨论了如何提高效率,并没有真正启发我数学等价性。)
I am porting a toy GL ES 1.1 codebase to GL ES 2.0. There are no built-in modelview matrix operations, so I'm attempting a drop in replacement of the glScalef
, glTranslatef
, glRotatef
calls with operations on a 4x4 "current matrix".
However, my matrix math is a little sketchy, and something's going on with the multiplication ordering and row vs column major notation, etc, and I'd love it if someone could quickly outline the semantics I should be dropping in here.
For instance, assuming I start with an identity matrix, and then (in ES 1.1 code) execute in order:
glTranslate(A);
glRotate(B);
glTranslate(C);
... what math do I need to be doing on my "current matrix" to replicate this functionality in the final modelview matrix I send to a shader? I've tried keeping a matrix, and for each operation, making a new matrix that represents it, and multiplying it into the current one. The result isn't correct though, and I think there's something I don't get about pre/post-multiply, -major, etc.
Anyone willing to say a few words on the theory here? Thanks. (I'd like to understand the basics before making it super-efficient.)
(This: Implement the Fixed function Pipeline efficent in OpenGL ES 2.0?
asks a similar question, but the answer talks about how to make it more efficient, and doesn't really enlighten me on the math equivalency.)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
基本上,您正在寻找 opengl 矩阵堆栈的替代品来进行转换。
假设您使用的是 c/c++,我建议查看 GLM 库: http://glm.g- truc.net/
它是一个仅包含头文件的库,易于使用,是 opengl es 2.0 之前的矩阵堆栈的完美替代品。它甚至提供了已弃用的 glu 函数的功能,例如 gluOrtho() 和 gluPerspective()。 Glm 的矩阵可以轻松传递到您的着色器,因为它们是在考虑着色器的情况下构思的。
您必须对代码进行一些更改;例如将您自己的顶点/矩阵定义转换为 glm::vec3 / glm::mat4。
下面是我如何构建传递给顶点着色器的 mvp 矩阵的示例:在本例中,actorInstance 类具有一些属性,例如定义为 glm::vec3 的位置(在世界中)和旋转。构造的模型、模型/视图和模型/视图/投影矩阵都是该类的属性:
显然,每个对象的 mvp 矩阵根据对象的位置和旋转每帧都会更新。 viewMatrix 和projectionMatrix 是从我的相机类传递下来的。
然后使用该矩阵来渲染网格:
希望这有帮助:)
编辑:实现矩阵堆栈的建议
这就是您的 glLoadIdentity()...
Basically, you're looking for a replacement of the opengl matrix stack to do your transformations.
Assuming you are using c/c++, I suggest having a look at the GLM library : http://glm.g-truc.net/
It's a header-only library, easy to use and the perfect replacement for the pre-opengl es 2.0 matrix stack. It even provides functionality for deprecated glu functions like gluOrtho() and gluPerspective(). Glm's matrices can easily be passed to your shader as they are conceived with shaders in mind.
You will have to make a few changes to your code; for instance converting your own vertex / matrix definitions to glm::vec3 / glm::mat4.
Here's an example of how I construct my mvp matrix that I pass to the vertex shader: in this case the actorInstance class has a few attributes like position (in the world) and rotation defined as glm::vec3's. The constructed model, model/view and model/view/projection matrices are all a property of the class:
Obviously the mvp matrix for each object gets updated every frame according to the object's position and rotation. The viewMatrix and projectionMatrix are passed down from my camera class.
That matrix is then used to render a mesh:
Hope this helps :)
EDIT : suggestions for implementing a matrix stack
And that is your glLoadIdentity()...
嗯,事情就是这样完成的。没什么特别的。
调用
glRotate
,glTranslate
和glScale
(以及< a href="http://www.opengl.org/sdk/docs/man/xhtml/glOrtho.xml" rel="nofollow">glOrtho
,glFrustum
,gluLookAt
和gluPerspective
,当然)相当简单构建,如链接中所示。您只需在当前矩阵
M
上右乘相应的变换矩阵T
:因为我们(或您想要复制的旧 OpenGL)想要之前调用的最后一个变换首先将绘图应用到对象上。
然后,无论您选择哪种,您还必须与矩阵的存储保持一致(行优先与列优先)。但由于您使用的是 OpenGL,列主存储将是一个好主意,因为它可以让您更轻松地将它们上传到 GLSL(不过,与转置标志无关),与矢量化 SIMD 指令(如 x86 的 SSE)配合使用效果更好而且与为 OpenGL 设计的其他库(出于同样的原因使用列主矩阵)配合得更好。您只需要与存储保持一致,并且不要在不同的函数调用中混淆它。
Well, that's exactly how it's done. Nothing fancy to it.
The respective matrices for calls to
glRotate
,glTranslate
andglScale
(and alsoglOrtho
,glFrustum
,gluLookAt
andgluPerspective
, of course) are rather easy to construct, as seen in the links.You just have to right-multiply the respective transformation matrix
T
on the current matrixM
:because we (or the old OpenGL you want to replicate) want the last transformation called before drawing to be applied on the object first.
Then you also have to be consistent with the storage of your matrix (row-major vs column-major), no matter for which you settle. But since you're using OpenGL, column-major storage would be a good idea, since it let's you upload them easier to GLSL (nothing against the transpose-flag, though), works better with vectorized SIMD-instructions (like x86's SSE) and moreover works better with other libraries designed for OpenGL (which use column-major matrices for the same reasons). You only have to be consistent with the storage and don't mix it up in different function calls.