amiga-news ENGLISH VERSION
.
Links| Forum| Kommentare| News melden
.
Chat| Umfragen| Newsticker| Archiv
.

amiga-news.de Forum > Programmierung > schnelles ein/ausblenden bei 16bit [ - Suche - Neue Beiträge - Registrieren - Login - ]

-1- [ - Beitrag schreiben - ]

29.11.2002, 11:46 Uhr

Micha1701
Posts: 938
Nutzer
Hi!

Weiß jemand von Euch wie man in C auf einem 800x600 Screen mit 16bit schnell ein und ausblenden kann? Alles was ich bisher versucht habe war einfach viel zu langsam...


--
:boing: Micha :boing:

Look at my HP: http://www.lanser-online.de.vu





[ Dieser Beitrag wurde von Micha1701 am 29.11.2002 editiert. ]

[ - Antworten - Zitieren - Direktlink - ]

29.11.2002, 14:16 Uhr

tokai
Posts: 1071
Nutzer
also so mit herkömmlichen Mitteln wirst du da wohl kein Glück haben. Ich habe letztens etwas ähnliches probiert, aber so richtig die ideale Lösung war das auch nicht. Und desto höher die Auflösung desto langsamer wirds. Aber Warp3D soll sowas u.a. können.

Aber vielleicht findest du ja hier eine Lösung:
http://www.2dgame-tutorial.com/Tutorial_2.htm


-> bei Alphablending.


Letztenendes wirst du nicht darum herumkommen, deinen RGB-Buffer per Hand zu "Faden". D.h. einen Loop, der Stück für Stück jeden Pixel ein- bzw. ausblendet (zu einer entsprechenden Farbe -> Alphabuffer) und danach jeweils den ganzen Buffer per WritePixelArray in's Fenster zu "blitten". Das war natürlich nur eine ganz grobe Erklärung. :)
--
http://www.christianrosentreter.de

[ Dieser Beitrag wurde von tokai am 29.11.2002 editiert. ]

[ - Antworten - Zitieren - Direktlink - ]

29.11.2002, 15:06 Uhr

Micha1701
Posts: 938
Nutzer
Hmm...

Habs so versucht (also mit den Buffern) aber es ist halt doch ziemlich langsam und sieht entsprechend beschissen aus...

Mit ReadRGBPixel() / WriteRGBPixel hatte ich sogar das stolze Ergebnis von schlappen 6 Minuten zum faden (in 5 Schritten)... Na spitze... :lach:
--
:boing: Micha :boing:

Look at my HP: http://www.lanser-online.de.vu



[ - Antworten - Zitieren - Direktlink - ]

30.11.2002, 19:57 Uhr

AC-FoX
Posts: 35
Nutzer
Hmm, also WriteRGBPixel() dürfte nicht so schnell sein, wie ein eigener Code, der genau auf deine Bedürfnisse zugeschnitten ist.
Ich bevorzuge bei zeitkritischen Operationen direkten Zugriff auf den Grafikspeicher. Das Problem dabei ist, daß der Grafikspeicher in verschiedenen Formaten vorliegen kann.
Wenn ich mal bei CGX nachschaue, finde ich da die Formate RGB15, BGR15, RGB15PC, BGR15PC und das gleiche für 16bit.
Wenn du dich auf 16bit beschränkst, wrden immer noch 4 verschiedene, aber fast identische Kernroutinen übrig bleiben.
Die Idee mit Buffern ist an sich schon sehr gut. Nur würde ich am Anfang den Buffer vom Screen lesen, und zwar indem ich den Inhalt direkt reinkopiere (auf ScreenWidth und BytesPerRow achten).
Dann würde ich von diesen Daten ausgehend für jedes Fade-Bild Abstufungen berechnen.
1. Daten aus Buffer lesen
2. Abhängig von Format zerlegen (RGB16 und BGR16 sollte gleich sein, da ja alle Komponenten gleichmässig abgesenkt werden)
3. Abhängig vom Fade-Counter (1, 2 oder 3. Durchgang?) die Werte vermindern
4. Daten in Grafikspeicher schreiben
Das Ganze könnte bei schöner Programmierung (bestenfalls in Assembler :) fast genauso schnell sein wie Copy-Speed.
Beachte, daß das Ergebnis des fadens nicht zurück in den Buffer, sondern nur in den Grafikspeicher geschrieben wird.
Beim Zerlegen der Daten in die Einzelteile braucht man ein OR und ein Shift. Zum Berechnen reicht ein Minus, bzw ein Shift. Minus braucht leider noch eine Null-Abfrage, sonst würde man ja negative Werte erzeugen.
Wieder mit Shift und OR zusammenbasteln, und rausschreiben.
Evtl kann man gleich zwei WORDs zusammen in einer LONG Operation berechnen, indem man geschickt ORs einsetzt. Bei Assembler könnte man auch mehrere Register mit Daten vollladen und bearbeiten, um weniger Load/Store Verluste in den Taktzyklen hat. Alle zugleich laden, nacheinander berarbeiten, und sofort, wenn man ein Ergebnis hat, das Register in den Speicher schreiben.
Aber das größte Problem dürfte immernoch die Geschwindigkeit sein. 800x600x2 Bytes macht lockere 937,5 KB. Grafikdurchsatz zur BVision mit LONG Write ist IIRC so bei 12 MB/sek. Das Maximum würde da bei 13 fps liegen, vorrausgesetzt, der RAM-Speed stimmt.

Viel Spaß,
FoX

[ - Antworten - Zitieren - Direktlink - ]

02.12.2002, 07:11 Uhr

Micha1701
Posts: 938
Nutzer
Tja, hab ich so probiert (allerdings nur in C und nicht in ASM)...

Leider immernoch zu lahm... Das shiften ist wohl zu zeitaufwendig für unsere 68k CPUs.... Naja, dann lass ichs halt bleiben... ;(
--
:boing: Micha :boing:

Look at my HP: http://www.lanser-online.de.vu



[ - Antworten - Zitieren - Direktlink - ]

02.12.2002, 09:52 Uhr

tokai
Posts: 1071
Nutzer
Zitat:
Original von Micha1701:
Hmm...

Habs so versucht (also mit den Buffern) aber es ist halt doch ziemlich langsam und sieht entsprechend beschissen aus...

Mit ReadRGBPixel() / WriteRGBPixel hatte ich sogar das stolze Ergebnis von schlappen 6 Minuten zum faden (in 5 Schritten)... Na spitze... :lach:


hmmm.... dann hast du ja pro Pixel noch zwei zusätzliche Funktionsaufrufe, wo Daten zwischen den Registern/ bzw. im Stack hinundhergeschoben werden müssen. Das muss ja langsam werden. :)

Wenn du nur eine Funktion hast (die wenn mögl nur mit Longwords im Speicher hantieren muss, die alles auf einmal erledigt müsste es theoretisch mit 4/5 frames (grob im Kopf überschlagen) pro Sekunde zu schaffen sein (mit einem 060er :).
--
http://www.christianrosentreter.de

[ - Antworten - Zitieren - Direktlink - ]

02.12.2002, 10:08 Uhr

Micha1701
Posts: 938
Nutzer
Mein letzter Versuch sah so aus:

Bitmap in Speicher kopiert und in RGB16 umgewandelt.

in einer Schleife die einzelnen shorts (also Pixel) dunkler gemacht (per Byteshifting) und in Bitmap geschrieben. Danach die Bitmap in das Screen Pixelformat konvertiert.

Das ganze dauerte auf einem 68040/25 knapp 8 Sekunden für 4 Stufen...

Eindeutig zu lahm...

Ich denke das Problem dabei ist auch die Konvertierung der Pixelformate. Je nach Format benötigt man bis zu 3 Shifts mit 4 ORs...



--
:boing: Micha :boing:

Look at my HP: http://www.lanser-online.de.vu



[ - Antworten - Zitieren - Direktlink - ]

02.12.2002, 10:39 Uhr

tokai
Posts: 1071
Nutzer
Zitat:
Original von Micha1701:
Mein letzter Versuch sah so aus:

Bitmap in Speicher kopiert und in RGB16 umgewandelt.

in einer Schleife die einzelnen shorts (also Pixel) dunkler gemacht (per Byteshifting) und in Bitmap geschrieben. Danach die Bitmap in das Screen Pixelformat konvertiert.

Das ganze dauerte auf einem 68040/25 knapp 8 Sekunden für 4 Stufen...

Eindeutig zu lahm...

Ich denke das Problem dabei ist auch die Konvertierung der Pixelformate. Je nach Format benötigt man bis zu 3 Shifts mit 4 ORs...


hmmm... wieso musst du erst konvertieren?




--
http://www.christianrosentreter.de

[ - Antworten - Zitieren - Direktlink - ]

02.12.2002, 11:06 Uhr

Micha1701
Posts: 938
Nutzer
Die Bitmap liegt doch auf der Grafikkarte in dem Format, mit der die Karte arbeitet (z.B. BGR16PC oder eines der anderen 7 Formate).

Die Faderoutine arbeitet aber mit RGB16 (8 unterschiedliche wäre zwar möglich aber...). Daher muß die KartenBitmap erstmal nach RGB16 konvertiert werden. Nur einmal am Anfang der Routine. Danach wird dann die geänderten RGB16 Pixel in die Karte geschrieben. Und dann die KartenBitmap wieder in ihr notwendiges Format zum anzeigen konvertiert...

Hmm... vielleicht erstellich mal alle 8 Routinen, nur mal zum sehen wie schnell das ganze dann ist... Auch wenn ich denke das es nicht der brüller sein wird...

--
:boing: Micha :boing:

Look at my HP: http://www.lanser-online.de.vu



[ - Antworten - Zitieren - Direktlink - ]

02.12.2002, 11:11 Uhr

thomas
Posts: 7678
Nutzer

Also ich habe am WE was ausprobiert, was auch sehr langsam ist, aber immerhin 4 fps gebracht hat:

scrbm = AllocBitMap (w,h,24,BMF_SPECIALFMT|SHIFT_PIXFMT(PIXFMT_RGB24))
tmpbm = AllocBitMap (w,h,24,BMF_SPECIALFMT|SHIFT_PIXFMT(PIXFMT_RGB24))
BltBitMap (scr->RastPort.BitMap,scrbm)

Dann für jede Stufe:
LockBitMap(scrbm)
LockBitMap(tmpbm)

dann per Hand die Daten von scrbm nach tmpbm mit Umrechnen der Helligkeit

UnLockBitMap(tmpbm)
UnLockBitMap(srcbm)
und BltBitMap (tmpbm,scr->RastPort.BitMap)

Die Konvertierung 16 -> 24 Bit hat CGX übernommen, war auch schnell genug. Die Umrechnung der Helligkeit hat am längsten gedauert. Wenn man die Bilder vorher berechnet und dann nur noch BltBitMap machen muß, könnte es schnell genug werden.

Gruß Thomas

--
Email: thomas-rapp@web.de
Home: home.t-online.de/home/thomas-rapp/

[ - Antworten - Zitieren - Direktlink - ]

02.12.2002, 13:14 Uhr

Azrael
Posts: 41
Nutzer
Zitat:
Original von Micha1701:

Das ganze dauerte auf einem 68040/25 knapp 8 Sekunden für 4 Stufen...

Eindeutig zu lahm...

Ich denke das Problem dabei ist auch die Konvertierung der Pixelformate. Je nach Format benötigt man bis zu 3 Shifts mit 4 ORs...


Am Shiften und ORen liegt's garantiert nicht. Wenn Du das schlau anstellst, würde das Bild selbst mit 2 Shifts und einem OR immer noch fast mit Kopiergeschwindigkeit geblendet werden.

Und wenn Du den hochoptimiertesten ASM verwendest, ist der 040/25 schlicht und einfach zu lahm. Da kannst Du machen, was Du willst. 800x600 ist schlicht und einfach ZU viel für den 040. Die schnellsten Grafikkarten am Amiga (außer die PCI-basierten) schaffen in der Praxis in solch einer Auflösung nicht mehr als 12-13 Full-Screen-Updates. Und dazu kommt noch die Konvertierung und Umrechnung. Soviel RAM-Durchsatz wie da nötig wäre, kann der 040er nicht einmal aufbringen.

Mein Tipp für maximale Geschwindikeit:
Saug Dir die render.library (oder so ähnlich) oder die ChunkyPPC.library (wurde z.b. auch von HereticII benutzt, und ja, trotz Ihres Namens funktioniert die auch auf 68k), die beiden übernehmen mit hochoptimierten Routinen alle Konvertierungen von Bildformaten. Alles was Du noch brauchst, ist ein RAM-Buffer in dem roh Dein Bild liegt. In der Library gibt es dann eine Funktion, die Deinen Buffer auf dem Screen anzeigt und sich selbst kümmert, welches Format das Ziel hat.

Dann probierst Du ein wenig herum und... schneller wird's NICHT.

Bye, Stefan.

--
Dreamworlds Development - http://www.dreamworlds.de

[ - Antworten - Zitieren - Direktlink - ]

02.12.2002, 15:14 Uhr

AC-FoX
Posts: 35
Nutzer
Ich hab hier mal ne Idee zu einer Abdunklung auf Shiftbasis:

//CODE Anfang
...
LONG data1;
LONG data2;
LONG data3;
LONG data4;
WORD *tmpbm;
WORD *scrbm;
LONG i;
LONG w, h;
LONG mask;
BYTE shiftcount; //müßte übergeben werden, als Durchlaufzähler
...
w=800;
h=600;

i=shiftcount;
mask=-1; //alle bits auf 1 setzen
while(i)
{
mask>>=1;
mask&=0x7bef7bef;
i--;
}

//schleife über Höhe, Pointer auf tmpbm und scrbm setzen
i=(w/8); //bzw (w>>3);
while(i)
{
data1=*(LONG*)tmpbm++; //rumcasten in C und Postinkrement...
data2=*(LONG*)tmpbm++;
data3=*(LONG*)tmpbm++;
data4=*(LONG*)tmpbm++;

data1>>=shiftcount;
data1&=mask;
*(LONG*)scrbm=data1;
scrbm+=2; //tja, ähm pointerarithmetik in C, der achtet auf BYTE, WORD und LONG, komisches Ding :)

...//gleiches für data2,3,4

i--;
}
//close schleife über höhe
...
//CODE Ende

Hierbei muß man pro LONG (also zwei Pixel) nur einmal shiften, und ein AND anbringen. Das AND 0x7bef7bef ist binär 2x0111101111101111. Es maskiert also das nach unten geshiftete Bit der jeweiligen Farbanteile weg. Je nach Durchlaufzähler wird also die mask weniger Einsen enthalten und mehr geshiftete Bits wegmaskieren.
Der Code funktioniert für Width mit mindestens Modulo 8, das paßt ja ziemlich gut für 800 :)
Außerdem kann man gleichzeitig RGB16 und BGR16 verarbeiten. Für RGB16_PC und BGR16_PC müßte man den gleichen Code nochmal machen, und noch ein LSB-MSB Switch machen:
data=(((data << 24) & 0xff000000))| ((data << 8) & 0x00ff0000) | ((data >> 8) & 0x0000ff00) |((data >> 24) & 0x000000ff));
nach dem Laden des Wertes aus der tmpbm und vor dem speichern in die scrbm machen. Alternativ geht auch ein
rotl.w #8,d1
swap d1
rotl.w #8,d1
wenn man das in C hinbekommt ;)

Hat noch jemand ne schnellere Idee? Evtl kann man noch was am Preload der datax was machen. Ein 040 ist ja keine superskalare CPU. Muß eben der Compiler etwas optimieren ;)
Der Code ist auch nur rein hypothetisch, hab ihn nicht ausprobiert - typische Mittagspausen-Beschäftigung...

Gruß,
FoX

[ Dieser Beitrag wurde von AC-FoX am 02.12.2002 editiert. ]

[ - Antworten - Zitieren - Direktlink - ]

02.12.2002, 15:46 Uhr

AC-FoX
Posts: 35
Nutzer
Also meine tmpbm und scrbm sind nicht auf die Weise angelegt, wie es Thomas gemacht hat. tmpbm ist mit AllocVec(800*600*2, MEMF_ANY); angelegt, und scrmb über AllocBitMap() mit dem gleichen BitMap-Format wie die Screen-BitMap (scrbm != Datenanfang, nicht vergessen). Ganz mutige können auch direkt die Screen-BitMap locken und sie gleich als Ziel des Algorithmus angeben. Dann wird aber ein sichtbarer Durchlauf entstehen, da der RasterBeam schneller sein wird, als die CPU bei Lesen bzw Schreiben in den Grafikspeicher.
Vor dem ersten Durchlauf also Screen-BitMap locken, Format feststellen und in tmpbm kopieren, dann freigeben. In jedem Durchlauf von der tmpbm nach scrbm "abdunkeln", die Screen-BitMap locken, die scrbm reinblitten und wieder freigeben.

Grüßli

[ Dieser Beitrag wurde von AC-FoX am 02.12.2002 editiert. ]

[ - Antworten - Zitieren - Direktlink - ]

02.12.2002, 17:12 Uhr

gni
Posts: 1106
Nutzer
Zitat:
AC-FoX:
Alternativ geht auch ein
rotl.w #8,d1
swap d1
rotl.w #8,d1
wenn man das in C hinbekommt ;)

Versuchs mal mit Aminet:dev/c/byteswap.lha :-)

[ - Antworten - Zitieren - Direktlink - ]

02.12.2002, 17:13 Uhr

gni
Posts: 1106
Nutzer
gelöscht, da doppelt wegen Ungeduld :-(


[ Dieser Beitrag wurde von gni am 02.12.2002 editiert. ]

[ - Antworten - Zitieren - Direktlink - ]

02.12.2002, 19:11 Uhr

AC-FoX
Posts: 35
Nutzer
Jaaaaa 'türlich, Inline-Assembler! Aber das kann ja jeder ;-)
Eigentlich wär die ganze Routine eine Sache für einen einzigen ASM-Code.
Aber ASM ist eben CPU-abhängig, und der PPC hätte gerade für den Byte-Swap beim Laden und Speichern einen perfekt zugeschnittenen Befehl - wieder zwei Taktzyklen pro 2 Pixel gespart - hehe.
Und Micha wollte ja reinen C-Code, und portierbar ist es auch noch, wenn man mal den Grafiksystem-Kram anpaßt.

Gruß,
FoX

[ - Antworten - Zitieren - Direktlink - ]

03.12.2002, 14:53 Uhr

gni
Posts: 1106
Nutzer
Zitat:
AC-FoX:
Jaaaaa 'türlich, Inline-Assembler! Aber das kann ja jeder ;-)

Nö, sonst würden es ja mehr Leute so machen! :-)

Zitat:
Eigentlich wär die ganze Routine eine Sache für einen einzigen ASM-Code.
Aber ASM ist eben CPU-abhängig, und der PPC hätte gerade für den Byte-Swap beim Laden und Speichern einen perfekt zugeschnittenen Befehl - wieder zwei Taktzyklen pro 2 Pixel gespart - hehe.

Wenn es reicht nur bestimmte Teile in ASM zu machen (wie hier das swap), dann ist diese Vorgehensweise doch akzeptabel.

Zitat:
Und Micha wollte ja reinen C-Code, und portierbar ist es auch noch, wenn man mal den Grafiksystem-Kram anpaßt.
Solange man das ganze per #ifdef wasserdicht macht, so daß es immer einen Fallback auf reines C gibt, seh ich kein Problem mit solchen "Tricks".

Gunther

[ - Antworten - Zitieren - Direktlink - ]

03.12.2002, 20:07 Uhr

AC-FoX
Posts: 35
Nutzer
Ja, für die in C nicht wirklich gut implementierbaren Funktionen wie Rotate oder Swap ist Inline-Assembler schon sinnvoll.
Bei der geringen Komplexheit der gesamten Fade-Routine wär es auch sinnvoll, sie komplett in ASM zu schreiben.
Dann würde man auch das Laden der Daten über ein movem.l abwickeln, dbra für die Schleifencounter, Preload der nächsten Daten vor Schleifenende, und und und...
Hat eigentlich schon jemand ausprobiert, ob der Code funktioniert?

Gruß,
FoX

[ - Antworten - Zitieren - Direktlink - ]

04.12.2002, 09:00 Uhr

tokai
Posts: 1071
Nutzer

Wie schaut denn das mit dem inline-Assembly beim SAS/C aus? Hatte letztens mal schnell durch die Doku geblättert aber auch nichts diebzgl. gefunden. Man muss immer erst ein externes (ASM-)Modul dazulinken. :)
--
http://www.christianrosentreter.de

[ - Antworten - Zitieren - Direktlink - ]

04.12.2002, 09:46 Uhr

gni
Posts: 1106
Nutzer
Zitat:
tokai:
Wie schaut denn das mit dem inline-Assembly beim SAS/C aus?

SAS/C unterstützt sowas nicht. Das kann nur __emit(), was aber für solche Sachen nicht zu gebrauchen ist. Abgesehen vom GCC, erlaubt noch VBCC inline-Assembly zu benutzen (natürlich anders ;-) Ansonsten konnte das auch Aztec-C.

[ - Antworten - Zitieren - Direktlink - ]


-1- [ - Beitrag schreiben - ]


amiga-news.de Forum > Programmierung > schnelles ein/ausblenden bei 16bit [ - Suche - Neue Beiträge - Registrieren - Login - ]


.
Impressum | Datenschutzerklärung | Netiquette | Werbung | Kontakt
Copyright © 1998-2022 by amiga-news.de - alle Rechte vorbehalten.
.