0

背景

我有一个用于开发汽车控制系统的程序,它使用 TCL 脚本语言和 OpenGL 的组合来额外渲染汽车在道路上行驶的行为。

我正在做的是实现对它的 OculusRift 支持,到目前为止已经设法解决了传感器部分,通过右键单击汽车正在行驶的窗口,我可以将它发送到 oculus rift。到目前为止,它看起来像这样:Youtube-Video

该程序的视觉部分已经有很多功能,包括调整 FOV、鱼眼镜头、相机方向、车内视图等选项。

在查看了软件文件夹后,我发现了一个 TCL 文件,其中包含以下几行:

// ... cut here

gl pushmatrix
gl loadidentity
gl translate $x $y $z
gl rotate $xrot 1 0 0
gl rotate $yrot 0 1 0
gl rotate $zrot 0 0 1
gl translate $offx $offy $offz
lassign [lrange [OGL get modelviewmatrix] 12 14] tx ty tz
gl popmatrix


dict set ::View($view) CameraMode FixedToBodyA
dict set ::View($view) xrot $xrot
dict set ::View($view) yrot $yrot
dict set ::View($view) zrot [expr $zrot + $zrot_eyeAngle]
dict set ::View($view) dist $conf(dist)
dict set ::View($view) VPtOffset_x $tx
dict set ::View($view) VPtOffset_y $ty
dict set ::View($view) VPtOffset_z $tz
dict set ::View($view) FieldOfView $conf(fov)
dict set ::View($view) AspectRatio $conf(AspectRatio)

return;
}

我没有找到任何处理渲染本身的行,但“gl”-命令足以让我明白这个 TCL 文件正在运行,直接附加到渲染过程。所以我用这个扩展了上面的内容:

// load a self written DLL that wraps OVR functionality (Github link bellow)

# now run tclovrGetData() from the loaded DLL to get sensor data
set data [tclovrGetData] 
// data = x y z xrot yrot zrot

gl pushmatrix
gl loadidentity
gl translate $x $y $z
gl rotate $xrot 1 0 0
...

Github 链接到 DLL

正如您在视频中看到的那样,它在显示器上看起来不错,但我们知道 Rift 的镜头会带来失真(这对我来说只是轻微的)和相当多的色差。

我的想法

我想要的是每 10-20 毫秒在视频中的屏幕上抓取“图像/纹理/帧”(我对术语仍然很陌生)并对其进行一些颜色过滤(我想看看我是否可以减少色差)。然后也许(为了使一切独立)用修改后的图像创建一个新窗口并将其发送到 Rift。基本上以所需的“格式”获取图像,以便能够对其执行计算。

我的想法是(因为我们附加到渲染过程)在上面的 TCL 文件中添加一些额外的行,这些行在我的 DLL 中调用可以执行以下操作的附加函数:

// Begin Oculus rendering loop
//1. get frame that is currently being rendered (in this process)
//2. copy this frame to memory
//3. perform some operations (color filtering) on this frame in memory
//4. send this frame to a new window

现在我的问题:

  • 这样的事情可能吗?
  • 有人能指出我正确的方向吗?即我可以使用的一些 gl 函数?
  • 也许 Direct3D 也可以?

我确实在 stackoverflow 上阅读了这篇文章,但未能理解:/

4

1 回答 1

0

这样的事情可能吗?

是的。但这可能不是最好的解决方案,因为将数据复制回 cpu 内存并在那里处理它很可能对实时应用程序来说不够快。

有人能指出我正确的方向吗?即我可以使用的一些 gl 函数?

如果您真的想这样做,您首先必须将图像渲染到帧缓冲区(或者更好地说是附加到帧缓冲区的纹理)。然后可以通过您在相关文章 (glGetTexImage) 中找到的函数将此纹理复制到 cpu 内存。还有其他选项,例如像素缓冲区,可能会更快一些(请参阅此处)

更快的解决方案

所有这些方法都要求您将数据从 gpu mem 复制到 cpu mem,在那里处理它并将所有内容复制回来。这需要 gpu 和 cpu 之间的大量同步,此外在 cpu 上处理图像会很慢。

根据您可以使用的可用 OpenGL 功能,有一些方法可以在 gpu 上执行整个图像处理。最简单的可能是使用着色器:

  1. 将场景渲染到帧缓冲区
  2. 绘制一个纹理四边形,其中来自 (1) 的纹理,在片段着色器中执行所有必要的操作。

在这种方法中,也不需要第二个窗口,因为后处理的四边形可以显示在第一个窗口中。有关 gpu 后处理的更多信息,您可以查看此处

于 2014-11-05T10:25:42.707 回答