用于自转和不同屏幕尺寸的矩阵乘法

时间:2013-01-11 10:49:51

标签: opengl opengl-es opengl-es-2.0

无论您使用固定或可编程着色器管道,常见的顶点管道都包含此矩阵乘法(自定义编码或幕后):

Projection * Modelview * Position

很多教程都会注意对象的旋转等项目应该进入Modelview矩阵。

我创建了一个基于度数的标准旋转矩阵函数,然后将度数参数添加到90的正确倍数,以说明屏幕的自动旋转方向。的工作原理。

对于不同的屏幕尺寸(屏幕的不同像素宽度和高度),我还可以在其中考虑Scale乘数,以便Modelview矩阵可能包含很多这些。

但是我所确定的是一个更冗长的矩阵数学,因为我对这些东西不熟悉,我会很感激这是否很聪明的反馈。

除了缩放和旋转等对象操作外,我还为屏幕缩放和屏幕方向添加了独立的矩阵。我最终得到了这个:

Projection * ScreenRotation * ScreenScale * Translate * Rotate * Scale * Position

其中一些是可互换的顺序,例如我可以切换RotateScale

这为我提供了更精细的控制和代码隔离,因此我可以专注于对象的旋转,而无需同时考虑屏幕的方向,例如。

这是适当组织矩阵数学的常用或可接受的策略吗?它似乎工作得很好,但这种冗长有任何陷阱吗?

1 个答案:

答案 0 :(得分:3)

这种冗长的主要问题是,如果在GPU上执行,它会浪费宝贵的计算周期。每个矩阵都将作为一个整体提供,从而迫使GPU为每个顶点计算,而在整个着色器中它实际上是一个常量。关于矩阵的好处是,单个矩阵可以保存整个变换链,并且可以通过单个向量矩阵乘法完成变换。

典型的节

Projection · Modelview · Position

使用两个矩阵来自,通常需要Modelview · Position的中间结果进行某些计算。从理论上讲,你可以将整个事情收缩到

ProjectionViewModel · Position

现在你提出这个矩阵表达式

  

投影* ScreenRotation * ScreenScale *翻译*旋转*缩放*位置

呃......这整个事情是不灵活的顶峰。你想要灵活性吗?这个东西是刚性,如果你想在已经旋转的几何体上应用一些非均匀缩放,那该怎么办呢。矩阵数学中的操作顺序很重要,你不能自由地混合它们。假设您正在绘制球体

Rotate(45, 0, 0, 1) · Scale(1,2,1) · SphereVertex

看起来与

完全不同
Scale(1,2,1) · Rotate(45, 0, 0, 1) · SphereVertex

屏幕比例和旋转可以并且应该直接应用于Projection矩阵,不需要额外的矩阵。关键的理解是,您可以将每个线性变换链组合成单个矩阵。出于实际原因,您希望将屏幕像素方面缩放应用为链中的最后一步,并将屏幕旋转应用为链中的倒数第二步。

因此,您可以构建投影矩阵,而不是在着色器中,而是在显示例程框架设置代码中。假设您正在使用我的linmath.h,它将如下所示

mat4x4 projection;
mat4x4_set_identity(projection);
mat4x4_mul_scale_aniso(projection, …);
mat4x4_mul_rotate_Z(projection, …);
if(using_perspective)
    mat4x4_mul_frustum(projection, …);
else
    mat4x4_mul_ortho(projection, …);

结果矩阵projection然后设置为投影矩阵均匀。