2013-10-20 2 views
7

Desidero disegnare linee il più velocemente possibile. Per questo motivo ho implementato un metodo utilizzando InteropBitmap. Funziona abbastanza bene. Il passo successivo è stato il confronto con ShardDX. Fondamentalmente quello che voglio fare è: Eseguendo il seguente codice in un BackgroundWorker. Questo informa il WPF su un aggiornamento del WIC. Ho scoperto che questo codice (che crea tutto il necessario per ShapeDX e tracciare linee) impiega circa 10ms in più rispetto a fare lo stesso usando InteropBitmap.SharpDX render in WPF

La mia domanda ora è semplicemente, come accelerare questo? Posso cambiare il codice in qualche modo che devo solo chiamare BeginDraw, creare linee e EndDraw, non sempre facendo tutto questo materiale di codifica/decodifica delle immagini? O c'è un approccio migliore?

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(); 

Con:

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

E:

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

risposta

4

SharpDX Toolkit supporta WPF tramite una trama condivisa Direct3D11-to-Direct3D9. È implementato nella classe SharpDXElement.

Potrebbe non essere possibile riutilizzarlo perché Direct2D (che si sta utilizzando per disegnare) può essere utilizzato con Direct3D11.1 o Direct3D10 e SharpDX utilizza Direct3D11 per il supporto WPF, quindi sarà necessario modificare la soluzione a un po.

In sostanza è necessario effettuare le seguenti operazioni:

  • inizializzazione Direct3D (10 o 11.1).
  • Inizializza Direct2D.
  • Creare la destinazione di rendering D3D con supporto Direct2D e il flag Shared (here è come è fatto in SharpDX).
  • Inizializza Direct3D9.
  • Creare il numero condiviso texture.
  • Associare la trama a D3DImage.

Non dimenticare di chiamare D3DImage.AddDirtyRect quando i contenuti della destinazione di rendering vengono aggiornati.

Dal codice che hai fornito non è chiaro se si sta facendo alcuna inizializzazione solo una volta o no, quindi cercate di chiamare qualsiasi codice di inizializzazione solo una volta e riutilizzare il target render - basta cancellarlo all'inizio di ogni frame. Questo è obbligatorio per ottenere prestazioni decenti.

Aggiornamento: SharpDX.Il Toolkit è stato deprecato e non viene più mantenuto. Viene spostato in un repository separato.

+0

Il collegamento a SharpDXElement è rotto. Si prega di aggiornarlo. – BrainSlugs83

+0

@ BrainSlugs83 - i collegamenti sono stati aggiornati. –

+0

A partire dal 2017, dicono: 'Il codice corrente del Toolkit in questo repository non funziona più con l'ultimo ramo di SharpDX.» – vines

4

Se si desidera condividere una superficie directx con WPF, l'opzione migliore è usare un WPF D3DImage. Promette di lavorare senza copiare se si utilizza il giusto formato di colore.

L'ho usato solo con Directx9, ma è possibile che sia compatibile anche con Direct2D, ma se non lo è D3d9 può disegnare anche le linee.

C'è un ottimo codeproject article con esempi. Dal codice gestito usando slimdx o sharpdx l'unica avvertenza non ovvia è che D3DImage conserva un conteggio dei riferimenti sulla superficie di DirectX, quindi è necessario azzerare il backbuffer in modo esplicito quando si desidera ripristinare il dispositivo d3d.

+0

Sembra un approccio migliore, forse potresti condividere un piccolo esempio? Aderendo al codice sopra? Sono abbastanza nuovo per questa roba DirectX. Ho iniziato a cercare già ma forse potresti aiutarti molto più velocemente. – user2799180

+0

Grazie per l'esempio. Ho già visto questo esempio ma non è così ovvio per me. DirectX è davvero nuovo per me, quindi preferirei un esempio senza la necessità di una libreria C++ a seconda del DirectX SDK. Sfortunatamente, non riesco a vedere come potrei applicare sharpdx su questo esempio. – user2799180