OpenGL - gluPerspective/glFrustum - zNear & zFar 问题

标签 opengl perspectivecamera visual-glitch

我正在编写一个太空探索应用程序。我决定以光年为单位,并准确地模拟了恒星之间的距离。经过修补和大量艰巨的工作(主要是学习绳索),我让相机从穿越宇宙的星舰的角度正常工作。

最初我没有注意 gluPerspective () 的 zNear 参数,直到我研究行星物体。由于我的比例是以光年为单位,我很快意识到由于 zNear 为 1.0f,我将无法看到这些物体。经过实验,我得出了这些数字:

#define POV 45
#define zNear 0.0000001f
#define zFar 100000000.0f
gluPerspective (POV, WinWidth/WinHeight, zNear ,zFar);

这非常有效,因为我能够巡航我的太阳系(位置 0,0,0)并靠近看起来很好的光照和纹理映射的行星。然而,其他系统(不在位置 0,0,0 处)更难通过,因为物体以不寻常的方式远离相机。

然而,我注意到在宇宙中巡航时开始发生奇怪的视觉故障。我身后的物体会“环绕”并显示在前方,如果我沿 Y 方向摆动 180 度,它们也会出现在它们原来的位置。因此,当在空间中翘曲时,大多数恒星的视差是正确的,但有些会出现并沿相反的方向行进(至少可以说这是令人不安的)。

通过将 zNear 更改为 0.1f 可以立即纠正所有这些故障(但也不会解析太阳系物体)。所以我被困住了。我也尝试过使用 glFrustum,它产生完全相同的结果。

我使用以下内容来查看世界:
glTranslatef(pos_x, pos_y, pos_z);

使用相关的相机代码根据需要进行定位。即使禁用相机功能也不会改变任何东西。我什至尝试过 gluLookAt() 并且它再次产生相同的结果。

当使用极端 zNear/zFar 值时,gluPerspective() 是否有限制?我试图缩小范围,但无济于事。我什至通过放大所有内容并使用更大的 zNear 值将我的世界单位从光年更改为公里 - 没有。帮助!

最佳答案

问题是你想同时解决太多。你想在太阳系的尺度上观察事物,同时也有半银河系的尺度。那根本不可能。不是实时渲染器。

只有这么多的浮点精度可以解决。由于您的 zNear 非常接近,您基本上已经破坏了距离相机超过 0.0001 的任何事物的深度缓冲区。

您需要做的是根据距离绘制事物。近处物体(在太阳系的尺度内)使用一个透视矩阵绘制,使用一个深度范围(例如,0 到 0.8)。然后使用不同的透视矩阵和不同的深度范围(0.8 到 1)绘制更远的对象。这确实是您完成这项工作的唯一方法。

此外,您可能需要以 double 数学计算 CPU 上对象的矩阵,然后将它们转换回单精度以供 OpenGL 使用。

关于OpenGL - gluPerspective/glFrustum - zNear & zFar 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7338296/

相关文章:

c++ - 使用 glad with a QOpenGLWidget 加载 OpenGL 函数指针

3d - 在 Three.Js 中使物体完全适合相机视锥

emacs - 如何强制emacs重新着色

opencv - 在给定内在、外在和 Y=0 约束的情况下估计 2D 像素的深度

ios - 来自 View Controller 的带有提示的 UINavigationController 动画

iOS 7 Navigation Bar Jump on Flip Horizo​​ntal Segue

macos - 来自 OpenGL Core 配置文件的 CIContext (OpenGL 3.2)

java - OpenGL 纹理绘制在一起时出现在错误的位置

c++ - 关于 OpenGL 的问题和将 C 转换为 C++ 的过程

opencv - 基本矩阵、本质矩阵和单应矩阵之间有什么区别?