【问题标题】:How do I program a stereo-capable graphics card to display stereo images?如何对具有立体功能的图形卡进行编程以显示立体图像?
【发布时间】:2011-02-08 04:09:56
【问题描述】:

我想编写自己的立体图像查看器,因为我需要的某些功能在我的 NVidia/EVGA GTX 580 附带的功能中缺少。

我不知道如何对卡进行编程以进入“快门”模式,其中每隔一帧(120 HZ)左右交替。

我查看了 OpenGL、Direct3D 和 XNA API,以及来自 NVIDIA 的信息,但不知道如何开始。如何设置单独的左右图像,如何告诉屏幕显示它,以及如何告诉驱动程序激活快门发射器?

(另一个令人不安的事情是,每当我使用捆绑软件在快门眼镜模式下查看立体图像和视频时,它都是全屏的,并且在进入该模式时屏幕会闪烁——即使我在 2D 模式下以 120Hz 的频率运行屏幕。有没有办法在窗口中显示 3D 表面,而不会破坏支持 3D 的 NVidia“游戏玩家”卡(570、580)上的屏幕其余部分?

【问题讨论】:

    标签: stereoscopy


    【解决方案1】:

    我对此有点晚了,但我只是使用 GTX 580 和 OpenGL 让立体 3D 工作。无需 Quadro 卡或 DirectX。

    我有 nVidia 3D Vision 驱动程序和 IR 发射器,只需在 nVidia 控制面板中将发射器设置为“始终开启”即可。

    在我的游戏引擎中,我切换到了 120Hz 的全屏模式,并以轻微的平截头体偏移渲染了两次场景(根据 nVidia 自己的文档 PDF 关于手动实现“2010_GTC2010.pdf”)。

    不需要四边形缓冲区或任何其他技巧,效果很好。另外,我可以控制所有设置,例如收敛等。

    【讨论】:

      【解决方案2】:

      对于具有 GEForce 系列的 NVidia 3Dvision,您需要写入两倍于显示器宽度的全屏 directX 表面,左侧图像在左侧,右侧图像在右侧 (duh)。
      然后你需要在图像的左下角写入一个魔法值,NVision驱动程序拾取并打开眼镜,你不需要nvapi.dll

      借助 Nvidia pro 眼镜和 Quadra 卡,您可以使用常规的 OpenGL 立体 API。

      ps.我确实找到了一些示例代码,可以在普通窗口中做到这一点。
      编辑 - 这是一个低级 USB 代码与我永远无法构建的 xmitter 对话,我认为它最终变成了这个 http://sourceforge.net/projects/libnvstusb/

      这里是一些使用 NVision 眼镜进行全屏显示的示例代码。
      我不是 DirectX 专家,因此其中一些可能不是最佳的。
      我的应用也是基于Qt的,代码中可能还有一些Qt位

      -----------------------------------------------------------------
          // header
          void create3D();
          void set3D();
          IDirect3D9 *_d3d;
          IDirect3DDevice9 *_d3ddev;
          QSize _size; // full screen size 
      
          IDirect3DSurface9 *_imageBuf; //Source stereo image
          IDirect3DSurface9 *_backBuf;    
      
      
      --------------------------------------------------------
         // the code     
      #include <windows.h>
      #include <windowsx.h>
      #include <d3d9.h>
      #include <d3dx9.h>
      #include <strsafe.h>
      
      #pragma comment (lib, "d3d9.lib")
      
      #define NVSTEREO_IMAGE_SIGNATURE 0x4433564e //NV3D
      
      typedef struct _Nv_Stereo_Image_Header
      {
      unsigned int dwSignature;
      unsigned int dwWidth;
      unsigned int dwHeight;
      unsigned int dwBPP;
      unsigned int dwFlags;
      } NVSTEREOIMAGEHEADER, *LPNVSTEREOIMAGEHEADER;
      
      
      // ORedflags in the dwFlagsfielsof the _Nv_Stereo_Image_Headerstructure above
      #define SIH_SWAP_EYES 0x00000001
      #define SIH_SCALE_TO_FIT 0x00000002
      
      // call at start to set things up
      void DisplayWidget::create3D()
      {
              _size = QSize(1680,1050); //resolution of my Samsung 2233z
      
              _d3d = Direct3DCreate9(D3D_SDK_VERSION);    // create the Direct3D interface
      
              D3DPRESENT_PARAMETERS d3dpp;    // create a struct to hold various device information
      
              ZeroMemory(&d3dpp, sizeof(d3dpp));    // clear out the struct for use
              d3dpp.Windowed = FALSE;    // program fullscreen
              d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;    // discard old frames
              d3dpp.hDeviceWindow = winId();    // set the window to be used by Direct3D
              d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;  // set the back buffer format to 32 bit // or D3DFMT_R8G8B8
              d3dpp.BackBufferWidth = _size.width();
              d3dpp.BackBufferHeight = _size.height();
              d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
              d3dpp.BackBufferCount = 1;
      
              // create a device class using this information and information from the d3dpp stuct
              _d3d->CreateDevice(D3DADAPTER_DEFAULT,
                                D3DDEVTYPE_HAL,
                                winId(),
                                D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                &d3dpp,
                                &_d3ddev);
      
      
          //3D VISION uses a single surface 2x images wide and image high
          // create the surface 
          _d3ddev->CreateOffscreenPlainSurface(_size.width()*2, _size.height(), D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &_imageBuf, NULL);
      
          set3D();
      
      }
      
      // call to put 3d signature in image
      void DisplayWidget::set3D()
      {
      
          // Lock the stereo image
          D3DLOCKED_RECT lock;
          _imageBuf->LockRect(&lock,NULL,0);
      
          // write stereo signature in the last raw of the stereo image
          LPNVSTEREOIMAGEHEADER pSIH = (LPNVSTEREOIMAGEHEADER)(((unsigned char *) lock.pBits) + (lock.Pitch * (_size.height()-1)));
      
          // Update the signature header values
          pSIH->dwSignature = NVSTEREO_IMAGE_SIGNATURE;
          pSIH->dwBPP = 32;
          //pSIH->dwFlags = SIH_SWAP_EYES; // Src image has left on left and right on right, thats why this flag is not needed.
          pSIH->dwFlags = SIH_SCALE_TO_FIT;
          pSIH->dwWidth = _size.width() *2;
          pSIH->dwHeight = _size.height();
      
          // Unlock surface
          _imageBuf->UnlockRect();
      
      }
      
      // call in display loop
      void DisplayWidget::paintEvent()
      {
          // clear the window to a deep blue
          //_d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 40, 100), 1.0f, 0);
      
          _d3ddev->BeginScene();    // begins the 3D scene
      
          // do 3D rendering on the back buffer here
          RECT destRect;
          destRect.left = 0;
          destRect.top = 0;
          destRect.bottom = _size.height();
          destRect.right = _size.width();
      
          // Get the Backbuffer then Stretch the Surface on it.
          _d3ddev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &_backBuf);
          _d3ddev->StretchRect(_imageBuf, NULL, _backBuf, &destRect, D3DTEXF_NONE); 
          _backBuf->Release();
      
          _d3ddev->EndScene();    // ends the 3D scene
      
          _d3ddev->Present(NULL, NULL, NULL, NULL);    // displays the created frame
      }
      
      // my images come from a camera
      // _left and _right are QImages but it should be obvious what the functions do  
      void DisplayWidget::getImages()
      {
                      RECT srcRect;
                      srcRect.left = 0;
                      srcRect.top = 0;
                      srcRect.bottom = _size.height();
                      srcRect.right = _size.width();
      
                      RECT destRect;              
                      destRect.top = 0;
                      destRect.bottom = _size.height();
      
                      if ( isOdd() ) {                    
                          destRect.left = _size.width();
                          destRect.right = _size.width()*2;
                          // get camera data for _left here, code not shown               
                          D3DXLoadSurfaceFromMemory(_imageBuf, NULL, &destRect,_right.bits(),D3DFMT_A8R8G8B8,_right.bytesPerLine(),NULL,&srcRect,D3DX_DEFAULT,0);         
                      } else {
                          destRect.left = 0;
                          destRect.right = _size.width();
                          // get camera data for _right here, code not shown          
                          D3DXLoadSurfaceFromMemory(_imageBuf, NULL, &destRect,_left.bits(),D3DFMT_A8R8G8B8,_left.bytesPerLine(),NULL,&srcRect,D3DX_DEFAULT,0);           
                      }
      
      
                      set3D();    // add NVidia signature
      
      }
      
      DisplayWidget::~DisplayWidget()
      {
          _d3ddev->Release();    // close and release the 3D device
          _d3d->Release();    // close and release Direct3D
      
      }
      

      【讨论】:

      • 谢谢! NVidia 真的没有说清楚。对于 Pro 卡(Quadra),我认为它可能在 OpenGL 中“正常工作”,但对于消费卡,有一些古怪的技巧。我刚刚看到一些关于 NVAPI 的页面,可以调用它来将卡插入各种模式。看起来消费卡只能在“全屏”模式下播放立体声,不像专业卡,所以我很想看看你的示例代码。
      • AFAIK 它仅在全屏模式下(正确)工作。 NVAPI 文档没用,网上很多人一直在努力解决这个问题。即使对业内人士来说,Nvidia 也完全没有帮助。
      • 我相信这个帖子里的人已经明白了:mtbs3d.com/phpBB/viewtopic.php?f=105&t=5072&start=15 我希望消费卡/游戏卡能得到比这更好的支持;我的申请很简单;我有一个小型 3D 照片共享网站 (3dpho.to),我想为一些流行的 3D 查看选项提供一些可下载的查看器。
      • 谢谢,Martin,但我需要自己编写....我希望它能够自动从我们的 3D 网站加载图像
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-11-24
      • 1970-01-01
      • 1970-01-01
      • 2021-03-24
      • 2011-07-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多