Wu's AntiAliasing-Linie

Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Neue Antwort erstellen

ChaosCoder

Betreff: Wu's AntiAliasing-Linie

BeitragSo, Apr 20, 2008 4:32
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo liebe Community,

nach erfolgloser Forensuche und auch erfolglosem stöbern im englischen Codearchiv nach einer Funktion, die es ermöglicht AntiAliasing-Linien zu zeichnen, habe ich mich mal schlau gemacht und fand den Algorithmus von Xiaolin Wu ganz angemessen. Er ermöglicht eben dieses Zeichnen von Linien mit Kantenglättung.
Ein paar Kleinigkeiten hab ich abgeändert und so lässt sich das Ergebnis doch echt sehen.
user posted image
Und hier kommt der Code:
Code: [AUSKLAPPEN]
Type TLine

   Function drawPlot(x:Int, y:Int, c:Float)
      c = 1 - (Cos(c * 180) + 1) / 2
      SetAlpha c
       Plot(x, y)
   End Function
   
   Function ipart:Int(x:Float)
       Return Int(x)
   End Function
   
   Function round:Int(x:Float)
       Return ipart(x + 0.5)
   End Function
   
   Function fpart:Float(x:Float)
       Return x - Int(x)
   End Function
   
   Function rfpart:Float(x:Float)
       Return 1 - fpart(x)
   End Function
   
   Function draw(x1:Float, y1:Float, x2:Float, y2:Float)
   
      Local lastalpha:Float = GetAlpha()
      Local tmp:Float
      
      Local dx:Int, dy:Int
      Local gradient:Float
      Local xend:Int, yend:Int, xgap:Float, ygap:Float
      Local xpxl1:Float, ypxl1:Float, xpxl2:Int, ypxl2:Int
      Local ypyl1:Float, xpyl1:Float, ypyl2:Float, xpyl2:Float
      Local interx:Float, intery:Float
      
      If Abs(x2 - x1) > Abs(y2 - y1)
      
         If x1 > x2 tmp = x1 x1 = x2 x2 = tmp tmp = y1 y1 = y2 y2 = tmp
      
         dx = x2 - x1
         dy = y2 - y1
         gradient = dy / Float(dx)
         
         xend = round(x1)
         yend = y1 + gradient * (xend - x1)
         xgap = rfpart(x1 + 0.5)
         xpxl1 = xend
         ypxl1 = ipart(yend)
         drawPlot(xpxl1, ypxl1, rfpart(yend) * xgap * lastalpha)
         drawPlot(xpxl1, ypxl1 + 1, fpart(yend) * xgap * lastalpha)
         intery = yend + gradient
         
         xend = round(x2)
         yend = y2 + gradient * (xend - x2)
         xgap = fpart(x2 + 0.5)
         xpxl2 = xend
         ypxl2 = ipart(yend)
         drawPlot(xpxl2, ypxl2, rfpart(yend) * xgap * lastalpha)
         drawPlot(xpxl2, ypxl2 + 1, fpart(yend) * xgap * lastalpha)
         
         For Local x:Int = xpxl1 + 1 To xpxl2 - 1
            drawPlot(x, ipart(intery), rfpart(intery) * lastalpha)
            drawPlot(x, ipart(intery) + 1, fpart(intery) * lastalpha)
            intery = intery + gradient
         Next
         
      Else
      
         If y1 > y2 tmp = y1 y1 = y2 y2 = tmp tmp = x1 x1 = x2 x2 = tmp
      
         dy = y2 - y1
         dx = x2 - x1
         gradient = dx / Float(dy)
         
         yend = round(y1)
         xend = x1 + gradient * (yend - y1)
         ygap = rfpart(y1 + 0.5)
         ypyl1 = yend
         xpyl1 = ipart(xend)
         DrawPlot(xpyl1, ypyl1, rfpart(xend) * ygap * lastalpha)
         DrawPlot(xpyl1, ypyl1 + 1, fpart(xend) * ygap * lastalpha)
         interx = xend + gradient
         
         yend = round(y2)
         xend = x2 + gradient * (yend - y2)
         ygap = fpart(y2 + 0.5)
         ypyl2 = yend
         xpyl2 = ipart(xend)
         DrawPlot(xpyl2, ypyl2, rfpart(xend) * ygap * lastalpha)
         DrawPlot(xpyl2, ypyl2 + 1, fpart(xend) * ygap * lastalpha)
         
         For Local y:Int = ypyl1 + 1 To ypyl2 - 1
            DrawPlot(ipart(interx), y, rfpart(interx) * lastalpha)
            DrawPlot(ipart(interx) + 1, y, fpart(interx) * lastalpha)
            interx = interx + gradient
         Next
      
      EndIf
      
      SetAlpha lastalpha
      
   End Function
   
End Type

Allerdings verwende ich den Befehl "Plot" weshalb die Funktion viiieeeel langsamer ist als die normale DrawLine-Funktion. Man könnte nun natürlich die Funktion abändern, damit sie auf pixmaps mit WritePixel schreibt, wie schnell das ist habe ich noch nicht getestet. Also man sollte es mit der Funktion jedenfalls nicht übertreiben Smile Falls jemand Bock hat das ganze noch weiter zu optimieren, nur zu, ich weiß grad nicht wie man das noch machen könnte... Ich habs jetzt erstmal als Klasse gemacht, wer will kanns natürlich auch als Funktion implementieren, das sollte ja kein Problem sein Razz
Damit mans gleich testen kann hier ein Beispielcode (Bitte oben besagten Code hinzufügen):
Code: [AUSKLAPPEN]
Graphics 400, 400, 0
SetBlend ALPHABLEND
SetClsColor 255, 255, 255
SetColor 0, 0, 0
Global angle:Int
While Not KeyHit(27)
   Cls
   angle = (angle + 1) Mod 360
   TLine.draw(200, 200, 200 + Sin(angle) * 180, 200 + Cos(angle) * 180)
   Flip
Wend

Viel Spaß damit! Wink

MfG chaos
Projekte: Geolaria | aNemy
Webseite: chaosspace.de
  • Zuletzt bearbeitet von ChaosCoder am So, Apr 20, 2008 15:59, insgesamt einmal bearbeitet

amon

BeitragSo, Apr 20, 2008 15:42
Antworten mit Zitat
Benutzer-Profile anzeigen
Du kannst den Code auch mit Plot nochmal um fast 20% beschleunigen:

Du machst sehr viele gleiche Berechnungen innerhalb der Schleifen bzw. innerhalb des DrawPlot Aufrufes.

Du kannst die Berechnung des Alphawertes ausserhalb die Schleife verlagern, in ein Variable speichern - und mit dieser Variable innerhalb der Schleife arbeiten und deinem DrawPlot gleich den vorkalkulierten Alphawert mitgeben.

Tankbuster

BeitragMo, Apr 21, 2008 14:57
Antworten mit Zitat
Benutzer-Profile anzeigen
Anstatt PLOT kann man das auch per WritePixelFast machen. Dann halt immernur einen Pixel zeichnen. Das ist laut augenzeugen en bissl schneller ^.^ Wink
Twitter
Download Jewel Snake!
Windows|Android

ChaosCoder

BeitragMo, Apr 21, 2008 15:21
Antworten mit Zitat
Benutzer-Profile anzeigen
@amon: wie jetzte? versteh ich nicht, wo mach ich denn in den schleifen viele berechnungen?

@tankbuster: schöner versuch aber wir sind hier unter bmax, da gibbet kein WritePixelFast Wink
Projekte: Geolaria | aNemy
Webseite: chaosspace.de

BtbN

BeitragMo, Apr 21, 2008 16:36
Antworten mit Zitat
Benutzer-Profile anzeigen
Code: [AUSKLAPPEN]
SuperStrict

Framework BRL.Max2D
Import BRL.GLMax2D
Import BRL.PolledInput
Import PUB.OpenGL


SetGraphicsDriver(GlMax2DDriver())
Graphics 800,600,0,0


SetBlend(ALPHABLEND)

glEnable(GL_LINE_SMOOTH)
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST)

Repeat
   Cls

   If KeyHit(KEY_Q) Then glEnable(GL_LINE_SMOOTH)
   If KeyHit(KEY_W) Then glDisable(GL_LINE_SMOOTH)
   If KeyHit(KEY_A) Then glHint(GL_LINE_SMOOTH_HINT, GL_FASTEST)
   If KeyHit(KEY_S) Then glHint(GL_LINE_SMOOTH_HINT, GL_NICEST)
   If KeyHit(KEY_D) Then glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE)

   DrawLine(400,300,MouseX(),MouseY())

   Flip
Until KeyHit(KEY_ESCAPE) Or AppTerminate()


End

ChaosCoder

BeitragMo, Apr 21, 2008 17:33
Antworten mit Zitat
Benutzer-Profile anzeigen
mist Sad
naja, dann halt nich Laughing
Projekte: Geolaria | aNemy
Webseite: chaosspace.de

Tankbuster

BeitragMo, Apr 21, 2008 19:45
Antworten mit Zitat
Benutzer-Profile anzeigen
Zitat:
@tankbuster: schöner versuch aber wir sind hier unter bmax, da gibbet kein WritePixelFast Wink


*dumm aus der wäsche guck* G_G

Tut mir leid. Normalerweise lese ich nie im Max Forum, deshalb dachte ich, das ist Basic >.<
Twitter
Download Jewel Snake!
Windows|Android

amon

BeitragMo, Apr 21, 2008 21:59
Antworten mit Zitat
Benutzer-Profile anzeigen
amon hat Folgendes geschrieben:
Du kannst den Code auch mit Plot nochmal um fast 20% beschleunigen:

Du machst sehr viele gleiche Berechnungen innerhalb der Schleifen bzw. innerhalb des DrawPlot Aufrufes.

Du kannst die Berechnung des Alphawertes ausserhalb die Schleife verlagern, in ein Variable speichern - und mit dieser Variable innerhalb der Schleife arbeiten und deinem DrawPlot gleich den vorkalkulierten Alphawert mitgeben.


Stimmt, sorry für die Verwirrung - ich hab zu wenig genau geschaut, und eine Codezeile in deiner Hauptschleife übersehen - damit ist mein Ansatz obsolet geworden. Smile

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group