GLSL 和 GLM 之间的矩阵数学不一致,或者是不是存在“坏”视图矩阵之类的东西

Posted

技术标签:

【中文标题】GLSL 和 GLM 之间的矩阵数学不一致,或者是不是存在“坏”视图矩阵之类的东西【英文标题】:inconsistencies with matrix maths between GLSL and GLM, or is there such thing as a "bad" view matrixGLSL 和 GLM 之间的矩阵数学不一致,或者是否存在“坏”视图矩阵之类的东西 【发布时间】:2015-04-11 10:35:29 【问题描述】:

所以,我在 GLSL 和 GLM 之间遇到了一些奇怪的问题。

如果我生成以下视图矩阵(C++):

vec3 pos(4, 1, 1);
vec3 dir(1, 0, 0);
mat4 viewMat = glm::lookAt(pos, pos+dir, vec3(0,0,1));

然后,在 glsl 中,执行:

fragColour.rgb = vec3(inverse(viewMat) * vec4(0,0,0,1)) / 4.f;

然后我希望屏幕变成粉红色,或 (1.0,0.25,0.25)。相反,我变黑了。

但是,如果我在 GLM 中这样做:

vec3 colour = vec3(glm::inverse(viewMat) * vec4(0,0,0,1)) / 4.f;
cout << glm::to_string(colour) << endl;

我得到了 (1.0,0.25,0.25) 的预期结果。

现在,如果我将 viewMat 改为 (C++):

vec3 pos(4, 1, 1);
vec3 dir(1, 0.000001, 0);
mat4 viewMat = glm::lookAt(pos, pos+dir, vec3(0,0,1));

然后砰!我在 GLSL 和 GLM 中都得到 (1.0,0.25,0.25)。

这对我来说毫无意义。为什么这样做?这个视图矩阵在 GLSL 中的其他任何地方都可以正常工作——我只是无法反转它。每当 dirY == 0.f. 时就会发生这种情况。

另外,请对问题标题提出改进建议,我不确定应该是什么。

编辑:另外,它似乎与lookAt 的向上向量(无论如何我设置为Z)没有任何关系。即使我设置为(0,1,0),也会发生同样的事情。一切都转向一边,但我仍然无法反转 GLSL 中的视图矩阵。

编辑:好的,所以在 derhass 的建议下,我已经尝试发送倒置的视图矩阵。巴姆,完美的工作。因此,似乎我的 GL 实现确实无法反转该矩阵。这很容易成为我遇到过的最奇怪的 GL 错误。不过,对于为什么在着色器中反转矩阵是一个坏主意的某种解释,我们将不胜感激。 EditAgain:在我的引擎中发送反转矩阵导致了巨大的帧率提升。一定要这样做。

【问题讨论】:

好吧,据我所知,这个问题对 glm 完全没有影响。看起来这只是 GLSL 中的反转问题。他们设置你的矩阵的方式,它应该是完全可逆的,并且数字问题不应该是一个问题。这可能只是您的 GL 实现的问题。另请注意,在大多数情况下,在着色器中反转矩阵是一个坏主意,但它当然应该工作。如果可能,我建议使用其他一些 GL 实现对此进行测试。 @derhass Ahhh,我没有考虑过发送已经反转的矩阵。我会试试的。我也会尝试看看问题是否也发生在其他地方。我目前正在使用一个相当旧的 nvidia 驱动程序(Ubuntu 14.04 的存储库中的那个)。 这是我第一次了解到 GLSL 现在有一个反函数。这绝对不是对 GPU 友好的操作。始终注意操作的层次结构:每个绘制、每个顶点、每个片段。始终将物品移到尽可能低的位置。通过对每个顶点进行逆运算,您只是遇到了一个非常不可能的代码路径。另请注意,通常不需要通用逆。大多数模型视图矩阵应该是“正交的”。其中逆向与转置相同。 嘿...可能不是说我是按片段做的好时机:P 【参考方案1】:

任意 4x4 矩阵求逆不是一项快速且安全的任务

由于许多原因,例如 GPU 端的 FPU 精度较低以及在求逆过程中需要许多除法(这取决于计算方法),并且并非所有矩阵都有逆矩阵等(我认为这也是 GL 具有也没有这样的实现)...有关此方面的更好图像,请参阅Understanding 4x4 homogenous transform matrices 并查找matrix_inv 函数,那里的计算实际上有多复杂(它使用行列式)。还有 GEM(高斯消除法),但由于其怪癖和需要对行进行排序而没有使用...

如果矩阵在每帧渲染中都是静态的,通常情况下,在每个顶点/片段中一次又一次地在顶点/片段/几何着色器中计算它是浪费 GPU 能力(这就是速度提升存在的原因) .

有人可能会反对orthogonal homogenous matrix inversion 只是转置矩阵,但是 GL/GLSL 如何知道它处理这样的矩阵(检查也不是那么简单)在这种情况下你可以使用transpose在 GLSL 中实现并且应该很快(它只是重新排序元素)

【讨论】:

我希望这就是答案。矩阵求逆通常会导致数值不稳定,如果可以的话,我几乎总是会避免矩阵求逆。 @DietrichEpp 我也是,但在图形中,尤其是相机效果,它不能那么容易地避免:( 这是一个常见的误解,通常很容易避免。您可以生成法线矩阵并进行反向投影等,而无需计算一般矩阵的逆矩阵。

以上是关于GLSL 和 GLM 之间的矩阵数学不一致,或者是不是存在“坏”视图矩阵之类的东西的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL/GLSL/GLM - Skybox 像第三人称一样旋转

glm中矩阵值的顺序不正确?

GLSL 中的正常旋转

用于 OpenGL 的轻量级数学库

GLM的向量矩阵乘法行为?

GLSL:如何使用投影矩阵计算光线方向?