[TIP] Ottimizzare performance 3D di WPF

WPF mette a disposizione un framework potentissimo per lavorare con oggetti e animazioni 3D. Noterete tuttavia che man mano che le interfacce si fanno più complesse, le performance dell'applicazione tendono a decadere velocemente.

Ecco quindi solo uno dei tip per accellerare l'esecuzione di oggetti tridimensionali. Supponiamo che abbiate una superficie (piano, sfera, quello che volete :)) tridimensionale e che vogliate applicare su di essa un VisualBrush.

La strada più semplice e veloce è quella di decorare il materiale della superficie con un VisualBrush, la cui Visual può puntare a un oggetto 2D o un oggetto creato a runtime: questo approccio tuttavia occupa molte risorse per il binding del Visual3D al brush originale.

Una soluzione che accellera parecchio le prestazioni grafiche può essere quella di convertire manualmente il VisualBrush in una immagine (ImageBrush), applicando poi all'oggetto 3D solo l'immagine. Il contro di questa soluzione è che si perde il binding tra la superficie e il brush: dovrete qiundi riapplicare l'immagine alla superficie ogni volta che il brush iniziale viene modificato. Vi assicuro però  che il miglioramento prestazionale è elevatissimo: nella maggior parte delle applicazioni conviene quindi complicare un po' di più il codice, risparmiando in prestazioni.

Ecco la funzione che vi permette di fare la magica trasformazione di un VisualBrush in ImageSource:

public ImageSource RasterizeVisual(VisualBrush visualBrush)

        {

            Rect bounds = VisualTreeHelper.GetDescendantBounds(visualBrush.Visual);

            RenderTargetBitmap rtb = new RenderTargetBitmap((int)(bounds.Width),

                                                            (int)(bounds.Height),

                                                            96,

                                                            96,

                                                            PixelFormats.Pbgra32);

            DrawingVisual dv = new DrawingVisual();

using (DrawingContext ctx = dv.RenderOpen())

            {

                ctx.DrawRectangle(visualBrush, null, new Rect(new Point(), bounds.Size));

            }

            rtb.Render(dv);

return rtb;

        }

 

Print | posted on domenica 28 gennaio 2007 15:16

Comments have been closed on this topic.