![]() |
Beschleunigung von Laderoutine
Meine Laderoutine..
Delphi-Quellcode:
Hat jemand eine Idee wie man das beschleunigen könnte.?
// is ShowCover
if ShowCover then begin if CoverPath <> '' then begin if CoverPath <> Path then ScanDirectory(CoverPath, 'jpg, jpeg, png', False); if aCovers.count > -1 then begin LstCoverPath.Clear; LstQuadTexture.Clear; end; if (aCovers.count <= QuadCount) then begin for I := 0 to (aCovers.count - 1) do begin // extract Filename aFileName := ExtractFileName(aCovers[I]); // extract extension aFileName := Copy(aFileName, 1, Length(aFileName) - Length(ExtractFileExt(aFileName))); // uppercase aFileName := AnsiUpperCase(aFileName); Name := ExtractFileName(GetAlbumArtisName); Name := Copy(Name, 1, Length(Name) - Length(ExtractFileExt(Name))); if (aFileName = 'FOLDER') or (aFileName = Name) then begin if quadTexture[I] <> NoCoverTexture then glDeleteTextures(1, @quadTexture[I]); LoadTexture(aCovers[I], quadTexture[I], False); LstQuadTexture.Add(IntToStr(quadTexture[I])); LstCoverPath.Add(aCovers[I]); end; end; // end for i transAlpha := 1.0; if (LastAddCover = 0) or (LastAddCover = Round(NoCoverTexture)) then Result := False; if LstCoverPath.count <> 0 then begin InitAlbumIniPath; SaveINI; end; exit; // exit For end else // else aCovers.count begin if (aCovers.count > QuadCount) then begin aCovers.Delete(0); for I := 0 to (aCovers.count - 1) do begin // extract Filename aFileName := ExtractFileName(aCovers[I]); // without extension aFileName := Copy(aFileName, 1, Length(aFileName) - Length(ExtractFileExt(aFileName))); aFileName := AnsiUpperCase(aFileName); Name := AnsiUpperCase(GetAlbumArtisName); Name := Copy(Name, 1, Length(Name) - Length(ExtractFileExt(Name))); if (aFileName = 'FOLDER') or (aFileName = Name) then begin if quadTexture[I] <> NoCoverTexture then glDeleteTextures(1, @quadTexture[I + 1]); LoadTexture(aCovers[I], quadTexture[I], False); LstQuadTexture.Add(IntToStr(quadTexture[I])); LstCoverPath.Add(aCovers[I]); end; end; // end for i transAlpha := 1.0; if LstCoverPath.count <> 0 then begin InitAlbumIniPath; SaveINI; end; end; // end aCovers.count end; // end else aCovers.count end; // end CoverPath end; //end ShowCover Das Problem ist das ich bei jeder neu eingelegten CD (Abspielen eines Albums) Alle Covers neu eingelesen und zugeordnet werden müssen da ich das erste Cover des Karussells lösche um am ende ein neues zu addieren. Aber nur dann wenn das Cover sich noch nicht im Karussell befindet. Mir fällt im Moment keine schnellere Lösung ein. Was die Anwendung blockt ist LoadTexture. Den Prozess weiterlaufen lassen bringt keine Abhilfe weil man dann das ersetzen jedes Cover sehen kann. gruss |
AW: Beschleunigung von Laderoutine
OK..
Ich habe es zumindest schon mal verkleinert. Wegen 1 Zeile
Delphi-Quellcode:
aCovers.Delete(0);
einen else Part einzurichten war nicht gerade gut durchdacht. Das kann ich mir dann auch sparen..
Delphi-Quellcode:
if (aCovers.count <= QuadCount) then
Delphi-Quellcode:
Aber schneller ist das trotzdem nicht.
if CoverPath <> '' then
begin if CoverPath <> Path then ScanDirectory(CoverPath, 'jpg, jpeg, png', False); if aCovers.count > -1 then begin LstCoverPath.Clear; LstQuadTexture.Clear; end; if (aCovers.count > QuadCount) then aCovers.Delete(0); for I := 0 to (aCovers.count - 1) do begin // extract Filename aFileName := ExtractFileName(aCovers[I]); // extract extension aFileName := Copy(aFileName, 1, Length(aFileName) - Length(ExtractFileExt(aFileName))); // uppercase aFileName := AnsiUpperCase(aFileName); Name := ExtractFileName(GetAlbumArtisName); if Name <> '' then Name := Copy(Name, 1, Length(Name) - Length(ExtractFileExt(Name))); if (aFileName = 'FOLDER') or (aFileName = Name) then begin if quadTexture[I] <> NoCoverTexture then glDeleteTextures(1, @quadTexture[I]); LoadTexture(aCovers[I], quadTexture[I], False); LstQuadTexture.Add(IntToStr(quadTexture[I])); LstCoverPath.Add(aCovers[I]); end; end; // end for i transAlpha := 1.0; if (LastAddCover = 0) or (LastAddCover = Round(NoCoverTexture)) then Result := False; if LstCoverPath.count <> 0 then begin InitAlbumIniPath; SaveINI; end; end; end; //end ShowCover gruss |
AW: Beschleunigung von Laderoutine
Hmm..
Wann ändert sich der CoverPath? Ändern sich die Bilder im CoverPath? Wenn sich daran nichts seit Programmstart ändert, dann mach das ScanDirectory() nur einmal bei Programmstart und nicht bei jedem Wechsel. Ist ein CD-Wechsel immer nur die nächste/vorherige CD ? Wenn Ja, dann behalte doch die aktuell angezeigten Covers bereits aufbereitet im Speicher und verwerfe immer nur das herausfallende um dann das eine neue nach zu laden. Derzeit werden jedes mal alle Bilder neu geladen. |
AW: Beschleunigung von Laderoutine
Zitat:
Zitat:
Zitat:
Zitat:
Zitat:
1. Zu beginn wird das Karussell mit NoCoverTexturen gefüllt TextureID(20). 2. Ändert sich ein Album wird geprüft ob an der aktuellen Position eine NoCoverTexturen verwendet wird. 3. Wenn ja wird diese mit dem Cover ersetzt wenn vorhanden, solange bis alle NoCoverTexturen mit Covers belegt sind. 4. Sind im Karussell alle NoCoverTexturen gefüllt und der Counter mehr wie die maximale Anzahl an Covern wird das erste Cover gelöscht und die anderen um einen platz nach hinten verschoben so das an letzter Position das alte durch das neue ersetzt wird. 5. Ist ein Cover vorhanden wird dieses verwendet ohne die alten zu ersetzen. 6. Ist kein Cover vorhanden dann wird die NoCoverTexturen für den Hintergrund verwendet die Covers im Karussell ändern sich dann nicht. Es ist so eingerichtet das nicht immer das letzte ersetzt wird sondern alle Cover um eins nach hinten verschoben werden. So hat man die Möglichkeit innerhalb von 25 Alben eines der vorherig verwendeten nochmals zum spielen auszuwählen. Hmm.. :idea: Müsste mal versuchen ob ich die vorherigen Covers mit den alten umstrukturieren kann ohne diese zu laden. Noch keine Ahnung wie das dann mit dem Speicher aussieht wenn die vorherigen nicht gelöscht werden. gruss |
AW: Beschleunigung von Laderoutine
Ich nehme an, du lädst jedes Mal z.b. bei Punkt 4 alle Cover neu? Falls ja, könntest du dein Array mit den Texturen auch als RingBuffer behandeln und nur intern eine Shift-Value verwalten, die angibt, an welcher Stelle des Arrays der "echte" Anfang zu finden ist. Dein Carousel renderst du dann nicht statisch von
Delphi-Quellcode:
zu
Low(Array)
Delphi-Quellcode:
, sondern einmal von
High(Array)
Delphi-Quellcode:
bis
Array[StartIndex]
Delphi-Quellcode:
und dahinter noch einmal von
High(Array)
Delphi-Quellcode:
bist
Low(Array)
Delphi-Quellcode:
.
Array[StartIndex - 1]
Sowas in der Art: ![]() Wobei du dir das Ende nicht merken musst, da bei dir die leeren Elemente ja mit der NoTexture aufgefüllt werden. |
AW: Beschleunigung von Laderoutine
Zitat:
Das mit ScanDirectory ist das kleinste Problem damit wird ja nur das nächste Cover gesucht. welches den Namen FOLDER bzw.. "Album - Artist" haben kann. "Folder.jpg" oder "The Wall (1979) - Pink Floyd.jpg" als Beispiel. Zitat:
Also beim ersten start wenn noch keine AlbumCover.ini existiert. Wird nachher ein Pfad zu einem Bild in der INI nicht gefunden warum auch immer wird diese gelöscht und alles geht von vorne los. gruss |
AW: Beschleunigung von Laderoutine
Ohne den Source komplett nachvollzogen zu haben, eine Anregung:
Es geht doch um Anzeige?! Statt die Daten im "Karussell" zu bewegen, könnte man die Sache beschleunigen, indem man nur einen Index (also ein weiteres Array mit Verweisen auf das eigentliche Karussell) manipuliert. Habe mal so etwas für eine Anzeige eines Rennverlaufs (mit Fotos der Jockeys/Pferde) gemacht. Da kam es bei den Änderungen auf Aktualität/Geschwindigkeit an. Allerdings war die Zahl der Teilnehmer "endlich", d.h. es kamen keine neuen hinzu. Gruß |
AW: Beschleunigung von Laderoutine
Warum speicherst Du das nicht zwischen?
Erzeuge Dir ein TDictionary mit den Covernamen und dem entsprechenden Bild und genauso das Dir... Dann musst Du nur 1 Cover neu laden, rest is in Memory... |
AW: Beschleunigung von Laderoutine
Zitat:
Ich bin noch am Testen ist nicht ganz so einfach. Das letzte Cover macht mir Schwierigkeiten beim verschieben.
Delphi-Quellcode:
Das letzte ist dann nicht mehr initialisiert weil es auf den vorherigen platz verschoben wurde.
for I := 0 to (aCovers.count - 1) do
begin quadTexture[I] := quadTexture[I + 1]; Dementsprechend kann ich das auch nicht freigeben.. weil nicht mehr gültig. Siehe Anhang! Anfang und Ende.. EDIT: Unterumständen muss ich dann die länge des Arrays neu setzen also den 24 Eintrag entfernen. Werde nochmal testen. (bringt nix) gruss |
AW: Beschleunigung von Laderoutine
OK- Ich verstehe nicht so ganz was Du da machst, aber eigentlich sollte das - so schnell sein, dass Du keine Verzögerung merkst... Von was sprechen wir hier?
|
AW: Beschleunigung von Laderoutine
Nimm doch statt nem Array eine Liste. Das ist doch tausend mal einfacher als den Kram in Arrays rumzuschieben.
Außerdem ist die Zeile hier unnötig:
Delphi-Quellcode:
if aCovers.count > -1 then
Eine Liste hat immer mehr als -1 Einträge ;) |
AW: Beschleunigung von Laderoutine
Wie sieht denn die LoadTexture-Methode aus?
Wäre es nicht auch zweckmäßig diese zu untersuchen, da du im ersten Post schreibst, das diese Methode blockt? |
AW: Beschleunigung von Laderoutine
Zitat:
Auf der einen Seite sagst du verstehst es nicht was ich mache aber im gleichen Atemzug gehst du davon aus Zitat:
Zitat:
Wenn es schnell genug wäre hätte ich mir die Frage danach sparen können und euch damit nicht belästigt. Das Problem ist das ich die Covers jedes Mal alle neu einlade. Nun habe ich versucht die Texturen umzustrukturieren. Die erste Texture wird gelöscht und diese dann mit der darauffolgendem neu gefüllt. Das geht schnell ohne das ich alle Texturen neu laden muss. Das Problem das aber nun auftaucht ist das dann die letzte Texture ungültig wird weil sie verschoben wurde. Dies hat zur folge das beim laden der letzten Texture die Nummerierung nicht fortläuft. Das laden von 25 Texturen nach jedem Liedwechsel verursacht in etwa eine Ladezeit von 2> Sekunden was mein Plugin quasi anhält. Das will ich vermeiden. gruss |
AW: Beschleunigung von Laderoutine
Zitat:
Das macht man ja auch nicht wenn man normale Bitmaps laden tut. Ich denke auch nicht das man hier etwas manipulieren sollte und ob sich da letztendlich was tut mag dahingestellt sein. Aber gut hier die für JPG!
Delphi-Quellcode:
function CreateTexture(Width, Height, Format: word; pData: Pointer): integer;
var Texture: GLuint; begin glGenTextures(1, @Texture); glBindTexture(GL_TEXTURE_2D, Texture); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); {Texture blends with object background} glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); { only first two can be used } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); { all of the above can be used } if Format = GL_RGBA then gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, pData) else gluBuild2DMipmaps(GL_TEXTURE_2D, 3, Width, Height, GL_RGB, GL_UNSIGNED_BYTE, pData); Result := Texture; end;
Delphi-Quellcode:
gruss
function LoadJPGTexture(Filename: string; var Texture: GLuint;
LoadFromResource: boolean): boolean; var Data: array of longword; W, Width: integer; H, Height: integer; BMP: TBitmap; JPG: TJPEGImage; C: longword; Line: ^longword; ResStream: TResourceStream; // used for loading from resource begin Result := False; JPG := TJPEGImage.Create; if LoadFromResource then // Load from resource begin try ResStream := TResourceStream.Create(hInstance, PChar(copy(Filename, 1, Pos('.', Filename) - 1)), 'JPEG'); JPG.LoadFromStream(ResStream); ResStream.Free; except on EResNotFound do begin MessageBox(0, PChar('File not found in resource - ' + Filename), PChar('JPG Texture'), MB_OK); Exit; end else begin MessageBox(0, PChar('Couldn''t load JPG Resource - "' + Filename + '"'), PChar('BMP Unit'), MB_OK); Exit; end; end; end else begin try JPG.LoadFromFile(Filename); except MessageBox(0, PChar('Couldn''t load JPG - "' + Filename + '"'), PChar('BMP Unit'), MB_OK); Exit; end; end; // Create Bitmap BMP := TBitmap.Create; BMP.pixelformat := pf32bit; BMP.Width := JPG.Width; BMP.Height := JPG.Height; BMP.canvas.draw(0, 0, JPG); // Copy the JPEG onto the Bitmap // BMP.SaveToFile('D:\test.bmp'); Width := BMP.Width; Height := BMP.Height; SetLength(Data, Width * Height); for H := 0 to Height - 1 do begin Line := BMP.scanline[Height - H - 1]; // flip JPEG for W := 0 to Width - 1 do begin c := Line^ and $FFFFFF; // Need to do a color swap Data[W + (H * Width)] := (((c and $FF) shl 16) + (c shr 16) + (c and $FF00)) or $FF000000; // 4 channel. Inc(Line); end; end; BMP.Free; JPG.Free; Texture := CreateTexture(Width, Height, GL_RGBA, addr(Data[0])); SetLength(Data, 0); Result := True; end; |
AW: Beschleunigung von Laderoutine
Zitat:
> wie 0 dann halt ändert aber nichts an meinem Problem. Und ja es ist eine Liste kein Array.. (obwohl die liste letztendlich auch aus einem besteht.) Solltest du das Array QuadTexture meinen. Ja das ist ein Array auf GLUint und hat seine Berechtigung. Ich habe keinen Bock zwischen Strings und GLUint herum zu jonglieren. gruss |
AW: Beschleunigung von Laderoutine
So geht's jetzt.
Mal sehen ob ich an anderer stelle noch was optimieren kann.
Delphi-Quellcode:
Danke für die Hilfe..
// is ShowCover
if ShowCover then begin if CoverPath <> '' then begin if CoverPath <> Path then ScanDirectory(CoverPath, 'jpg, jpeg, png', False); if aCovers.count > 0 then LstCoverPath.Clear; if (aCovers.count > QuadCount) then begin // delete first Cover aCovers.Delete(0); // move textures from destination to source for I := 0 to (aCovers.count - 1) do begin quadTexture[I] := quadTexture[I + 1]; // add to List LstCoverPath.Add(aCovers[I]); // Load last Testure if I = (QuadCount - 1) then begin // extract Filename aFileName := ExtractFileName(aCovers[I]); // extract extension aFileName := Copy(aFileName, 1, Length(aFileName) - Length(ExtractFileExt(aFileName))); // uppercase aFileName := AnsiUpperCase(aFileName); Name := ExtractFileName(GetAlbumArtistName); if Name <> '' then Name := Copy(Name, 1, Length(Name) - Length(ExtractFileExt(Name))); if (aFileName = 'FOLDER') or (aFileName = Name) then begin if quadTexture[I] <> NoCoverTexture then glDeleteTextures(1, @quadTexture[I]); LoadTexture(aCovers[I], quadTexture[I], False); end; end; end; end else begin for I := 0 to (aCovers.count - 1) do begin // extract Filename aFileName := ExtractFileName(aCovers[I]); // extract extension aFileName := Copy(aFileName, 1, Length(aFileName) - Length(ExtractFileExt(aFileName))); // uppercase aFileName := AnsiUpperCase(aFileName); Name := ExtractFileName(GetAlbumArtistName); if Name <> '' then Name := Copy(Name, 1, Length(Name) - Length(ExtractFileExt(Name))); if (aFileName = 'FOLDER') or (aFileName = Name) then begin if quadTexture[I] = NoCoverTexture then LoadTexture(aCovers[I], quadTexture[I], False); // add to List LstCoverPath.Add(aCovers[I]); end; end; // end for i end; transAlpha := 1.0; if (LastAddCover = 0) or (LastAddCover = Round(NoCoverTexture)) then Result := False; if LstCoverPath.count <> 0 then begin InitAlbumIniPath; SaveINI; end; end; end; //end ShowCover gruss |
AW: Beschleunigung von Laderoutine
OK...
Warum speicherst Du nicht die fertigen Data's Dann brauchst Du nur die Pointer um legen... |
AW: Beschleunigung von Laderoutine
Zitat:
Bei den Covers mache ich es ja schon. Und wenn es am spielen ist ändern diese sich immer abhängig vom Album natürlich das gerade wechselt. Es ist jetzt zumindest so das die Texturen wechseln wenn das Lied abspielt und nicht erst ein paar Sekunden später. Nur am Anfang werden alle Covers geladen dann nur noch jeweils eins. gruss |
AW: Beschleunigung von Laderoutine
Was Mavarik meint ist wohl folgendes:
Warum lädst und erzeugst du die Texturen für jedes Abspielen eines einzelnen Songs neu? Es wäre doch sinnvoller, beim "Betreten" eines Albumordners einmalig das JPEG zu laden und die Textur zu erzeugen und abzuspeichern. Hierfür würde sich das erwähnte Dictionary anbieten mit den Albumordner-string als Key und die OpenGL-Texture als Value. |
AW: Beschleunigung von Laderoutine
Zitat:
Ist das Album im Karussell enthalten wird nichts geladen da im Array QuadTextures vorhanden. Dann werden die Texturen jetzt lediglich im Array verschoben so das ich sie nicht neu laden muss. Wie gesagt NUR dann wenn nicht vorhanden wird geladen. Da ist mit Dictionary nichts zu machen. Es würde viel zu lange dauern 1000 Alben beim Start in ein Dictionary einzulesen und dann zu vergleichen wenn ein neuer Titel abgespielt wird. So speichere ich nur die 25 Alben bzw. so viele wie sich im Karussell befinden ab 5 und aufwärts max 25 Zudem habe ich keinen Einfluss darauf welches Album gerade gespielt wird. Das ist ein Plugin das sich die Daten über die Audio-Anwendung holt welche dieses verwendet. Zitat:
Letztendlich ist das auch nur ein *.jpg oder anderer typ. Warum soll ich diese dann abspeichern wenn sie schon im Albums Pfad vorhanden ist. Die Texture ID bringt mir gar nichts. gruss |
AW: Beschleunigung von Laderoutine
Zitat:
Behalte doch einfach die OpenGL-Texture während der Laufzeit des Plug-Ins? Wenn ich das richtig verstehe, schmeißt du ja die Texturen weg, sobald die Grenze von (aCovers.count > QuadCount) überschritten ist. Der Flaschenhals ist ja das übertragen des JPEG-Bildes auf das Bitmap-Bild. Hier kannst du übrigens ein paar Zeilen einsparen: Anstatt:
Delphi-Quellcode:
Kannst du auch das schreiben:
// Create Bitmap
BMP := TBitmap.Create; BMP.pixelformat := pf32bit; BMP.Width := JPG.Width; BMP.Height := JPG.Height; BMP.canvas.draw(0, 0, JPG); // Copy the JPEG onto the Bitmap
Delphi-Quellcode:
BMP := TBitmap.Create;
BMP.Pixelformat := pf32bit; BMP.Assign(JPG); Zitat:
Das Vergleichen mit den neuen Titel/Albumpfad ist übrigens super schnell per TDictonary. Zitat:
Letztendlich ist das auch nur ein *.jpg oder anderer typ. Zitat:
|
AW: Beschleunigung von Laderoutine
Kannst mir das mal als Beispiele auf meine Routine übertragen?
So das ich das mal testen kann. Ich bin mir auch nicht sicher ob D2010 TDictionary unterstützt (Habe es vorher noch nicht verwendet.) Ok gibt es.. Zitat:
Zitat:
Das!
Delphi-Quellcode:
geht nicht.
BMP := TBitmap.Create;
BMP.Pixelformat := pf32bit; BMP.Assign(JPG); Danach wird mein Plugin einfach beendet. gruss |
AW: Beschleunigung von Laderoutine
Zitat:
Delphi-Quellcode:
...
uses System.Generics.Collections; ... var EWeissCoverDictionary: TDictionary<string, GLuint>; procedure Construct; begin EWeissCoverDictionary := TDictionary<string, GLuint>.Create; end; procedure LoadCovers(const CoverPath: string; out Texture: GLuint); begin if not EWeissCoverDictionary.TryGetValue(CoverPath, Texture) then begin LoadTexture(CoverPath, Texture, False); EWeissCoverDictionary.Add(CoverPath, Texture); end; end; procedure MachKaputtWasEuchKaputtMacht; var Texture: GLuint; begin for Texture in EWeissCoverDictionary.Values do begin glDeleteTextures(1, @Texture); end; EWeissCoverDictionary.Free; end; Zitat:
|
AW: Beschleunigung von Laderoutine
Zitat:
Werde es mir mal anschauen danke für das Beispiel. Obwohl ich eigentlich mit dem aktuellen Stand zufrieden bin. Hab das Teil im Hintergrund so ca. 5 Stunden laufen lassen. Keine Probleme und der speicherverbrauch liegt so bei 48 MB. EDIT: Habe mir da mal angeschaut. Letztendlich ist es so das es keinen sinn macht alle Covers incl. Texturen zu speichern. Im habe maximal 25 Cover im Karussell wird das 26 Geladen dann wird das erste gelöscht die anderen rücken dann nach und das 25 ist das aktuell spielende Album. Wenn ich das erste Cover lösche welchen sinn macht es dann dieses gespeichert zu lassen es kann aus dem Plugin dann nicht mehr abgespielt werden. Der sinn des Karussell ist das man ein beliebiges Album nochmals spielen kann. Ein gelöschtes Album kann man aber nicht mehr spielen von daher muss ich es auch nicht abspeichern weder im Array, Dictionary noch in einer Datei. Trotz allem ist schon interessant. gruss |
AW: Beschleunigung von Laderoutine
Bei der von mir vorgeschlagenen Lösung würdest du jeweils maximal 25 Texturen behalten, aber müsstest trotzdem immer nur Eine neu laden.
Init:
Delphi-Quellcode:
Neues Album laden:
InsertIndex := 0;
for I := Low(TextureArray) to High(TextureArray) do begin TextureArray[I] := NoCoverTexture; end;
Delphi-Quellcode:
Zeichnen vom Carousel:
if (TextureArray[InsertIndex] <> NoCoverTexture) then
begin DeleteTexture(TextureArray[InsertIndex]); end; LoadTexture(Pfad, TextureArray[InsertIndex]); Inc(InsertIndex); if (InsertIndex = Length(A)) then begin InsertIndex := Low(A); end;
Delphi-Quellcode:
for I := InsertIndex to High(TextureArray) do
begin RenderTexture(TextureArray[I]); end; for I := Low(TextureArray) to InsertIndex - 1 do begin RenderTexture(TextureArray[I]); end; |
AW: Beschleunigung von Laderoutine
Zitat:
|
AW: Beschleunigung von Laderoutine
Zitat:
Wie soll ich dann das nächste Album addieren wenn das Maximum erreicht ist? Was soll ich mit einem Cover das keine Verwendung mehr findet? Warum soll ich unnötiger weise den Speicher mehr belasten als nötig? gruss |
AW: Beschleunigung von Laderoutine
Zitat:
Beim Start werden all Texturen mit NoCoverTexturen befüllt.
Delphi-Quellcode:
Anschließend wird die INI eingeladen.
// fill all Quads with NoCoverTexture
if FileExists(FullDataPath + 'images\Default\NoCover.JPG') then begin LoadTexture(FullDataPath + 'images\Default\NoCover.JPG', NoCoverTexture, False); for q := 0 to QuadCount - 1 do quadTexture[q] := NoCoverTexture; end else NoCoverTexture := 0;
Delphi-Quellcode:
In aCovers stehen jetzt alle 25 Pfade zu den Album Covers.
procedure LoadINI;
var I: Integer; str: string; tmpList: TStringList; begin tmpList := TStringList.Create; try With AlbumIni do begin aCovers.Clear; CoverCount := StrToInt(ReadString('AlbumCover', 'Count', '0')); if CoverCount > 0 then begin for I := 0 to CoverCount - 1 do begin str := ReadString('AlbumCover', 'Folder' + IntToStr(I), ''); if (Length(str) > 0) then if FileExists(str) then aCovers.Add(str) else tmpList.Add(str); end; end; end; finally if tmpList.count > 0 then begin AlbumIni.EraseSection('AlbumCover'); for I := 0 to aCovers.count - 1 do AlbumIni.WriteString('AlbumCover', 'Folder' + IntToStr(I), aCovers.strings[I]); end; tmpList.Free; end; AlbumIni.Free; end; Jetzt werden all NoCoverTexturen mit den vorhandenen Covers gefüllt.
Delphi-Quellcode:
Und hier wird jetzt nur noch 1 Cover geladen..
if (aFileName = 'FOLDER') or (aFileName = Name) then
begin if quadTexture[I] = NoCoverTexture then LoadTexture(aCovers[I], quadTexture[I], False); // add to List LstCoverPath.Add(aCovers[I]); end;
Delphi-Quellcode:
Der erste Eintrag in der Liste für die Pfade zu den Cover Bildern wird geöscht.
if (aCovers.count > QuadCount) then
begin // delete first Cover aCovers.Delete(0); // move textures from destination to source for I := 0 to (aCovers.count - 1) do begin quadTexture[I] := quadTexture[I + 1]; // add to List LstCoverPath.Add(aCovers[I]); // Load last Testure if I = (QuadCount - 1) then begin // extract Filename aFileName := ExtractFileName(aCovers[I]); // extract extension aFileName := Copy(aFileName, 1, Length(aFileName) - Length(ExtractFileExt(aFileName))); // uppercase aFileName := AnsiUpperCase(aFileName); Name := ExtractFileName(GetAlbumArtistName); if Name <> '' then Name := Copy(Name, 1, Length(Name) - Length(ExtractFileExt(Name))); if (aFileName = 'FOLDER') or (aFileName = Name) then begin if quadTexture[I] <> NoCoverTexture then glDeleteTextures(1, @quadTexture[I]); LoadTexture(aCovers[I], quadTexture[I], False); end; end; end; end
Delphi-Quellcode:
aCovers.Delete(0);
Hier werden die Texturen verschoben
Delphi-Quellcode:
quadTexture[I] := quadTexture[I + 1];
Jetzt wird die Liste zu den Cover Bildern aktualisiert
Delphi-Quellcode:
LstCoverPath.Add(aCovers[I]);
Wenn I das gleiche wie Maximaler Cover Count -1 dann wird die letzte Texture gelöscht
Delphi-Quellcode:
glDeleteTextures(1, @quadTexture[I]);
und nur noch einmalig für dieses Album geladen
Delphi-Quellcode:
LoadTexture(aCovers[I], quadTexture[I], False);
Das geht schnell ohne merklichen Performance Verlust. Ich weiß das Rendern von dir ist nur ein Beispiel aber da steckt im Original einiges mehr an Funktionen drin
Delphi-Quellcode:
procedure RenderAlbum(aDeltaTime: single);
// Diese Funktion zeichnet die Quader. ColorScale skaliert dabei die Farbwerte der oberen beiden Ecken procedure DrawQuads(); var I: Integer; // index der for-schleife QuadAngle: single; // die Rotation des aktuellen Quads aPos: TGLVectord3; // die finale Position des aktuellen Quads [aPos = array[0..2] of single] begin glEnable(GL_TEXTURE_2D); glInitNames; glPushName(0); // alle Quads durchgehen for I := 0 to QuadCount - 1 do begin // Position initialisieren (aPos[0] = 0, aPos[1] = 0, aPos[2] = 10) aPos := Vector_Make3f(0, 0, 12); // Die Rotation des Quads (um den Mittelpunkt des Kreises, der durch die Quads gebildet wird) // + ListAnge, also die Rotation, die mit der Maus gemacht wird QuadAngle := DegToRad(360 / (QuadCount) * I) + ListAngle; // Den Positionvektor um den Mittelpunkt des Kreises um die Y-Achse rotieren aPos := Vector_Rotatef3(aPos, Vector_Make3f(0, 0, 0), QuadAngle, False, True, False); glBindTexture(GL_TEXTURE_2D, quadTexture[I]); if I = CurrentQuad then begin // Jetzt brauchen wir Blending glEnable(GL_BLEND); // nun die Blending-Funktion setzen glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glColor4f(1, 1, 1, 0.7); // move to foreground StayOnTop(aPos, 1.5); // show only available cover if not(quadTexture[I] = NoCoverTexture) then begin win.IMGTexture := quadTexture[I]; win.bRenderGUI := True; end; end else begin // Original Farben setzen glColor4f(1, 1, 1, 1); // Blenden ausschalten glDisable(GL_BLEND); end; if not(LastAddCover = Round(NoCoverTexture)) then if LastAddCover = Trunc(quadTexture[I]) then begin glColor3f(1.0, 1.0, 1.0); glDisable(GL_TEXTURE_2D); // rahmen zeichnen glLineWidth(1); glBegin(GL_LINE_LOOP); glVertex3f(aPos[0] - QuadSizeS, aPos[1] + QuadSizeS * 2, aPos[2]); glVertex3f(aPos[0] - QuadSizeS, aPos[1], aPos[2]); glVertex3f(aPos[0] + QuadSizeS, aPos[1], aPos[2]); glVertex3f(aPos[0] + QuadSizeS, aPos[1] + QuadSizeS * 2, aPos[2]); glEnd; glEnable(GL_TEXTURE_2D); // Quad zeichnen glBegin(GL_QUADS); glTexCoord2f(0, 1); glVertex3f(aPos[0] - QuadSizeS, aPos[1] + QuadSizeS * 2, aPos[2]); glTexCoord2f(0, 0); glVertex3f(aPos[0] - QuadSizeS, aPos[1], aPos[2]); glTexCoord2f(1, 0); glVertex3f(aPos[0] + QuadSizeS, aPos[1], aPos[2]); glTexCoord2f(1, 1); glVertex3f(aPos[0] + QuadSizeS, aPos[1] + QuadSizeS * 2, aPos[2]); glEnd(); end; // Quad zeichnen glBegin(GL_QUADS); glTexCoord2f(0, 1); glVertex3f(aPos[0] - QuadSize, aPos[1] + QuadSize * 2, aPos[2]); glTexCoord2f(0, 0); glVertex3f(aPos[0] - QuadSize, aPos[1], aPos[2]); glTexCoord2f(1, 0); glVertex3f(aPos[0] + QuadSize, aPos[1], aPos[2]); glTexCoord2f(1, 1); glVertex3f(aPos[0] + QuadSize, aPos[1] + QuadSize * 2, aPos[2]); glEnd(); glLoadName(I + 1); end; glPopName; end; begin glDepthMask(ByteBool(GL_TRUE)); // Kamera ausrichten, damit man was sieht glTranslatef(0, -7, -30); // Maus verarbeiten if FMousePos.X > 0 then begin if FMousePos.X < 30 then ListAngle := ListAngle - pi / 4 * aDeltaTime else if FMousePos.X > _FNormal.Image1.Width - 30 then ListAngle := ListAngle + pi / 4 * aDeltaTime; end; // Wichtig für die Spiegelung glDisable(GL_CULL_FACE); glEnable(GL_BLEND); // Jetzt spiegel wir alles an der x-z-Ebene glScalef(1, -1, 1); // Jetzt zeichnen wir zuerst die Reflektionen der Quads DrawQuads(); glDisable(GL_BLEND); // Dann spiegel wir wieder zurück glScalef(1, -1, 1); // und zeichnen die eigentlichen Quads DrawQuads(); // Jetzt brauchen wir Blending glEnable(GL_BLEND); // nun die Blending-Funktion setzen glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBegin(GL_QUADS); glColor4f(0.0, 0.0, 0.0, 0.7); glVertex3f(-15, 0, 15); glVertex3f(-15, 0, -15); glVertex3f(15, 0, -15); glVertex3f(15, 0, 15); glEnd(); glDisable(GL_BLEND); glLoadIdentity; end; gruss |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:03 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz