我正在OpenGL中构建一个LIDAR模拟器。这意味着片段着色器返回光矢量的长度(距离)代替其中一个颜色通道,通过到远平面的距离进行归一化(因此它将在0和1之间)。换句话说,我用红色表示光强度,用蓝色表示距离;我将绿色设置为0. Alpha未使用,但我将其保持为1。
这是我的测试对象,恰好是一块石头:
然后我将像素数据写入文件并将其加载到点云可视化器(每像素一个点) - 基本上是默认值。当我这样做时,很明显我的所有点都位于不同的平面中,每个点位于不同的深度:
我尝试在R中绘制相同的数据。它最初没有显示默认直方图,因为平面的密度非常高。但当我将休息时间设置为60左右时,我明白了:
我已经尝试缩小近处和远处飞机之间的距离,以防它出现精确问题。首先我做了1-1000,现在我在1-500。它可能减少了飞机之间的距离,但我无法分辨,因为这意味着相机必须更靠近物体。
有什么我想念的吗?这是否与我禁用抗锯齿的事实有关? (抗锯齿导致更糟糕的周期性伪像,但在相机和对象之间反而出现。我禁用了线条平滑,多边形平滑和多重采样,并且处理了这个特定问题。)
这是执行距离计算的两个地方:
ec_pos
,即顶点相对于相机的位置。light_dir0
计算ec_pos
和相机位置,并用它来计算距离。是因为我在顶点着色器中计算ec_pos
吗?如何在片段着色器中计算ec_pos
呢?
答案 0 :(得分:3)
我可以想到几个可能的问题。
(1)你的深度精度。远平面对分辨率的影响很小;近平面是重要的。请参阅Learning to Love your Z-Buffer。
(2)根据您提供的内容,更可能的解释是像素数据的转换/保存。着色器输出浮点值,但这些值存储在帧缓冲区中,每个通道通常只有8位。对于颜色,这意味着你的浮点数将被映射到底层的8位(固定宽度,整数)表示,因此只有256个值。
如果你想输出像素数据作为它们的真实浮点数,你应该制作一个32位浮点RGBA FBO(例如GL_RGBA32F
或类似的东西)。这将存储实际浮动。然后,当您的数据来自GPU时,它将返回原始着色器值。
如果您没有方便的FBO实现,我想您可以在float
中对vec4
中的单个{{1}}进行一些乘法编码。