Как мне запрограммировать видеокарту с поддержкой стерео для отображения стереоизображений? - PullRequest
4 голосов
/ 08 февраля 2011

Я бы хотел написать свой собственный просмотрщик стереоизображений, потому что мне нужны определенные функции, которых нет в той, что входит в комплект поставки моего NVidia / EVGA GTX 580.

Я не могу понять, какчтобы запрограммировать карту на переход в режим «shutterglass», в котором чередуются все остальные кадры (при 120 Гц) влево и вправо.

Я смотрел на API OpenGL, Direct3D и XNA, а также на информацию от NVIDIA.и не могу понять, с чего начать.Как настроить отдельные левые и правые изображения, как сказать экрану, чтобы он отображался, и как сказать драйверу активировать передатчик ShutterGlass?

(Еще одна неприятная вещь заключается в том, что всякий раз, когда я использую в комплектепрограммное обеспечение для просмотра стереоизображений и видео в режиме ShutterGlass, оно работает в полноэкранном режиме, и экран мигает при входе в этот режим - даже если я запускаю экран на частоте 120 Гц в режиме 2D. Есть ли способ создать трехмерную поверхность в окне, не нарушая настройки?остальная часть экрана на видеокартах NVidia с поддержкой 3D (570, 580)?

Ответы [ 2 ]

3 голосов
/ 21 ноября 2012

Я немного опоздал с этим, но я только что получил стереоскопическое 3D для работы, используя только GTX 580 и OpenGL.Нет необходимости в карте Quadro или DirectX.

У меня есть драйвер nVidia 3D Vision и ИК-излучатель, и я просто установил для излучателя значение «Всегда включено» на панели управления nVidia.

В моей игреПосле этого я переключился в полноэкранный режим с частотой 120 Гц и дважды визуализировал сцену с небольшим смещением усеченного конуса (в соответствии с собственной документацией nVidia в формате PDF о ручной реализации " 2010_GTC2010.pdf ").

Нет необходимости в четырехъядерных буферах или других трюках, это прекрасно работает.Кроме того, я контролирую все настройки, такие как конвергенция и т. Д.

2 голосов
/ 08 февраля 2011

Для NVidia 3Dvision с диапазоном GEForce вам необходимо написать полноэкранную поверхность DirectX, в два раза превышающую ширину дисплея, с левым изображением слева, справа справа (дух).
Затем вам нужно записать магическое значение в левом нижнем углу изображения, которое драйвер NVision подхватывает и включает очки, вам не нужен nvapi.dll

С очками Nvidia pro и картой Quadra вы можете использовать обычный стерео API OpenGL.

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

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...