Linienalgorithmus
Übersicht

![]() |
darthBetreff: Linienalgorithmus |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hier ist ein (einfacher) Algorithmus um Linien schneller zu zeichnen. Es bietet eine Alternative zum "Original" hier http://www.blitzbase.de/quellcode/bresenham.bb.
Code: [AUSKLAPPEN] Function Linie(x1#,y1#,x2,y2,r,g,b)
farbe=r*$10000+g*$100+b vx#=x2-x1 : vy#=y2-y1 l#=Sqr(vx^2+vy^2) vx=vx/l : vy=vy/l Repeat WritePixelFast x1,y1,farbe x1=x1+vx y1=y1+vy Until Int(x1)=x2 And Int(y1)=y2 End Function Natürlich darf man nicht vergessen vorher den Buffer zu locken, die Anwendung sähe also wie folgt aus: Code: [AUSKLAPPEN] Graphics 800,600
setbuffer backbuffer() Lockbuffer(backbuffer()) linie 0,0,800,600 unlockbuffer(backbuffer()) flip 0 waitkey() Wie auch immer, dieser Code dient "nur" dazu, Linien zu zeichnen. Er ersetzt keine Füllfunktionen, wie zum Beispiel Kreise. Für solches sollte man den Algorithmus aus dem Link verwenden. PS: wer gestrichelte Linien möchte kann den hier verwenden: Code: [AUSKLAPPEN] Function Linie(x1#,y1#,x2,y2,s,r,g,b)
farbe=r*$10000+g*$100+b vx#=x2-x1 : vy#=y2-y1 l#=Sqr(vx^2+vy^2) vx=vx/l : vy=vy/l Repeat If m<=s Then WritePixelFast x1,y1,farbe x1=x1+vx y1=y1+vy m=m+1 If m>=2*s Then m=0 Until Int(x1)=x2 And Int(y1)=y2 End Function [EDIT, 11.04.2010] Hallo, jaja, heute sehe ich ziemlich schnell ein, dass ein Algorithmus mit Wurzel und FloatingPoint Operation nicht wirklich schnell sein kann. Einzig der Code für die "gestrichelte" Linie ist wahrscheinlich sinnvoll :> Aber das zu beurteilen sei anderen überlassen. Ich habe gerade gesehen, dass der verlinkte Code nichtmehr vorhanden ist, also habe ich beschlossen, einen Bresenham kurz selber zu schreiben. Es ist eigentlich gar nicht derart schwer, v.a weil [url=http://en.wikipedia.org/wiki/Bresenham's_line_algorithm]Wikipedia[/url] einen ziemlich guten/einfach zu verstehenden Ansatz liefert. BlitzBasic: [AUSKLAPPEN] Function BLine(x0, y0, x1, y1) Der Code (funktioniert übrigens nur für Spezialfälle..) liest die gesetzte Bildschirmfarbe aus und färbt die Linie danach. Standardmässig wird mit WritePixelFast gezeichnet, das heisst, vor dem Zeichnen der Linie, muss man den Buffer mit LockBuffer versiegeln. Im Anschluss habe ich dann noch einige Geschwindigkeitstests gemacht, das Ergebnis ist eigentlich recht befriedigend. Line im Lockbuffer Modus ist etwa doppelt so schnell wie Bresenham (wahrscheinlich weil BB intern damit arbeitet..). Bresenham (ebenfalls Lockbuffer) folgt mit etwa der doppelten Zeit, und dann etwas langsamer Line ohne Lockbuffer. Die Zeiten sind im 1000stel MS Bereich für einen Aufruf (gemessen 5000 Aufrufe, dividiert), da hat man ziemlich schwankende Ergebnisse, aber es sollte trotzdem repräsentativ sein. Der TestCode: BlitzBasic: [AUSKLAPPEN] Graphics 800,600,0,2 So im Abschluss kann ich eigentlich nur sagen: Benutzt die originale BB Line im Lockbuffer Modus, es ist eigentlich mit Abstand das Schnellste! Und auch aus Erfahrung kann ich sagen, dass man damit eigentlich Bildschirmfüllend zeichnen kann (Beispiel). Dieses Ergebnis macht diesen Thread eigentlich absolut sinnlos. Einzig ein wenig Vektorgeometrie und der Bresenham Algorithmus werden hier dargestellt, deren Verwendung sich in BB nicht lohnt. Auf der Seite wird ebenfalls eine allgemeine und optimierte Version erklärt. Dort hat man keinerlei Float Operationen mehr, es wird alles mit Integern gelöst. Das führt zu einer erhöhten Geschwindigkeit. Der optimierte Algorithmus ist etwa gleich schnell, bis ein kleines bisschen langsamer als die native BB Linie. Der Vollständigkeit wegen sei er aber trotzdem hier eingefügt: BlitzBasic: [AUSKLAPPEN] Function OBLine(x0, y0, x1, y1) Es bleibt also dabei: Benutzt die original Linie im Lockbuffer Modus und ihr habt keine Probleme. So mache ich es eigentlich immer. In dem Sinne: MfG, Darth |
||
- Zuletzt bearbeitet von darth am So, Apr 11, 2010 16:11, insgesamt 4-mal bearbeitet
![]() |
pixelshooter |
![]() Antworten mit Zitat ![]() |
---|---|---|
darf man fragen, warum x1 und y1 float sind? | ||
>> Musikerstellung, Grafik und Design: http://www.pixelshooter.net.tc |
![]() |
darth |
![]() Antworten mit Zitat ![]() |
---|---|---|
weil vx und vy floats sind
und es tut sich schwert int+float zu addieren, so kann es (bei ungünstigen fällen) zu einer endlosschleife und somit zu einem stack overflow kommen, weil die ints nie grösser werden... (und die schleife nie beendet wird) daher float. |
||
Diese Signatur ist leer. |
![]() |
XeresModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
Warum ist Lockbuffer nicht in der Funktion integriert? Kommt's da zu Geschwindigkeitseinbußen wenn man den Buffer immer Locked/unkocked ? | ||
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus THERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld) |
#ReaperNewsposter |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Xeres hat Folgendes geschrieben: Warum ist Lockbuffer nicht in der Funktion integriert? Kommt's da zu Geschwindigkeitseinbußen wenn man den Buffer immer Locked/unkocked ?
Jop, deine Annahme ist richtig ![]() |
||
AMD Athlon 64 3500+, ATI AX800 Pro/TD, 2048 MB DRR 400 von Infineon, ♥RIP♥ (2005 - Juli 2015 -> sic!)
Blitz3D, BlitzMax, MaxGUI, Monkey X; Win7 |
![]() |
maximilian |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ja. Jeder Lock-Aufruf ist eine teure Sache. Du solltest es so managen, pro Schleifendurchlauf nur 1x zu locken, weil anscheinend der gesamte Bildschirminhalt dafür intern von DirectDraw kopiert werden muss.
/edit: argh, zu spät |
||
Variety is the spice of life. One day ignore people, next day annoy them. |
Matthias |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Hay. Also ich kann mir das kaum vorstellen das deine Function schneller ist. Schon alleine wegen der sqr function und den Floats. Aber es kann natürlich gut möglich sein. Deshalb würde ich es mir wünschen wenn du mal tatsächlich einen Code schreibst der beide functionen gegenüberer stellt,
und den Geschwindigkeits-Unterschied in Prozente angibt. |
||
![]() |
BladeRunnerModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
Wenn es Dich interessiert bist Du gerne eingeladen selbst einen Test zu verfassen. | ||
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3 Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64 B3D BMax MaxGUI Stolzer Gewinner des BAC#48, #52 & #92 |
![]() |
Progger93Betreff: Linie ist Langsamer |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ich hab's mal getestet und bin zu folgendem ergebnis gekommen:
nach 5000 durchläufen -line: 704 -linie: 217 Code: [AUSKLAPPEN] Graphics 640,480,16,1 SetBuffer BackBuffer() start1=MilliSecs() For I=0 To 5000 Line 0,0,640,480 Next gesamt1=MilliSecs()-start1 start2=MilliSecs() LockBuffer(BackBuffer()) For I=0 To 5000 Linie(0,0,640,480,255,255,255) Next UnlockBuffer(BackBuffer()) gesamt2=MilliSecs()-start2 Print "Line: "+gesamt1 Print "Linie: "+gesamt2 WaitKey End Function Linie(x1#,y1#,x2,y2,r,g,b) farbe=r*$10000+g*$100+b vx#=x2-x1 : vy#=y2-y1 l#=Sqr(vx^2+vy^2) vx=vx/l : vy=vy/l Repeat WritePixelFast x1,y1,farbe x1=x1+vx y1=y1+vy Until Int(x1)=x2 And Int(y1)=y2 End Function |
||
MfG Pascal
Win 7|T7250@2.0Ghz|3GB RAM|M8600GT |
- Zuletzt bearbeitet von Progger93 am Do, Sep 27, 2007 17:22, insgesamt 2-mal bearbeitet
![]() |
BladeRunnerModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
Du machst Linie nur leider 5000 statt 500 mal. Congrats. | ||
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3 Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64 B3D BMax MaxGUI Stolzer Gewinner des BAC#48, #52 & #92 |
![]() |
Progger93 |
![]() Antworten mit Zitat ![]() |
---|---|---|
sry hab ich übersehen ich werds mal anders versuchen | ||
MfG Pascal
Win 7|T7250@2.0Ghz|3GB RAM|M8600GT |
![]() |
BladeRunnerModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ich hab das ganze auch nochmal Durchlaufen lassen und erziehle ähnliche Ergebnisse - Bresenham gewinnt bei je 5000 Durchläufen mit 240 vor Line mit 270 und Darth mit 450 ms.
Bresenham jedoch musste ich um den letzten Pixel kürzen, da hier trotz lockbuffer der letzte Pixel (writepixelfast x2,y2,rgb) zu einem MAV führte. |
||
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3 Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64 B3D BMax MaxGUI Stolzer Gewinner des BAC#48, #52 & #92 |
Matthias |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Naja konnte ich mir schon fast denken. Und ich finde wenn der Code so langsamm ist gegenüber bresenham und sogar noch der Standertlinie dann gehört er nicht hier rein. | ||
![]() |
Eingeproggt |
![]() Antworten mit Zitat ![]() |
---|---|---|
Wenn man so fair ist, und den Buffer auch für den Line-Versuch locked, ist Line noch fast doppelt so schnell.
Bei mir 240, danach 135ms. Die Version von Darth ist leider wirklich mit Abstand die langamste, aber er hat ne recht einfache Methode eingebaut, um sie strichliert zu machen, ich würds deshalb im Codearchiv lassen. |
||
Gewinner des BCC 18, 33 und 65 sowie MiniBCC 9 |
![]() |
darth |
![]() Antworten mit Zitat ![]() |
---|---|---|
Nach den vielen Ansichten dass mein Algorithmus langsam(er) sei, wollte ich das natürlich selber nachprüfen. Und es stimmt, - teilweise - !
Für lange Linien eignet sich gewiss der eingebaute Line Befehl (je 5000 Linien von 0,0 bis 800,600: Line=600 / Linie=1800). Jetzt ein ABER, für kurze Linien eignet sich mein Algorithmus scheinbar besser. Wieder je 5000 linien, diesmal von 0,0 bis 50,50: Line=171 / Linie=133. Dieser Vorteil ist aber schnell aufgebraucht und erreicht schon bei ca 0,0,100,100 die Stufe, dass Line wieder besser wird. (Da Bresham so ausser Konkurenz steht hab ich den gar nicht mitgetestet, ich glaube euch dass er besser ist ![]() Fazit daraus: Wer sehr kurze Linien braucht ist mit meinem Algorithmus sicherlich nicht schlecht beraten, für lange Linien ist davon abzuraten und auf den eingebauten Befehl zu schwenken oder ganzzeitlich Bresham einzusetzen. PS: Die Testcodes: Code: [AUSKLAPPEN] start1=MilliSecs()
For k=0 To 5000 Color 255,255,255 : Line 0,0,50,50 Next Flip 0 stop1=MilliSecs() start2=MilliSecs() LockBuffer(BackBuffer()) For k=0 To 5000 linie 0,0,50,50,255,255,255 Next UnlockBuffer(BackBuffer()) Flip 0 stop2=MilliSecs() |
||
Diese Signatur ist leer. |
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group