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... -- Micha 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... -- Micha 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... -- Micha Look at my HP: http://www.lanser-online.de.vu [ - Antworten - Zitieren - Direktlink - ] |
02.12.2002, 09:52 Uhr tokai Posts: 1071 Nutzer |
Zitat: 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... -- Micha Look at my HP: http://www.lanser-online.de.vu [ - Antworten - Zitieren - Direktlink - ] |
02.12.2002, 10:39 Uhr tokai Posts: 1071 Nutzer |
Zitat: 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... -- Micha Look at my HP: http://www.lanser-online.de.vu [ - Antworten - Zitieren - Direktlink - ] |
02.12.2002, 11:11 Uhr thomas Posts: 7718 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: 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: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:Nö, sonst würden es ja mehr Leute so machen! :-) Zitat:Wenn es reicht nur bestimmte Teile in ASM zu machen (wie hier das swap), dann ist diese Vorgehensweise doch akzeptabel. Zitat: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: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-2024 by amiga-news.de - alle Rechte vorbehalten. |