DrawLines Überlauf

  • VB.NET
  • .NET (FX) 3.0–3.5

Es gibt 21 Antworten in diesem Thema. Der letzte Beitrag () ist von vb-checker.

    Int16.MaxValue ist viel zu klein..
    Brauche das für mein Funktionsgraphen, da ist das Problem wenn bspweise bei einer Funktion extrem große Abweichungen sind, werden die einzelnen Y Schritte (Abstände zwischen den Punkten) zu klein gehalten und die größten Y-Werte können dann schonmal (in Bildschirm Koordinaten) auf über Single.MaxValue kommen und dann kommt so ein Fehler..
    Habs jetzt schon gelöst, war eigtl relativ simpel. (Das ich nich früher drauf gekommen bin..)
    Ich konnte vorm zeichnen einfach abfragen ob die Koordinaten ausserhalb des Bildschirms liegen, wenn Ja einfach den Punkt am Rand zeichnen lassen.
    Das funktioniert, weil beim bewegen die Koordinaten des Graphen bzw der einzelnen Punkte bewegt werden.

    Damit wird auch nur noch das gezeichnet was man auch sehen kann

    Gonger96 schrieb:

    Es ist extrem unperformant, wenn du Sachen renderst die sowieso nicht sichtbar sind.
    Bei Winforms-OwnerDrawing gilt das nicht. Das Rectangle, in was gezeichnet wird, ist geclippt, also das Aufwändige am Zeichnen, nämlich die BildschirmPixel manipulieren, findet nur innerhalb dieses Clips statt.
    Das mit dem Clip hab ich mal fein visualisiert: Control mit beweglicher Figur

    Artentus schrieb:

    Das ist afaik in jeder Grafik-API so
    nein - "normale" Engines malen immer den ganzen Bildschirm. Winforms misst das Eckchen pixelgenau aus, wo reingemalt wird.

    jdfs. Gongers Behauptung, es sei unperformant, ausserhalb des Zeichnungsbereiches zu zeichnen, ist falsch. Indem du an Zeichenbefehlen rumoptimierst, die ansonsten eh wggeclippt werden, gewinnst du gar nix, jdfs. nicht messbar.

    ErfinderDesRades schrieb:

    Winforms misst das Eckchen pixelgenau aus, wo reingemalt wird.
    Redest du jetzt von Invlidate(Region)? Unter DirectX gibts das wirklich nicht, aber darum gings mir nicht. Egal ob GDI, DX, OGL oder was es sonst noch so gibt, die Ausgabe ist nur eine endliche Anzahl an Pixeln, der Puffer. Beim Rastern von Formen in den Puffer können logischerweise nur die Pixel gesetzt werden, die auch da sind, auch unter DirectX wird der Pixel an der Stelle -1,-1 nicht gesetzt werden können. Aber um festzustellen, dass ein Pixel nicht innerhalb des sichtbaren Bereiches, also des Puffers, liegt, muss erstmal die Position des Pixels berechnet und damit schon der komplette Rasterizing-Prozess durchlaufen worden sein. Das einzige, was also tatsächlich wegfällt, ist der Schreibzugriff auf den Puffer, was halt der langsamste Teil ist, aber man stelle sich vor, man hat ein paar millionen Objekte außerhalb des sichtbaren Bereichs, dann summieren sich diese überflüssigen Rasterizing-Berechnungen ziemlich auf und das drückt dann auf die Performance.

    Edit:
    Schreib z.B. mal sowas in den Paint-Handler:

    C#-Quellcode

    1. for (int i = 0; i < 10000000; i++)
    2. {
    3. e.Graphics.FillRectangle(Brushes.White, new Rectangle(-10000, -10000, 5000, 5000));
    4. }
    Obwohl die Rechtecke komplett außerhalb des sichtbaren Bereichs liegen braucht der Zeichenvorgang bei mir einige Sekunden. Zehn Millionen mag viel sein, weit jenseits dessen, was man bei GDI normalerweise zeichnet, aber neuere Computerspiele kommen ganz schnell auf solche Zahlen an Vertices.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Artentus“ ()

    mit iwelchen unperformanten Berechnungen und irrsinnigen Schleifen bremst man jedes Proggi aus.

    Also nochmal der genaue Punkt meiner Aussage: Beim OwnerDrawing ist die Zeichnung geclippt. Von Zeichenbefehlen ist nur derjenige Anteil teuer, der sich auf den Bereich des Clip-Rectangles auswirkt. Alles was ausserhalb "gezeichnet" wird, ist ca. 1000 mal schneller, und daher kann man - wenn man ansonsten effizienten Zeichencode hat - an der Optimierung im ausserhalb liegenden Bereich nicht viel gewinnen.

    Zur Illustration, wie Clipping wirkt:
    geclippt sei das Rectangle {0, 0, 100, 100}
    Dann gibts keinen messbaren Performance-Unterschied, ob man nun die Diagonale mit diesen Punkten zeichnet:
    {0,0} - {100,100}
    oder mit:
    {-1000,-1000} - {1000,1000}

    Schaut euch unbedingt die gegebene Clip-Visualisierung mal an. Insbesondere schiebt das Anwendungsfenster mal tw über den Rand des Bildschirms und zurück - es zeigt sich ein für manche sicherlich überraschender Effekt.

    Artentus schrieb:

    gibts unter DirectX übrigens ganz genauso
    echt?
    ich dachte DirectX würde in jedem Frame halt den ganzen Bildschirm malen (und habs auch noch nie anners gesehen).
    DirectX' Malereien könnten auch auf einen gezielten Ausschnitt beschränkt werden?
    Gibts denn da auch sowas wie die Control.Invalidate(rectangle) - Methode, mit der die Zeichenbereiche quasi aufgesammelt werden, woraus dann der Clip gebildet wird?