Seite 1 von 1

Transparenz

Verfasst: 23.03.2009, 14:41
von TomCat
Hi,

ich will Pixel transparent ausgeben, d.h. ich muss einen RGB Pixel mit dem Hintergrundpixel verrechnen. Das Ganze funktioniert so, dass der Rotwert des Vordergrundpixels mit dem Rotwert des Hintergrundpixels in Abhängigkeit der Transparenz verrechnet wird.

Beispiel:
bei Transparenz von 0,3 wird der Rotwert des Vordergrundpixels mit 0,3 multipliziert und der Rotwert des Hintergrundpixels mit 1-0,3 als 0,7. dann werden beide Ergebnisse addiert und man erhält den auszugebenden Rotwert. Das ganz muss dann für Grün und Blau ebenfalls gemacht werden.

Mein Problem ist, dass ich 6 Multiplikationen machen muss um eine einzigen Pixel zu erhalten. Dann noch einen Schwung Maskierungen um die Farbwerte aus den Registern zu extrahieren. Das ist einfach saulangsam.

Weiß jemand einen schnellen Algo dafür?

Die RGB-werte der Vordergrundfarbe und Hintergrundfarbe liegen bereits in zwei 32-Bit Registern vor. In EAX und EBX.

ciao,
TomCat

Re: Transparenz

Verfasst: 23.03.2009, 14:44
von Schrompf
Nach meinem Wissen gibt es dafür keinen magischen Trick, der mit weniger auskommt. Allerdings ist mir die Operation auch nicht als so langsam bekannt... auf einem aktuellen Singlecore solltest Du damit Pixel im mehrstelligen Millionenbereich pro Sekunde verrechnen können. Zeig doch mal den Code, der Dir aktuell zu langsam ist.

Re: Transparenz

Verfasst: 23.03.2009, 14:55
von Aramis
Vielleicht hilft folgende Umformung:

Code: Alles auswählen

F = S*a + D*(1-a)
F = S*a + D - D*a
F = a*(S-D)+D 
Somit verringert sich die Zahl der Multiplikationen auf 3.

Re: Transparenz

Verfasst: 23.03.2009, 14:56
von Krishty
Wenn man die Pixel erst von 8-bpp-Integern zu 32-bpp-Floats und die Ergebnisse danach wieder zurück konvertieren muss, wird das ganz schnell langsam …

Ich habe beim Googlen das hier gefunden, vielleicht hilft es dir ja.

Alternativ könnte das auch beschleunigt werden, indem alles bereits als Float×4 vorliegt und du SSE samt Prefetching nutzt … würde aber eine hübsche Intrinsic-Schweinerei und ist nur in begrenzten Anwendungsfällen sinnvoll, geschweige denn dem Aufwand angemessen.

Gruß, Ky

Re: Transparenz

Verfasst: 23.03.2009, 15:12
von TomCat
ok, mal code:

vordergrund und hintergrundfarbe liegen in EDI und ESI vor
tranparenzwerte gehen bei mir von integer 0-255. Damit muss ich am ende nicht auch noch dividieren.


mov eax,esi
and eax,11111111b ;um nur die letzten 8 bit zu erhalten fuer die Rotwertkalulation
mul foregroundmultiplier
mov ebx,eax

mov eax,edi
and eax,11111111b ;um nur die letzten 8 bit zu erhalten fuer die Rotwertkalulation
mul backgroundmultiplikator

add eax,ebx
shr eax,8 ;division durch 256
//damit ist der rotwert in eax
mov rotwert,eax

....
das ganze jetzt noch für die anderen beiden Farben und die Ergebnisse in das 32-bit Zielregister einmaskieren. Soll ich das auch noch zeigen. Ist ja jetzt schon elends viel code.

Re: Transparenz

Verfasst: 23.03.2009, 15:21
von Aramis
Mit meiner obigen Umformung dürfte es so aussehen:

Code: Alles auswählen

mov eax,esi                ; Vordergrundfarbe
and eax,11111111b 

mov ebx,edi                ; Hintergrundfarbe
and ebx,11111111b 

sub eax,ebx                
mul alpha
shr eax,8
add eax,edi                ; Finaler Rotwert nun in eax
(keine Garantie drauf, ich hab lange nichts mehr mit x86-Assembler zu tun gehabt)
Ansonsten würde ich an deiner Stelle aber auch direkt mit fp32-Fließkommatupeln arbeiten. SSE(x) dürfte die ganze Sache nochmals deutlich beschleunigen.

Re: Transparenz

Verfasst: 23.03.2009, 15:26
von TomCat
Alexander Gessler hat geschrieben:Mit meiner obigen Umformung dürfte es so aussehen:

Code: Alles auswählen

mov eax,esi                ; Vordergrundfarbe
and eax,11111111b 

mov ebx,edi                ; Hintergrundfarbe
and ebx,11111111b 

sub eax,ebx              //das hier geht nicht !!!  sobald eax <= ebx ist es immer Null !!    
mul alpha
shr eax,8
add eax,edi                ; Finaler Rotwert nun in eax
(keine Garantie drauf, ich hab lange nichts mehr mit x86-Assembler zu tun gehabt)

Re: Transparenz

Verfasst: 23.03.2009, 16:04
von Aramis
Vielleicht hilft dir das hier weiter.

Re: Transparenz

Verfasst: 24.03.2009, 08:39
von Jörg
Gut dass auf den Assemblercode keine Garantie gegeben wurde.

1. Die Subtraktion ist schon in Ordnung, da wird nichts auf 0 gesetzt, ausser eax==ebx
2. Statt mul muss imul verwendet werden, da mit vorzeichenbehafteten Zahlen multipliziert wird
3. imul eax,alpha , sonst wird edx gekillt (2-Operanden-Form)

Der Link zum double-blend ist zu empfehlen, eventuell findest du noch etwas unter Software-MMX dazu (so
haben wir das zu Pentium-90-Zeiten genannt, als MMX nur auf den High-End-Systemen verfuegbar war)

Re: Transparenz

Verfasst: 25.03.2009, 23:31
von Zudomon
Ich hab mal aus Spass versucht, eine andere Variante zu probieren. Wie schnell oder langsam das bezüglich anderer implementierungen ist, weiß ich nicht.
Meine Lösung dafür ist eine 3 Dimensionale Lookuptabelle... wobei die 3 Bytewerte als Index benutzt werden... während die Lookuptabelle bei mir etwa ne halbe Sekunde zum erstellen braucht ( nicht optimiert, einfach primitiv erstellt ), kann ich anschließend etwa 148 Millionen Werte berechnen... wenn ich mich nicht irre, wären das etwa 102 FPS bei 800x600 und 32Bit :D

Mit Multithreading wäre da dann natürlich noch mehr drin...

Re: Transparenz

Verfasst: 26.03.2009, 00:36
von Schrompf
Naja... ohne Deine Kreativität in Zweifel zu ziehen: Lookup-Tables größer als der First-Level-Cache sind heutzutage eine Garantie dafür, Performance zu verlieren. Mit 16MB Lookup-Table bist Du selbst jenseits des Third-Level-Caches - ich behaupte mal, die ursprüngliche Lösung dürfte um einiges schneller sein.

Re: Transparenz

Verfasst: 26.03.2009, 00:53
von Zudomon
Schrompf hat geschrieben:Naja... ohne Deine Kreativität in Zweifel zu ziehen: Lookup-Tables größer als der First-Level-Cache sind heutzutage eine Garantie dafür, Performance zu verlieren. Mit 16MB Lookup-Table bist Du selbst jenseits des Third-Level-Caches - ich behaupte mal, die ursprüngliche Lösung dürfte um einiges schneller sein.
War ja nur ne Idee... aber du hast Recht, Geschwindigkeitsmäßig wird das dann um einiges langsamer sein.

Die Frage ist auch, in wie weit das überhaupt über Software laufen muss. Vielleicht wäre ja auch eine Lösung über CUDA denkbar.

Re: Transparenz

Verfasst: 26.03.2009, 18:07
von TomCat
Hi,

naja bei einer LUT muss man halt die Werte ausm Speicher lesen. Auch nicht grad fix. Noch dazu wenns Cache-misses erzeugt. Also ich hab das mal optimiert. Und zwar so, dass fast alles über die Standardregister läuft. Also das Ganze dauert dann etwa 60 Takte. Zumindest auf einem lahmen Celeron 1800. Der braucht alleine für ne integer multiplikation ca. 5 Takte. Und da sind ja leider 6 davon im code. Mit dem kann ich für die Anwendung aber einigermassen leben.

ciao,
TomCat, dem immer alles zu langsam ist.

Re: Transparenz

Verfasst: 26.03.2009, 18:19
von Jörg
Bezueglich clock-cycles findest du hier noch was: http://www.gamedev.net/reference/articl ... cle817.asp

Re: Transparenz

Verfasst: 27.03.2009, 12:48
von kkrahl
Mal ne blöde Frage von einem Anfänger. Warum benutz man hier kein Blending?

Karl

Re: Transparenz

Verfasst: 28.03.2009, 16:39
von Krishty
Wie meinst du das? Er führt ja Alphablending durch, nur eben selbstprogrammiertes.