使用SharpDX显示D3DImage

时间:2017-08-21 17:45:50

标签: c# wpf directx-9 intptr

我打算开发一个应用程序来从文件中获取图像并使用Directx9显示它。我已经使用了这段代码,但我在SetBackBuffer方法!!

上得到了错误
System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.



     private void d3dImage_IsFrontBufferAvailableChanged(object sender, DependencyPropertyChangedEventArgs e)
            {
                if (d3dImage.IsFrontBufferAvailable)
                {

                    // (Re)initialization:
                    Bitmap b = new Bitmap(@"C:\Users\newuser\Desktop\3.jpg");
                    IntPtr Mysurface = b.GetHbitmap();

                    if (Mysurface != IntPtr.Zero)
                    {
                        d3dImage.Lock();
//Error occurred this line 
                   d3dImage.SetBackBuffer(D3DResourceType.IDirect3DSurface9, Mysurface);
                        d3dImage.Unlock();
                        CompositionTarget.Rendering += CompositionTarget_Rendering;
                    }
                }
                else
                {
                    // Cleanup:
                    CompositionTarget.Rendering -= CompositionTarget_Rendering;
                    //Sample.Cleanup();
                }
            }


      protected override void OnSourceInitialized(EventArgs e)
            {
                base.OnSourceInitialized(e);
                // Now that we can get an HWND for the Window, force the initialization
                // that is otherwise done when the front buffer becomes available:
                d3dImage_IsFrontBufferAvailableChanged(this,
                new DependencyPropertyChangedEventArgs());
            }


      private void CompositionTarget_Rendering(object sender, EventArgs e)
            {
                if (d3dImage.IsFrontBufferAvailable)
                {
                    d3dImage.Lock();
                    //Sample.Render();
                    // Invalidate the whole area:
                    d3dImage.AddDirtyRect(new Int32Rect(0, 0,
                    d3dImage.PixelWidth, d3dImage.PixelHeight));
                    d3dImage.Unlock();
                }
            }

实际上我想在d3dimage项目的WPF中显示图片。谁能帮我?我找不到关于Directx和C#!!!

的好资源

使用Sharpdx编辑并获得新错误“HRESULT: [0x8876086C], Module: [SharpDX.Direct3D9], ApiCode: [D3DERR_INVALIDCALL/InvalidCall],”

s = new SharpDX.Direct3D9.Surface(IntPtr.Zero);

 SharpDX.Direct3D9.Surface.FromFile(s, @"C:\Users\newuser\Desktop\3.jpg", SharpDX.Direct3D9.Filter.None, 1);

1 个答案:

答案 0 :(得分:1)

您正在将后台缓冲区设置为Bitmap。你不能做这个。后台缓冲区必须是IDirect3DSurface9类型。这在SetBackBuffer方法的文档中有说明。

为了使用C#(托管)中的DirectX9(非托管),您需要使用包装器库。你在用一个吗?如果没有,有几个可用。 SlimDXSharpDX似乎是最受欢迎的。使用任何包装器库,您可以创建使用IDirect3DSurface9呈现的IDirect3DDevice9,并将该表面附加到WPF控件。然后,您呈现的内容将出现在控件中。

我认为使用DirectX对您所需要的内容可能过度,但我不确定您项目的整个范围是什么。

使用SharpDX的解决方案

我整理了一个使用SharpDX在D3DImage内显示图像的工作示例。这是非常基本的,并没有包含正确的错误处理。它只是为了让你朝着正确的方向前进。

步骤1 - 创建D3D9设备

要创建必要的曲面,您需要一个Direct3D 9 Device。以下代码将使用SharpDX创建Device

//Create the d3d interface.
Direct3D d3d = new Direct3D();

//Get a handle to the WPF window. This is required to create a device.
IntPtr windowHandle = new WindowInteropHelper(this).Handle;

//Create a device. Using standard creation param. 
//Width and height have been set to 1 because we wont be using the backbuffer.
//Adapter 0 = default adapter.
PresentParameters presentationParams = new PresentParameters(1,1);
Device d3dDevice = new Device(d3d, 0, DeviceType.Hardware, windowHandle, CreateFlags.HardwareVertexProcessing, presentationParams);

第2步 - 创建图像表面

创建一个表面来保存图像数据。

//Create an empty offscreen surface. Use SystemMemory to allow for surface copying.
Surface imageSurface = Surface.CreateOffscreenPlain(d3dDevice, ImageWidthPixels, ImageHeightPixels, Format.A8R8G8B8, Pool.SystemMemory);

//Fill the surface with the image data.
Surface.FromFile(imageSurface, "dx.jpg", Filter.None, 0);

第3步 - 创建渲染目标表面

创建充当渲染目标的曲面。这是D3DImage所需的表面类型。

//Create the surface that will act as the render target.
//Set as lockable (required for D3DImage)
Surface target = Surface.CreateRenderTarget(d3dDevice, ImageWidthPixels, ImageHeightPixels, Format.A8R8G8B8, MultisampleType.None, 0, true);

步骤4 - 将图像表面复制到渲染目标。

可以使用Device.UpdateSurfaces方法将图像表面复制到渲染目标表面。请注意,在前面的步骤中,两个曲面都使用相同的格式创建(A8R8G8B)。当心这个。这是表面复印所必需的。

//Copy the image surface contents into the target surface.
d3dDevice.UpdateSurface(imageSurface, target);

步骤5 - 将表面附加到D3DImage

现在你有一个包含你的图像的表面,可以用于' D3DImage`。确保使用目标曲面,而不是图像源曲面。

this.wpfImageSource.Lock();
this.wpfImageSource.SetBackBuffer(D3DResourceType.IDirect3DSurface9, target.NativePointer);
this.wpfImageSource.AddDirtyRect(new Int32Rect(0, 0, wpfImageSource.PixelWidth, wpfImageSource.PixelHeight));
this.wpfImageSource.Unlock();

结果

图像出现!

[4]: https://i.stack.imgur.com/OS9Ne.png