Transparenz
Transparenz
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
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
Schnelle Autos !
Schnelle Frauen !
Schneller Code !
Schnelle Frauen !
Schneller Code !
- Schrompf
- Moderator
- Beiträge: 5114
- Registriert: 25.02.2009, 23:44
- Benutzertext: Lernt nur selten dazu
- Echter Name: Thomas
- Wohnort: Dresden
- Kontaktdaten:
Re: Transparenz
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.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
- Aramis
- Moderator
- Beiträge: 1458
- Registriert: 25.02.2009, 19:50
- Echter Name: Alexander Gessler
- Wohnort: 2016
- Kontaktdaten:
Re: Transparenz
Vielleicht hilft folgende Umformung:
Somit verringert sich die Zahl der Multiplikationen auf 3.
Code: Alles auswählen
F = S*a + D*(1-a)
F = S*a + D - D*a
F = a*(S-D)+D
- Krishty
- Establishment
- Beiträge: 8336
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: Transparenz
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
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
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.
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.
Schnelle Autos !
Schnelle Frauen !
Schneller Code !
Schnelle Frauen !
Schneller Code !
- Aramis
- Moderator
- Beiträge: 1458
- Registriert: 25.02.2009, 19:50
- Echter Name: Alexander Gessler
- Wohnort: 2016
- Kontaktdaten:
Re: Transparenz
Mit meiner obigen Umformung dürfte es so aussehen:
(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.
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
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
Alexander Gessler hat geschrieben:Mit meiner obigen Umformung dürfte es so aussehen:
(keine Garantie drauf, ich hab lange nichts mehr mit x86-Assembler zu tun gehabt)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
Schnelle Autos !
Schnelle Frauen !
Schneller Code !
Schnelle Frauen !
Schneller Code !
- Aramis
- Moderator
- Beiträge: 1458
- Registriert: 25.02.2009, 19:50
- Echter Name: Alexander Gessler
- Wohnort: 2016
- Kontaktdaten:
Re: Transparenz
Vielleicht hilft dir das hier weiter.
Re: Transparenz
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)
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
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...
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...
- Schrompf
- Moderator
- Beiträge: 5114
- Registriert: 25.02.2009, 23:44
- Benutzertext: Lernt nur selten dazu
- Echter Name: Thomas
- Wohnort: Dresden
- Kontaktdaten:
Re: Transparenz
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.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Re: Transparenz
War ja nur ne Idee... aber du hast Recht, Geschwindigkeitsmäßig wird das dann um einiges langsamer sein.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.
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
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.
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.
Schnelle Autos !
Schnelle Frauen !
Schneller Code !
Schnelle Frauen !
Schneller Code !
Re: Transparenz
Bezueglich clock-cycles findest du hier noch was: http://www.gamedev.net/reference/articl ... cle817.asp
Re: Transparenz
Mal ne blöde Frage von einem Anfänger. Warum benutz man hier kein Blending?
Karl
Karl
- Krishty
- Establishment
- Beiträge: 8336
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: Transparenz
Wie meinst du das? Er führt ja Alphablending durch, nur eben selbstprogrammiertes.