SharpDX在WPF中呈现

时间:2013-10-20 17:13:42

标签: c# wpf sharpdx

我想尽快画出线条。出于这个原因,我使用InteropBitmap实现了一个方法。这非常有效。下一步是与ShardDX进行比较。基本上我想做的是: 在BackgroundWorker中运行以下代码。这确实告知WPF有关WIC的更新。我发现这个代码(创建ShapeDX和绘制线所需的所有代码)比使用InteropBitmap做同样的代码要花费大约10ms。

我现在的问题很简单,如何加快速度?我可以以某种方式更改代码,我只需要调用BeginDraw,创建行和EndDraw,而不是总是执行所有这些图像编码/解码的东西吗?或者有更好的方法吗?

var wicFactory = new ImagingFactory();
var d2dFactory = new SharpDX.Direct2D1.Factory();

const int width = 800;
const int height = 200;

var wicBitmap = new Bitmap(wicFactory, width, height, SharpDX.WIC.PixelFormat.Format32bppBGR, BitmapCreateCacheOption.CacheOnLoad);

var renderTargetProperties = new RenderTargetProperties(RenderTargetType.Default, new PixelFormat(Format.Unknown, AlphaMode.Unknown), 0, 0, RenderTargetUsage.None, FeatureLevel.Level_DEFAULT);

var d2dRenderTarget = new WicRenderTarget(d2dFactory, wicBitmap, renderTargetProperties);

var solidColorBrush = new SharpDX.Direct2D1.SolidColorBrush(d2dRenderTarget, SharpDX.Color.White);

d2dRenderTarget.BeginDraw();
//draw whatever you want
d2dRenderTarget.EndDraw();

// Memorystream.
MemoryStream ms = new MemoryStream();
var stream = new WICStream(wicFactory, ms);
// JPEG encoder
var encoder = new SharpDX.WIC.JpegBitmapEncoder(wicFactory);
encoder.Initialize(stream);

// Frame encoder
var bitmapFrameEncode = new BitmapFrameEncode(encoder);
bitmapFrameEncode.Initialize();
bitmapFrameEncode.SetSize(width, height);
var pixelFormatGuid = SharpDX.WIC.PixelFormat.FormatDontCare;
bitmapFrameEncode.SetPixelFormat(ref pixelFormatGuid);
bitmapFrameEncode.WriteSource(wicBitmap);

bitmapFrameEncode.Commit();
encoder.Commit();

ms.Seek(0, SeekOrigin.Begin);

// JPEG decoder
var decoder = new System.Windows.Media.Imaging.JpegBitmapDecoder(ms, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
// Write to wpf image
_WIC = decoder.Frames[0];
// Tell WPF to update
RaisePropertyChanged("WIC");

bitmapFrameEncode.Dispose();
encoder.Dispose();
stream.Dispose();

使用:

System.Windows.Media.Imaging.BitmapFrame _WIC;
    public System.Windows.Media.Imaging.BitmapSource WIC
    {
        get
        {
            return (System.Windows.Media.Imaging.BitmapSource)_WIC.GetAsFrozen();
        }
    }

<StackPanel>
   <Image Name="huhu1" Source="{Binding WIC}" />  
</StackPanel>

3 个答案:

答案 0 :(得分:6)

SharpDX Toolkit通过Direct3D11到Direct3D9共享纹理支持WPF。它在SharpDXElement类中实现。

您可能无法按原样重复使用,因为Direct2D(您用于绘制)可以与Direct3D11.1或Direct3D10互操作,SharpDX使用Direct3D11支持WPF,因此您需要稍微调整一下解决方案位。

基本上您需要执行以下操作:

  • 初始化Direct3D(10或11.1)。
  • 初始化Direct2D。
  • 使用Direct2D支持创建D3D渲染目标,Shared标志(here是在SharpDX中完成的方式)。
  • 初始化Direct3D9
  • 创建共享的texture
  • 将纹理绑定到D3DImage

当渲染目标的内容更新时,不要忘记调用D3DImage.AddDirtyRect

从你提供的代码中不清楚你是否只进行了一次所有的初始化,所以尝试只调用一次初始化代码并重用渲染目标 - 只需在每一帧的开头清除它。这是获得良好表现的必要条件。

更新:SharpDX.Toolkit已被弃用,不再维护。它被移动到一个单独的存储库。

答案 1 :(得分:5)

如果您想与WPF共享directx表面,最好的选择是使用WPF D3DImage。如果使用正确的颜色格式,它可以在不复制的情况下工作。

我只使用它与Directx9,但它也可能与Direct2D兼容,但如果它不是D3d9也可以画线。

有一个很棒的codeproject article示例。从使用slimdx或sharpdx的托管代码中,唯一不明显的警告是D3DImage保留了DirectX表面的引用计数,因此当您想要重置d3d设备时,需要显式地使后备缓冲区为空。

答案 2 :(得分:0)

您可以使用this

它在WPF中使用sharpDx,而wpf可以将Win32HwndControl添加到HwndHost。