Seite 1 von 2

Antialiased Drawing

Verfasst: 20.03.2012 17:07
von Lambda
Kennt jemand einen Filter dafür? Gerade RoundedBox macht sehr unschöne Ränder. Muss nicht gerade eine Lösung für Spiele sein. (CanvasGadget)

lg :D

Re: Antialiased Drawing

Verfasst: 20.03.2012 17:40
von NicTheQuick
Vielleicht gDrawing?

Re: Antialiased Drawing

Verfasst: 20.03.2012 17:56
von Lambda
Ein Filter wäre mir etwas lieber als der GDI extra Kram ^^

Re: Antialiased Drawing

Verfasst: 20.03.2012 19:46
von STARGÅTE
Dafür kannst du den Filter von hier nutzen:
RoundImageFilterCallback

Den Filter kannst du aber nur auf eine Box anwenden.

Für Lines und Ellipsen wäre ein solcher Filter einfach zu langsam.
Dann lieber GDI+

Re: Antialiased Drawing

Verfasst: 20.03.2012 21:12
von Lambda
Und er funktioniert auch bei Verwendung von Gradianten? Die Box ist nämlich nichtmehr sichtbar wenn ich es verwende.

Re: Antialiased Drawing

Verfasst: 20.03.2012 23:50
von STARGÅTE
Klar geht das.

Der CustomFilterCallback macht nix anderes, als die Farbe die theoretisch gezeichnet wird und die Farbe die der Untergrund hat, an den Callback zu geben. Dort kannst du dann das "verhalten" (im Normalfall AlphaBlend(SourceColor, DestinationColor)) ändern.

Hier ein Beispiel für ein LinearGradient mit einer Box die aber dann zum Kreis gefiltert wird, welcher 25 Pixel Unschärfe-Rand hat.

Code: Alles auswählen


Enumeration
	#Window
	#Gadget
EndEnumeration


Procedure FilterCallback(X.i, Y.i, SourceColor, DestinationColor)
	; X, Y - Koordinaten
	; SourceColor - Farbe die gezeichnet werden soll (vom Gradien oder die angabe in Box)
	; DestinationColor - Untergrundfarbe
	Protected Distance.f = Sqr(Pow(X-OutputWidth()/2,2)+Pow(Y-OutputHeight()/2,2))
	Protected Alpha.a
	If Distance > 125
		SourceColor = $00000000
	ElseIf Distance > 100
		Alpha = Alpha(SourceColor)*(125-Distance)/25
		SourceColor & $00FFFFFF | Alpha << 24
	EndIf
	ProcedureReturn AlphaBlend(SourceColor, DestinationColor)
EndProcedure


OpenWindow(#Window, 0, 0, 256, 256, "Beispiel", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
CanvasGadget(#Gadget, 0, 0, WindowWidth(#Window), WindowHeight(#Window))


If StartDrawing(CanvasOutput(#Gadget))
	Box(0, 0, OutputWidth()/2, OutputHeight()/2, $000000)
	Box(OutputWidth()/2, OutputHeight()/2, OutputWidth()/2, OutputHeight()/2, $000000)
	DrawingMode(#PB_2DDrawing_Gradient|#PB_2DDrawing_AlphaBlend|#PB_2DDrawing_CustomFilter)
	CustomFilterCallback(@FilterCallback())
	LinearGradient(0, 0, OutputWidth()-1, OutputHeight()-1)
		GradientColor(0.0, $FFFF8000)
		GradientColor(1.0, $FF00FF80)
	Box(0, 0, OutputWidth(), OutputHeight())
	StopDrawing()
EndIf


Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
Bild

Re: Antialiased Drawing

Verfasst: 21.03.2012 00:12
von Lambda
Absolut perfektes Beispiel. :allright:

Nur leider versteh ich die Gebrauchsweise davon nicht richtig. Wie kann ich zb den radius so minimieren das daraus nur weiche kanten werden. Oder wenn ich für die nächste Form eine ganz andere Farbe verwende?

Re: Antialiased Drawing

Verfasst: 21.03.2012 00:36
von STARGÅTE
Hier mal etwas detailierter was passiert, wenn du ein CustomFilterCallback benutzt:
  • Nehmen wir mal an, das gesamte Bild (200 x 200 Pixel) ist vorher Rot.
  • Du rufst nun (nach CustomFilterCallback) den Befehl Box(50, 50, 100, 100, RGBA(0,0,255,128))
  • Ohne den Callback würde nun eine Box mit halbtransparentem Blau auf das Rot gezeichnet werden.
  • Durch den Filter passiert nun folgendes:
  • Jeder Pixel, der durch Box() gezeinet werden würde, wird mit seinen Koordinaten, der Untergrundfarbe (Rot) und der Zeichnen-Farbe (halbtransparentes Blau) an den Filter gegeben.
  • Im Filter errechnen ich nun zB den Abstand des Pixels zum Bildzentrum (für Kreis).
  • Ist der Abstand > 50 Pixel, wird der Pixel nicht gezeichnet.
  • ist der Abstand (Float) zwischen 49 und 50 Pixel (normale Kantenglättung), muss er "geglättet" werden, also ändere ich den Alpha-Wert der Zeichenfarbe, um den Pixel abzuschwächen.
  • Ist der Abstand <= 99 Pixel, wird der Pixel normal gezeichnet.

Code: Alles auswählen


Enumeration
	#Window
	#Gadget
EndEnumeration

Global Radius.f = 50


Procedure FilterCallback(X.i, Y.i, SourceColor, DestinationColor)
	Protected Distance.f = Sqr(Pow(X-OutputWidth()/2,2)+Pow(Y-OutputHeight()/2,2))
	Protected Alpha.a
	If Distance > Radius
		SourceColor = $00000000
	ElseIf Distance > Radius-1
		Alpha = Alpha(SourceColor)*(Radius-Distance)
		SourceColor & $00FFFFFF | Alpha << 24
	EndIf
	ProcedureReturn AlphaBlend(SourceColor, DestinationColor)
EndProcedure


OpenWindow(#Window, 0, 0, 200, 200, "Beispiel", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
CanvasGadget(#Gadget, 0, 0, WindowWidth(#Window), WindowHeight(#Window))


If StartDrawing(CanvasOutput(#Gadget))
	Box(0, 0, 200, 200, RGBA(255,0,0,255))
	DrawingMode(#PB_2DDrawing_AlphaBlend|#PB_2DDrawing_CustomFilter)
	CustomFilterCallback(@FilterCallback())
	Box(50, 50, 100, 100, RGBA(0,0,255,128))
	StopDrawing()
EndIf

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
Das heißt, was genau der Filter machen soll, muss du selber schreiben.
Was bei einem Kreis noch einfach ist (Glättung) ist bei einer Linie schon schwerer.
Das heißt, herauszufinden, wie der zu zeichnende Pixel verändert werden muss. (mehr Berechungen).

Re: Antialiased Drawing

Verfasst: 21.03.2012 03:51
von Lambda
Schön erklärt :allright: mal sehn was sich so zusammenklopfen lässt.

Etwas offtopic aber ich möchte dazu kein extra Thread eröffnen. Wenn ich eine "Ribbon" ähnliche Toolbar programmiere ist das rechtlich ok? Es wäre vom funktionellem wie ein Panel mit dem man zwischen Toolbars schalten kann, was aber ähnlich aussieht wie eine Ribbonleiste.

Re: Antialiased Drawing

Verfasst: 21.03.2012 14:34
von bobobo
ämm -- Bilder muss man gar nicht malen zum Zeitpunkt wenn man sie braucht sondern kann
die auch vorab basteln und dann passend einbauen. Dann sollte das mit dem Antialiasing eigent-
lich gar kein Problem mehr sein.

Das sollte auch energetisch günstiger sein :)