www.rolandk.de
- Aktuelle Themen zu .Net -
Achtung: Hier handelt es sich um meine alte Seite.
Die aktuelle ist unter folgendem Link erreichbar: www.rolandk.de/wp/
Home Tutorials Direct2D und DirectWrite Chapter 2 - Einfache Objekte




















































Chapter 2 - Einfache Objekte
Donnerstag, den 29. Juli 2010 um 17:48 Uhr

 

 

Brushes in Direct2D

Im Grunde haben wir im letzten Kapitel gesehen, dass zeichnen in Direct2D im Prinzip nicht viel anders als in System.Drawing funktioniert. In diesem Kapitel schauen wir uns genauer an, wie sich Direct2D bei mehreren Objekten verhält, wie transparente Objekte gezeichnet werden. Zusätzlich habe ich im Beispielprogramm einen einfachen Performancevergleich zwischen System.Drawing und Direct2D implementiert.

 

Im letzten Kapitel haben wir ja schon für den Hintergrund einen SolidGradientBrush erzeugt. Folgendes Coding zeigt das noch mal zur Wiederholung:

  1. //Create linear gradient brush
  2. D2D.GradientStop[] gradientStops = new D2D.GradientStop[]
  3. {
  4. new D2D.GradientStop(){ Position = 0f, Color = new Color4(Color.LightGray) },
  5. new D2D.GradientStop(){ Position = 1f, Color = new Color4(Color.LightSteelBlue) }
  6. };
  7. m_backBrushGradient = new D2D.GradientStopCollection(m_renderTarget, gradientStops);
  8. m_backBrushEx = new D2D.LinearGradientBrush(
  9. m_renderTarget,
  10. m_backBrushGradient,
  11. new D2D.LinearGradientBrushProperties()
  12. {
  13. StartPoint = new PointF(0, this.Height),
  14. EndPoint = new PointF(0, 0)
  15. });

In diesem Ausschnitt wird zuerst eine Array mit GradientStop Strukturen angelegt. Diese beschreiben, wie genau der Farbverlauf verläuft (In diesem Beispiel am Anfang Grau und am Ende Blau). Man kann natürlich auch Zwischenschritte angeben, also ganz wie in System.Drawing oder WPF auch. Das Gegenstück in System.Drawing würde so aussehen:

  1. //Create gdi backbrush
  2. m_backBrushGdi = new LinearGradientBrush(
  3. new Point(0, this.Height),
  4. new Point(0, 0),
  5. Color.LightGray,
  6. Color.LightSteelBlue);

Andere Brush Typen gibt es in Direct2D natürlich auch, so gibt es etwa einen SolidColorBrush für einfache Farben, einen RadialGradientBrush für runde Farbverläufe und einen BitmapBrush für Bilder. Im nächsten Ausschnitt werden zum Beispiel SolidColorBrush Objekte erzeugt:

  1. //Create solid brush
  2. m_blackBrush = new D2D.SolidColorBrush(m_renderTarget, new Color4(Color.Black));
  3. m_lightBlueBrush = new D2D.SolidColorBrush(m_renderTarget, new Color4(Color.LightBlue));
  4. m_blackBrush.Opacity = 0.4f;
  5. m_lightBlueBrush.Opacity = 0.4f;

Neu hier ist Allerdings die Opacity Eigenschaft. Hiermit kann man bestimmen, mit welchem Transparenzfaktor gezeichnet werden soll (0 = Durchsichtig, 1 = Undurchsichtig). Da es sich dabei um eine Eigenschaft der Basisklasse Brush handelt, können wir das für alle anderen Brush Typen genauso festlegen und auch jederzeit verändern, ohne die Resource neu erzeugen zu müssen. Interessant ist, dass es auch Performancetechnisch für Direct2D nicht viel Unterschied macht, ob jetzt transparent gezeichnet wird, oder nicht. Diesen Umstand verdanken wir der verstärkten Hardwarebeschleunigung von Direct2D.

 

Zeichnen mehrerer Objekte

Wie man im Screenshot weiter oben sieht, werden in diesem Beispiel jede Menge abgerundeter Rechtecke gezeichnet. Die Parameter beim Zeichnen (etwa Größe der Rechtecke, ob transparent gezeichnet wird, ...) werden in einem Panel eingestellt, welches an der oberen linken Ecke zu finden ist. Im Beispiel kann man zwar zwischen System.Drawing und Direct2D umschalten, hier aber lediglich der Direct2D teil, damit es nicht zu lang wird:

  1. if (m_chkHighQuality.Checked) { m_renderTarget.AntialiasMode = D2D.AntialiasMode.PerPrimitive; }
  2. else { m_renderTarget.AntialiasMode = D2D.AntialiasMode.Aliased; }
  3.  
  4. //Fill background
  5. m_renderTarget.FillRectangle(
  6. m_backBrushEx,
  7. new Rectangle(new Point(), this.Size));
  8.  
  9. //Update transparency of brushes
  10. if (m_chkTransparent.Checked)
  11. {
  12. m_blackBrush.Opacity = 0.5f;
  13. m_lightBlueBrush.Opacity = 0.5f;
  14. }
  15. else
  16. {
  17. m_blackBrush.Opacity = 1f;
  18. m_lightBlueBrush.Opacity = 1f;
  19. }
  20.  
  21. //Draw all rectangles
  22. int rectSize = m_scrollRectangleSize.Value;
  23. int rectSpacing = m_scrollRectangleSize.Value / 10;
  24. int radius = m_scrollRectangleSize.Value / 7;
  25. int rectangleCount = 0;
  26. for (int loopX = 0; loopX < this.Width / rectSize + 1; loopX++)
  27. {
  28. for (int loopY = 0; loopY < this.Height / rectSize + 1; loopY++)
  29. {
  30. if (m_chkRounded.Checked)
  31. {
  32. //Create rectangle to draw
  33. D2D.RoundedRectangle rect = new D2D.RoundedRectangle()
  34. {
  35. Left = loopX * rectSize + rectSpacing,
  36. Right = loopX * rectSize + rectSize - rectSpacing,
  37. Top = loopY * rectSize + rectSpacing,
  38. Bottom = loopY * rectSize + rectSize - rectSpacing,
  39. RadiusX = (float)radius,
  40. RadiusY = (float)radius
  41. };
  42.  
  43. //Draw the rectangle (border and fill)
  44. m_renderTarget.FillRoundedRectangle(m_lightBlueBrush, rect);
  45. m_renderTarget.DrawRoundedRectangle(m_blackBrush, rect);
  46. }
  47. else
  48. {
  49. Rectangle rect = new Rectangle(
  50. loopX * rectSize + rectSpacing,
  51. loopY * rectSize + rectSpacing,
  52. rectSize - rectSpacing, rectSize - rectSpacing);
  53. m_renderTarget.FillRectangle(m_lightBlueBrush, rect);
  54. m_renderTarget.DrawRectangle(m_blackBrush, rect);
  55. }
  56.  
  57. //Count rectangles
  58. rectangleCount++;
  59. }
  60. }

In diesem Ausschnitt werden vor dem Zeichnen erst einmal verschiedenste Parameter gezogen. So wird etwa ganz am Anfang festgelegt, ob die Kanten geglättet werden sollen, oder nicht. Dies erfolgt recht einfach über die AntialiasMode im RenderTarget Objekt und gilt für alle von da an gezeichneten Objekte. Anschließend wird die Transparenz der Brushes und die Größe der Rechtecke (und damit die Anzahl) festgelegt. Beim Zeichnen selbst wird zwischen zwei Möglichkeiten unterschieden, einmal abgerundete und einmal normale Rechtecke. Man sieht schnell, dass das vom Coding her nicht viel Unterschied macht, allerdings wirkt sich das geringfügig auf die Performance aus.

 

Weiter geht's

In diesem Kapitel haben wir uns die Brushes genauer angeschaut und mehrere Objekte mit oder ohne Transparenz gezeichnet. Man sieht in diesem Beispiel wieder, dass die Anwendung von Direct2D kein Hexenwerk ist. Im nächsten Kapitel schauen wir uns das etwas komplexere Thema Text an und behandeln dabei die Schnittstelle DirectWrite.

 

Quellen

  • DirectX SDK
    Die Beispiele und die Dokumentation im DirectX SDK sind zwar auf C++ ausgelegt, da sich SlimDX stark an der originalen API orientiert, ist das SDK aber dennoch sehr hilfreich.
  • Msdn
    Auf Msdn findet man eine sehr umfangreiche Hilfe zu Direct2D und DirectWrite.
  • SlimDX
    Hauptseite des SlimDX-Projekts.

 

Siehe auch...

 

Kommentar hinzufügen

Ihr Name:
Kommentar: