GLSL 和 GLM 之间的矩阵数学不一致,或者是否存在 "bad" 视图矩阵
inconsistencies with matrix maths between GLSL and GLM, or is there such thing as a "bad" view matrix
所以,我发现了 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;
然后我希望屏幕变成 pinkish-red,或 (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:在我的引擎中发送倒置矩阵导致帧率大幅提升。一定要这样做。
任意 4x4 矩阵求逆不是一项快速且安全的任务
由于很多原因,比如GPU端的FPU精度较低,求逆过程中需要多次除法(这取决于计算方法),并不是所有的矩阵都有求逆等(我想这也是为什么GL 也没有这样的实现)...为了获得更好的图像,请参阅 并在其中查找 matrix_inv
函数计算的真正复杂程度(它使用行列式)。还有GEM(高斯消元法),但由于它的怪癖和需要对行进行排序而未被使用...
如果矩阵在每帧渲染中都是静态的(通常是这种情况),那么在 Vertex/Fragment/Geometry 着色器中每次 Vertex/Fragment 一次又一次地计算它是一种 GPU 能力的浪费(这就是速度的原因有提升)。
有人可能会反对 orthogonal homogenous matrix 反转只是转置矩阵,但是 GL/GLSL 怎么知道它处理这样的矩阵(检查也不是那么简单)无论如何在那种情况下你可以使用在 GLSL 中实现的 transpose
并且应该很快(它只是元素的重新排序)
所以,我发现了 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;
然后我希望屏幕变成 pinkish-red,或 (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:在我的引擎中发送倒置矩阵导致帧率大幅提升。一定要这样做。
任意 4x4 矩阵求逆不是一项快速且安全的任务
由于很多原因,比如GPU端的FPU精度较低,求逆过程中需要多次除法(这取决于计算方法),并不是所有的矩阵都有求逆等(我想这也是为什么GL 也没有这样的实现)...为了获得更好的图像,请参阅 matrix_inv
函数计算的真正复杂程度(它使用行列式)。还有GEM(高斯消元法),但由于它的怪癖和需要对行进行排序而未被使用...
如果矩阵在每帧渲染中都是静态的(通常是这种情况),那么在 Vertex/Fragment/Geometry 着色器中每次 Vertex/Fragment 一次又一次地计算它是一种 GPU 能力的浪费(这就是速度的原因有提升)。
有人可能会反对 orthogonal homogenous matrix 反转只是转置矩阵,但是 GL/GLSL 怎么知道它处理这样的矩阵(检查也不是那么简单)无论如何在那种情况下你可以使用在 GLSL 中实现的 transpose
并且应该很快(它只是元素的重新排序)