9

我想尽可能快地画线。出于这个原因,我使用 InteropBitmap 实现了一个方法。这工作得很好。下一步是与 ShardDX 进行比较。基本上我想做的是:在 BackgroundWorker 中运行以下代码。这确实会通知 WPF 关于 WIC 的更新。我发现这段代码(创建 ShapeDX 和画线所需的所有代码)比使用 InteropBitmap 执行相同的代码要长约 10 毫秒。

我现在的问题很简单,如何加快速度?我可以以某种方式更改代码,我只需要调用 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>
4

3 回答 3

6

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

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

基本上你需要做以下事情:

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

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

从您提供的代码中不清楚您是否只进行一次所有初始化,因此请尝试仅调用一次任何初始化代码并重用渲染目标 - 只需在每一帧的开头清除它即可。这是获得良好性能的必要条件。

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

于 2013-10-31T15:57:04.873 回答
5

如果您想与 WPF 共享一个 directx 表面,最好的选择是使用WPF D3DImage。如果您使用正确的颜色格式,它承诺无需复制即可工作。

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

有一篇很棒的代码项目文章,其中包含示例。从使用 slimdx 或 sharpdx 的托管代码中,唯一不明显的警告是 D3DImage 保留对您的 DirectX 表面的引用计数,因此当您想要重置您的 d3d 设备时,您需要显式地清空后台缓冲区。

于 2013-10-20T17:24:33.283 回答
0

您可以使用Smartrak/WpfSharpDxControl:提供 WPF 控件来托管 SharpDx 内容。

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

于 2018-04-12T08:37:17.013 回答