将渲染的图像克隆到窗口/屏幕进行处理

时间:2014-11-05 09:53:27

标签: c++ opengl directx tcl oculus

背景

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

我正在做的是为它实施OculusRift支持,到目前为止已经设法解决了sesor部分,右键单击汽车行驶的窗口我可以将它发送到眼裂谷。到目前为止看起来像这样: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 link to the 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上发布了This帖子但未能理解:/

1 个答案:

答案 0 :(得分:0)

  

这样的事情会成为可能吗?

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

  

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

如果你真的想这样做,你首先要将图像渲染到帧缓冲区(或者更好地说是附加到帧缓冲区的纹理)。然后可以通过相关帖子(glGetTexImage)中找到的函数将此纹理复制到cpu内存中。还有其他选项,如像素缓冲区可能会更快(see here)

更快的解决方案

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

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

  1. 将场景渲染为帧缓冲区
  2. 绘制纹理四边形 纹理来自(1),在片段着色器中进行所有操作 必要的。
  3. 在该方法中,也不需要第二窗口,因为后处理的四边形可以在第一窗口中显示。有关gpu上的后期处理的更多信息,您可以查看here