2012-01-26 15 views
6

Qualcuno potrebbe fornire un esempio di un modo efficace per lavorare con i pixel usando Direct2D?Come lavorare con i pixel usando Direct2D

Per esempio, come posso scambiare tutti verdi pixel (RGB = 0x00FF00) con pixel rossi (RGB = 0xFF0000) su un target di rendering? Qual è l'approccio standard? È possibile utilizzare ID2D1HwndRenderTarget per quello? Qui presumo l'utilizzo di una sorta di accelerazione hardware. Devo creare un oggetto diverso per le manipolazioni dirette dei pixel?

Utilizzo di DirectDraw Vorrei utilizzare il metodo BltFast su IDirectDrawSurface7 con un'operazione logica. C'è qualcosa di simile con Direct2D?

Un altro compito è generare dinamicamente immagini complesse dove ogni punto di posizione e colore è il risultato di una funzione matematica. Per fare un esempio, semplifichiamo tutto e disegniamo Y = X^2. Come farlo con Direct2D? In definitiva avrò bisogno di disegnare funzioni complesse, ma se qualcuno potrebbe darmi un semplice esempio per Y = X^2.

risposta

11

Innanzitutto, è utile pensare a ID2D1Bitmap come a "bitmap del dispositivo". Può o meno vivere in una memoria indirizzabile localmente dalla CPU, e non offre alcun modo conveniente (o almeno veloce) per leggere/scrivere i pixel dal lato CPU del bus. Quindi avvicinarsi da quell'angolo è probabilmente l'approccio sbagliato.

Quello che penso si voglia è un normale bitmap WIC, IWICBitmap, che è possibile creare con IWICImagingFactory :: CreateBitmap(). Da lì puoi chiamare Lock() per ottenere il buffer, quindi leggere/scrivere usando i puntatori e fare quello che vuoi. Quindi, quando è necessario disegnarlo sullo schermo con Direct2D, utilizzare ID2D1RenderTarget :: CreateBitmap() per creare una nuova bitmap del dispositivo o ID2D1Bitmap :: CopyFromMemory() per aggiornare una bitmap del dispositivo esistente. Puoi anche eseguire il rendering in un IWICBitmap utilizzando ID2D1Factory :: CreateWicBitmapRenderTarget() (non accelerato hardware).

Non si otterrà l'accelerazione hardware per questi tipi di operazioni. Il Direct2D aggiornato in Win8 (dovrebbe essere disponibile anche per Win7 alla fine) ha alcune cose spiffy per questo, ma è piuttosto complesso.

0

Il problema specifico di scambiare tutti i pixel verdi con pixel rossi può essere affrontato tramite ID2D1Effect come di Windows 8 e aggiornamento della piattaforma per Windows 7.

Più in particolare, Color matrix effect.

8

di Rick risposta parla i metodi può essere usato se non ti interessa perdere l'accelerazione hardware. Mi sto concentrando su come ottenere ciò utilizzando una notevole quantità di accelerazione GPU.

Per mantenere l'hardware di rendering accelerato e ottenere le migliori prestazioni, è necessario passare da ID2DHwndRenderTarget alle nuove interfacce ID2DDevice e ID2DDeviceContext. Onestamente non aggiunge molta più logica al tuo codice e i vantaggi in termini di prestazioni sono notevoli. Funziona anche su Windows 7 con l'aggiornamento della piattaforma. Per riepilogare il processo:

  1. Creare una fabbrica DXGI quando si crea la fabbrica D2D.
  2. Creare un dispositivo D3D11 e un dispositivo D2D da abbinare.
  3. Creare una catena di scambio utilizzando la fabbrica DXGI e il dispositivo D3D.
  4. Chiedere la catena di scambio per il suo buffer posteriore e avvolgerla in un bitmap D2D.
  5. Render come prima, tra le chiamate a BeginDraw() e EndDraw(). Ricorda di separare il buffer posteriore e distruggere il bitmap D2D avvolgendolo!
  6. Call Present() sulla catena di scambio per visualizzare i risultati.
  7. Ripetere dal 4.

Una volta fatto questo, avete sbloccato una serie di possibili soluzioni. Probabilmente il modo più semplice e più efficace per risolvere il tuo problema esatto (scambiare i canali colore) è usare lo color matrix effect come una delle altre risposte citate. È importante riconoscere che è necessario utilizzare l'interfaccia ID2DDeviceContext più recente anziché ID2DHwndRenderTarget per ottenere ciò. Ci sono molti altri effetti che possono fare operazioni più complicate se lo si desidera. Ecco alcuni di quelli più utili per semplice modifica dei pixel:

Per generalmente risolvere il problema di manipolare i pixel direttamente senza far cadere accelerazione hardware o facendo tonnellate di copia, ci sono due opzioni. Il primo è scrivere un pixel shader e avvolgerlo in un effetto D2D completamente personalizzato. È più lavoro che ottenere il buffer dei pixel sulla CPU e fare un po 'vecchio bit-mashing, ma fare tutto ciò sulla GPU è sostanzialmente più veloce. Il framework degli effetti D2D rende anche estremamente semplice riutilizzare i tuoi effetti per altri scopi, combinarli con altri effetti, ecc.

Per quelle volte in cui devi assolutamente fare manipolazioni con pixel della CPU ma vuoi comunque un notevole grado di accelerazione, puoi gestire le tue trame D3D11 mappabili. Ad esempio, è possibile utilizzare le textures di staging se si desidera manipolare in modo asincrono le risorse di texture dalla CPU. C'è another answer che va più in dettaglio. Vedere ID3D11Texture2D per ulteriori informazioni.

+2

Degno di nota è che è possibile utilizzare 'QueryInterface' su un ID2D1RenderTarget' (qualsiasi tipo)' per ottenere la 'ID2D1DeviceContext'. Ciò consente di utilizzare il metodo molto più semplice 'ID2D1Factory :: CreateHwndRenderTarget' ma ancora ottenere l'API più recente e evitare di trattare con i documenti DXGI/Direct3D. Questo non è documentato, ma sembra essere intenzionale, da quello che posso dire. –