Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Mi Mai 15, 2024 04:29

Foren-Übersicht » Programmierung » Einsteiger-Fragen
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 9 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: Screenshot - so richtig schnell?
BeitragVerfasst: So Mai 19, 2013 06:45 
Offline
DGL Member

Registriert: Do Mär 05, 2009 20:17
Beiträge: 284
Wohnort: Kaiserslautern
Hallo,

gibt es eine Möglichkeit einen Screenshot der 3D Szene in die Zwischenablage oder in bmp zu rendern die annähernd so schnell ist wie das normale Rendern?

Hintergrund: ich möchte zum Anfang gerne bis zu 400 "Bilder" schiessen um diese weiterzuverwenden... bei einer Bildgröße von ca. 1620x1080 braucht diese Procedur dafür 1,3 Sekunden bei mir.
Code:
  1. function shotperpixel(bmp:TBitmap):Tbitmap;
  2.   var
  3.     pixels: array of Byte;
  4.     x,y: integer;
  5.     n: Integer;
  6.     VP: array[0..3] of Integer;
  7. begin
  8.   Screen.Cursor := crHourGlass;                            // Eieruhr einschalten
  9.   glGetIntegerv(GL_VIEWPORT, @VP);                         // Viewport in VP ablegen
  10.   glPixelStoref(GL_PACK_ALIGNMENT,1);                      // [*2] keine Ahnung
  11.   setLength(pixels,VP[2]*VP[3]*3);                         // Die Anzahl der notwendingen Bytes im array of
  12.                                                            // Pixels beträgt Breite mal Höhe mal 3
  13.   glReadPixels(0,0,VP[2],VP[3],                            // Die Bytes auslesen und in Pixel schreiben
  14.                GL_RGB,GL_UNSIGNED_BYTE,@pixels[0]);
  15.   bmp.Width := VP[2];                                      // Dem BMP die Viewport Breite beibringen
  16.   bmp.Height := VP[3];                                     // Dem BMP die Viewport Höhe beibringen
  17.   n := 0;                                                  // Zähler für die Pixel auf 0 setzen
  18.   for y := VP[3]-1 downto 0 do                             // [*2] für die Anzahl der Zeilen
  19.     for x := 0 to VP[2]-1 do                               //      für die Anzahl der Pixel in der Breite
  20.       begin
  21.         bmp.Canvas.Pixels[x,y] :=                          // Die Pixel ins Canvas des BMP malen
  22.           RGB(pixels[n],pixels[n+1],pixels[n+2]);          // und zwar immer Rot, Grün und Blauwert aus dem array Pixel
  23.         inc(n,3);                                          // den zähler um 3 erhöhen
  24.       end;
  25.   result:=bmp;                                             // Das bmp als result zurückliefern
  26.   Screen.Cursor := crDefault;                              // den normalen Mauszeiger wieder einschalten
  27. end;


das wären dann bei 400 Bildern über 8 Minuten Wartezeit und das will ich keinem zumuten.. die selbe Szene rendert in 0.007 Sekunden also 185 mal schneller...
Hat jemand eine alternative function oder wenigstens einen Tipp wie es noch geht?

[EDIT]: Die Szene muß dafür nicht unbedingt dargestellt werden, wenn das auch ohne geht, wäre es mir sogar noch lieber.. [/EDIT]
Danke schonmal und allen schöne Pfingsten!


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Screenshot - so richtig schnell?
BeitragVerfasst: So Mai 19, 2013 08:37 
Offline
Compliance Officer
Benutzeravatar

Registriert: So Aug 08, 2010 08:37
Beiträge: 460
Programmiersprache: C / C++ / Lua
Dass es so langsam ist, liegt hauptsächlich an TBitmap und den anderen verwendeten Windows-Sachen.

Es wäre wesentlich besser, einfach 400 Framebufferobjekte anzulegen, in die du dann direkt renderst. Diese dann aber wieder in Bitmaps umzuwandeln braucht aber wieder einiges an Zeit, aber wenn das Programm danach weiterläuft könntest du dann für das Konvertieren/Speichern einen neuen Thread anlegen, der das dann abarbeitet.

Damit wären glaub ich alle deine Wünsche erfüllt, oder? :D

_________________
offizieller DGL Compliance Beauftragter
Never run a changing system! (oder so)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Screenshot - so richtig schnell?
BeitragVerfasst: So Mai 19, 2013 09:21 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Sep 23, 2002 19:27
Beiträge: 5812
Programmiersprache: C++
Bitmap.SetPixels ist hier wie End schon sagt der langsamste Part.

In meiner Screenshotfunktion (die nur wenige ms für 1920x1080 braucht) schiebe ich die Pixeldaten direkt via SetDIBits in das Bitmap :

Code:
  1.  
  2. var
  3.  RGBBits  : PRGBQuad;
  4.  BMP      : TBitmap;
  5.  Header   : PBitmapInfo;
  6.  ...
  7. begin
  8. ...
  9. glPixelStorei(GL_PACK_ALIGNMENT, 4);
  10. glPixelStorei(GL_PACK_ROW_LENGTH, 0);
  11. glPixelStorei(GL_PACK_SKIP_ROWS, 0);
  12. glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
  13. glReadPixels(0, 0, Viewport[2], Viewport[3], GL_BGRA, GL_UNSIGNED_BYTE, RGBBits);
  14. ...
  15. BMP := TBitmap.Create;
  16. BMP.PixelFormat := pf32Bit;
  17. BMP.Width       := Viewport[2];
  18. BMP.Height      := Viewport[3];
  19. GetMem(Header, SizeOf(TBitmapInfoHeader));
  20. ...
  21. with Header^.bmiHeader do
  22.  begin
  23.  biSize        := SizeOf(TBitmapInfoHeader);
  24.  biWidth       := Viewport[2];
  25.  biHeight      := Viewport[3];
  26.  biPlanes      := 1;
  27.  biBitCount    := 32;
  28.  biCompression := BI_RGB;
  29.  biSizeImage   := Viewport[2]*Viewport[3]*4;
  30.  end;
  31. ...
  32. SetDIBits(Bmp.Canvas.Handle, Bmp.Handle, 0, Viewport[3], RGBBits, TBitmapInfo(Header^), DIB_RGB_COLORS);
  33.  

_________________
www.SaschaWillems.de | GitHub | Twitter | GPU Datenbanken (Vulkan, GL, GLES)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Screenshot - so richtig schnell?
BeitragVerfasst: So Mai 19, 2013 09:28 
Offline
DGL Member
Benutzeravatar

Registriert: Do Sep 02, 2004 19:42
Beiträge: 4158
Programmiersprache: FreePascal, C++
end: sieht man davon ab, dass 400 FBOs bei Full-HD so ca. 3.3 Gigabyte Speicher (hier vermutlich GRAM) verbrauchen.

grüße

_________________
If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung.
current projects: ManiacLab; aioxmpp
zombofant networkmy photostream
„Writing code is like writing poetry“ - source unknown


„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Screenshot - so richtig schnell?
BeitragVerfasst: So Mai 19, 2013 10:00 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Also die meiste Zeit beim Screenshot speichern kostet die Kompression.
Ich rate dir das was du mit glReadPixels bekommst direkt ohne jede weitere Verarbeitung auf Platte zu schreiben. Idealerweise ist die "Platte" hier natürlich ein RAM-Drive oder eine SSD. ;) Später wenn die Aufnahme komplett ist gehst du nochmal drüber und speicherst in einem platzsparenderen Format mit dem du was anfangen kannst, z.B. PNG, JPG, etc. oder du machst direkt ein Video draus.

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Screenshot - so richtig schnell?
BeitragVerfasst: So Mai 19, 2013 15:58 
Offline
DGL Member

Registriert: Do Mär 05, 2009 20:17
Beiträge: 284
Wohnort: Kaiserslautern
erstmal danke für die Antworten, besonders Sascha, ich versuche gerade deinen code bei mir einzupassen, aber ich bekomme eine Zugriffsverletzung in der Zeile:

Code:
  1. glReadPixels(0, 0, VP[2], VP[3], GL_BGRA, GL_UNSIGNED_BYTE, RGBBits);


ich vermute mal es kracht beim RGBBits, was ja ein PRGBQuad ist, ich hab nur leider keine ahnung wie ich das initialisieren muß..


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Screenshot - so richtig schnell?
BeitragVerfasst: So Mai 19, 2013 16:19 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Sep 23, 2002 19:27
Beiträge: 5812
Programmiersprache: C++
Sorry, die Zeile hab ich ganz vergessen. Da kommen halt die Bytes des Bitmap rein, muss also Höhe*Breite*4 groß sein, also z.B. so :

Code:
  1. GetMem(RGBBits, Viewport[2]*Viewport[3]*4);

_________________
www.SaschaWillems.de | GitHub | Twitter | GPU Datenbanken (Vulkan, GL, GLES)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Screenshot - so richtig schnell?
BeitragVerfasst: So Mai 19, 2013 16:46 
Offline
DGL Member

Registriert: Do Mär 05, 2009 20:17
Beiträge: 284
Wohnort: Kaiserslautern
Wahnsinn! DANKE!

0.03 Sekunden statt 1,38 Sekunden!!

Dann habe ich bei 400 Bildern ca. 12-15 Sekunden, das ist schonmal vieeeeel besser als 9 Minuten!!!

wirklich klasse!


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Screenshot - so richtig schnell?
BeitragVerfasst: Mo Mai 20, 2013 13:12 
Offline
DGL Member

Registriert: Do Mär 05, 2009 20:17
Beiträge: 284
Wohnort: Kaiserslautern
EDIT: nevermind, hab den memory leak gefunden...
dieser post kann auch gelöscht werden..


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 9 Beiträge ] 
Foren-Übersicht » Programmierung » Einsteiger-Fragen


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 4 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.038s | 17 Queries | GZIP : On ]