2011-05-09 8 views
6

Estoy tratando de hacer una aplicación muy simple que muestre diferentes imágenes en cada ojo. Tengo el monitor Asus VG236H y el kit NVIDIA 3D Vision, las gafas de obturador estéreo 3D. Estoy usando C#, .NET Framework 2.0, DirectX 9 (Managed Direct X) y Visual Studio 2008. He estado buscando alto y bajo ejemplos y tutoriales, he encontrado un par y basé aquellos en los que he creado el programa, pero por alguna razón no puedo hacer que funcione.¿Cómo controlar los estereofónicos por separado con C#? (Gafas con obturador 3D NVIDIA)

Al buscar ejemplos de cómo mostrar diferentes imágenes para cada ojo, muchas personas siguen refiriéndose a la presentación de NVIDIA en GDC 09 (el famoso documento GDC09-3DVision-The_In_and_Out.pdf) y en las páginas 37-40. Mi código está construido principalmente sobre la base de ese ejemplo:

  1. Estoy cargando dos texturas (red.png y blue.png) en la superficie (_imageLeft y _imageRight), en LoadSurfaces función()
  2. Set3D() función pone esas dos imágenes una junto a la otra en una imagen más grande que tiene el tamaño de 2x ancho de pantalla y altura de pantalla + 1 (_imageBuf).
  3. La función Set3D() continúa al agregar la firma estéreo en la última fila.
  4. OnPaint() - la función toma el búfer posterior (_backBuf) y copia el contenido de la imagen combinada (_imageBuf) en él.

Cuando ejecuto el programa, las gafas de obturador comienzan a funcionar, pero solo veo las dos imágenes una al lado de la otra en la pantalla. ¿Podría alguien ayudarme y decirme qué estoy haciendo mal? Creo que resolver este problema también podría ayudar a otros, ya que todavía no parece ser un ejemplo simple de cómo hacer esto con C#.

A continuación se presentan las partes tácticas de mi código. proyecto completo se puede descargar aquí: http://koti.mbnet.fi/jjantti2/NVStereoTest.rar

public void InitializeDevice() 
    { 
     PresentParameters presentParams = new PresentParameters(); 

     presentParams.Windowed = false; 
     presentParams.BackBufferFormat = Format.A8R8G8B8; 
     presentParams.BackBufferWidth = _size.Width; 
     presentParams.BackBufferHeight = _size.Height; 
     presentParams.BackBufferCount = 1; 
     presentParams.SwapEffect = SwapEffect.Discard; 
     presentParams.PresentationInterval = PresentInterval.One; 
     _device = new Device(0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, presentParams); 
    } 

    public void LoadSurfaces() 
    { 
     _imageBuf = _device.CreateOffscreenPlainSurface(_size.Width * 2, _size.Height + 1, Format.A8R8G8B8, Pool.Default); 

     _imageLeft = Surface.FromBitmap(_device, (Bitmap)Bitmap.FromFile("Blue.png"), Pool.Default); 
     _imageRight = Surface.FromBitmap(_device, (Bitmap)Bitmap.FromFile("Red.png"), Pool.Default); 
    } 

    private void Set3D() 
    { 
     Rectangle destRect = new Rectangle(0, 0, _size.Width, _size.Height); 
     _device.StretchRectangle(_imageLeft, _size, _imageBuf, destRect, TextureFilter.None); 
     destRect.X = _size.Width; 
     _device.StretchRectangle(_imageRight, _size, _imageBuf, destRect, TextureFilter.None); 

     GraphicsStream gStream = _imageBuf.LockRectangle(LockFlags.None); 

     byte[] data = new byte[] {0x44, 0x33, 0x56, 0x4e, //NVSTEREO_IMAGE_SIGNATURE   = 0x4433564e 
            0x00, 0x00, 0x0F, 0x00, //Screen width * 2 = 1920*2 = 3840 = 0x00000F00; 
            0x00, 0x00, 0x04, 0x38, //Screen height = 1080    = 0x00000438; 
            0x00, 0x00, 0x00, 0x20, //dwBPP = 32      = 0x00000020; 
            0x00, 0x00, 0x00, 0x02}; //dwFlags = SIH_SCALE_TO_FIT  = 0x00000002; 

     gStream.Seek(_size.Width * 2 * _size.Height * 4, System.IO.SeekOrigin.Begin); //last row 
     gStream.Write(data, 0, data.Length); 

     gStream.Close(); 

     _imageBuf.UnlockRectangle(); 
    } 

    protected override void OnPaint(System.Windows.Forms.PaintEventArgs e) 
    { 
     _device.BeginScene(); 

     // Get the Backbuffer then Stretch the Surface on it. 
     _backBuf = _device.GetBackBuffer(0, 0, BackBufferType.Mono); 
     _device.StretchRectangle(_imageBuf, new Rectangle(0, 0, _size.Width * 2, _size.Height + 1), _backBuf, new Rectangle(0, 0, _size.Width, _size.Height), TextureFilter.None); 
     _backBuf.ReleaseGraphics(); 

     _device.EndScene(); 

     _device.Present(); 

     this.Invalidate(); 
    } 

Respuesta

2

Un amigo mío encontró el problema. Los bytes en la firma estéreo estaban en orden inverso. Aquí está el orden correcto:

byte[] data = new byte[] {0x4e, 0x56, 0x33, 0x44, //NVSTEREO_IMAGE_SIGNATURE   = 0x4433564e; 
0x00, 0x0F, 0x00, 0x00, //Screen width * 2 = 1920*2 = 3840 = 0x00000F00; 
0x38, 0x04, 0x00, 0x00, //Screen height = 1080    = 0x00000438; 
0x20, 0x00, 0x00, 0x00, //dwBPP = 32      = 0x00000020; 
0x02, 0x00, 0x00, 0x00}; //dwFlags = SIH_SCALE_TO_FIT  = 0x00000002; 

El código funciona perfectamente después de este cambio. Este código incluso podría servir como un buen tutorial para alguien más que intenta lo mismo. :)

Cuestiones relacionadas