Transparenz

Für Fragen zu Grafik APIs wie DirectX und OpenGL sowie Shaderprogrammierung.
Antworten
TomCat
Beiträge: 10
Registriert: 02.03.2002, 10:29

Transparenz

Beitrag von TomCat » 23.03.2009, 15:41

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
Schnelle Autos !
Schnelle Frauen !
Schneller Code !

Benutzeravatar
Schrompf
Moderator
Beiträge: 3960
Registriert: 26.02.2009, 00:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: Transparenz

Beitrag von Schrompf » 23.03.2009, 15:44

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.
Häuptling von Dreamworlds. Baut an was Neuem. Hilft nebenbei nur höchst selten an der Open Asset Import Library mit.

Benutzeravatar
Aramis
Moderator
Beiträge: 1458
Registriert: 25.02.2009, 20:50
Echter Name: Alexander Gessler
Wohnort: 2016
Kontaktdaten:

Re: Transparenz

Beitrag von Aramis » 23.03.2009, 15:55

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.

Benutzeravatar
Krishty
Establishment
Beiträge: 7090
Registriert: 26.02.2009, 12:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Transparenz

Beitrag von Krishty » 23.03.2009, 15:56

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
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne

TomCat
Beiträge: 10
Registriert: 02.03.2002, 10:29

Re: Transparenz

Beitrag von TomCat » 23.03.2009, 16:12

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.
Schnelle Autos !
Schnelle Frauen !
Schneller Code !

Benutzeravatar
Aramis
Moderator
Beiträge: 1458
Registriert: 25.02.2009, 20:50
Echter Name: Alexander Gessler
Wohnort: 2016
Kontaktdaten:

Re: Transparenz

Beitrag von Aramis » 23.03.2009, 16:21

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.

TomCat
Beiträge: 10
Registriert: 02.03.2002, 10:29

Re: Transparenz

Beitrag von TomCat » 23.03.2009, 16:26

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)
Schnelle Autos !
Schnelle Frauen !
Schneller Code !

Benutzeravatar
Aramis
Moderator
Beiträge: 1458
Registriert: 25.02.2009, 20:50
Echter Name: Alexander Gessler
Wohnort: 2016
Kontaktdaten:

Re: Transparenz

Beitrag von Aramis » 23.03.2009, 17:04

Vielleicht hilft dir das hier weiter.

Jörg
Establishment
Beiträge: 296
Registriert: 03.12.2005, 14:06
Wohnort: Trondheim
Kontaktdaten:

Re: Transparenz

Beitrag von Jörg » 24.03.2009, 09:39

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)

Benutzeravatar
Zudomon
Establishment
Beiträge: 2127
Registriert: 25.03.2009, 08:20
Kontaktdaten:

Re: Transparenz

Beitrag von Zudomon » 26.03.2009, 00:31

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...

Benutzeravatar
Schrompf
Moderator
Beiträge: 3960
Registriert: 26.02.2009, 00:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: Transparenz

Beitrag von Schrompf » 26.03.2009, 01:36

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.
Häuptling von Dreamworlds. Baut an was Neuem. Hilft nebenbei nur höchst selten an der Open Asset Import Library mit.

Benutzeravatar
Zudomon
Establishment
Beiträge: 2127
Registriert: 25.03.2009, 08:20
Kontaktdaten:

Re: Transparenz

Beitrag von Zudomon » 26.03.2009, 01:53

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.

TomCat
Beiträge: 10
Registriert: 02.03.2002, 10:29

Re: Transparenz

Beitrag von TomCat » 26.03.2009, 19:07

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.
Schnelle Autos !
Schnelle Frauen !
Schneller Code !

Jörg
Establishment
Beiträge: 296
Registriert: 03.12.2005, 14:06
Wohnort: Trondheim
Kontaktdaten:

Re: Transparenz

Beitrag von Jörg » 26.03.2009, 19:19

Bezueglich clock-cycles findest du hier noch was: http://www.gamedev.net/reference/articl ... cle817.asp

kkrahl
Beiträge: 56
Registriert: 20.10.2008, 13:41

Re: Transparenz

Beitrag von kkrahl » 27.03.2009, 13:48

Mal ne blöde Frage von einem Anfänger. Warum benutz man hier kein Blending?

Karl

Benutzeravatar
Krishty
Establishment
Beiträge: 7090
Registriert: 26.02.2009, 12:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Transparenz

Beitrag von Krishty » 28.03.2009, 17:39

Wie meinst du das? Er führt ja Alphablending durch, nur eben selbstprogrammiertes.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne

Antworten