[CG] 沿 y 轴观察时无法正常渲染物体的原因

之前做 CG 课 lab2 的时候遇到了如标题所示的问题,当时并不知道原因。不久前又一次遇到该问题,这次我决定把它搞明白。

我使用 RenderDoc 对出错的部分进行了 profiling,发现传递给 GPU 的 uniform 变量 viewMatrix 里面有大量的 NaN 项,考虑到我的观察矩阵使用 glm::lookAt 函数产生,所以猜想问题与它有关。

当然,函数本身出错的概率,特别是对于 GLM 这种历史悠久的数学库而言,是极低的,但也无法排除这一可能,因此放在最后考虑吧。

目前唯一的线索只有 观察方向,我想,得先把观察方向与 lookAt 函数之间的关系搞明白,于是找到了 lookAt 的源码(下面贴的是 lookAtRH,适用于 OpenGL 的右手坐标系,相应的还有 lookAtLH,两个函数区别很小):

template <typename T, qualifier Q>
GLM_FUNC_QUALIFIER mat<4, 4, T, Q> lookAtRH(vec<3, T, Q> const &eye, vec<3, T, Q> const &center,
vec<3, T, Q> const &up)
{
vec<3, T, Q> const f(normalize(center - eye));
vec<3, T, Q> const s(normalize(cross(f, up)));
vec<3, T, Q> const u(cross(s, f));
mat<4, 4, T, Q> Result(1);
Result[0][0] = s.x;
Result[1][0] = s.y;
Result[2][0] = s.z;
Result[0][1] = u.x;
Result[1][1] = u.y;
Result[2][1] = u.z;
Result[0][2] = -f.x;
Result[1][2] = -f.y;
Result[2][2] = -f.z;
Result[3][0] = -dot(s, eye);
Result[3][1] = -dot(u, eye);
Result[3][2] = dot(f, eye);
return Result;
}

然后我发现了问题所在。因为观察方向沿 y 轴,也就是 center - eye 的结果与 y 轴平行(考虑精度损失,应当是 “接近平行”),而 up 向量传入的是 (0,1,0),导致 cross(f, up) 的结果是一个零向量,因而 u 也变成了零向量。最坏情况下,得到的 view matrix 的几乎所有元素都是 0 !

这应该就是无法正常显示的原因了。不过,还有一个地方没弄清楚:为什么实际运行得到的值是 NaN 而不是理论上的 0?等有空了再另写一篇文章讨论下这个奇怪的现象吧。

posted @   ZXPrism  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示