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

Aktuelle Zeit: Sa Dez 21, 2024 16:04

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



Ein neues Thema erstellen Auf das Thema antworten  [ 8 Beiträge ] 
Autor Nachricht
BeitragVerfasst: Mo Aug 15, 2016 13:38 
Offline
DGL Member

Registriert: Mo Jul 17, 2006 13:16
Beiträge: 69
Hallo zusammen,
ich habe schon einige Zeit nicht mehr mit OpenGL gearbeitet und bin ein wenig aus der Materie draußen, also helft mir mal bitte kurz auf die Sprünge:

In meinem Programm muss ich auf Objekten als Textur Graphiken anzeigen lassen, die der Benutzer zur Laufzeit festlegt.
Um Problemen zuvor zu kommen, dass die Graphiken PowerOf2 groß sein müssen oder tatsächlich die maximale Texturgröße überschritten wird (20 MP Digicam vs. Büro-PC-Graphikkarte ftw), lasse ich die Graphiken bei Bedarf auf die [nächste PowerOf2 der] Bildschirmgröße verkleinern.

Das Problem tritt nun bei PNG-Dateien, bzw. Dateien mit Transparenz-/Alphakanal auf: Ich muss ja leider die Dateien von der Festplatte des Benutzers über ein TImage-
Objekt laden, weil sonst schon beim Laden der Textur mittels LoadFromFile entweder eine Exception ausgelöst wird wegen Arbeitsspeicher zu klein etc., oder ich die fertige Textur nicht verkleinern kann (also im RAM von der Auflösung her, nicht auf dem Bildschirm). In dem TImage wird die Graphik dann verkleinert. Nun muss ich sie -laut ordnungsgemäßem Weg- auf ein BMP zeichnen, mit AssignFromBitmap an das TglBitmap2d übergeben und dann mit GenTexture die eigentliche Textur erzeugen. Da mir hier aber der Alphakanal verloren geht, wird die TransparenzFarbe bei der Textur nun immer als Weiß dargestellt, was ja letztendlich falsch ist.

Ich habe nun einen WorkAround der das PNGImage verkleinert und dann in einen MemoryStream abgespeichert, worauf dann von dem TglBitmap dieser neu geladen wird. Das funktioniert generell, aber ist das auch "schön", oder eher unprofessionell?

Abgesehen von der Tatsache, dass ich hier noch die PowerOf2 TexturSize für Resize verwende, was natürlich bei jedem Bild das nicht quadratisch ist, falsch ist, und der Weg via BMP aktuell nicht geht. (Vorhin ging's noch...) Kann ich mit .Draw auf PNG eine PND verkleinert so zeichnen, dass der Transparenzwert übernommen wird?

Code:
  1.    if tmpImage.Picture.Graphic.InheritsFrom(TPngImage) then begin
  2.       png := TPngImage(tmpImage.Picture.Graphic);
  3.       png.Resize(w, h);
  4.       ms := TMemoryStream.Create;
  5.       png.SaveToStream(ms);
  6.       ms.Position := 0;
  7.       LoadPNG(ms);
  8.       FreeAndNil(ms);
  9.     end else begin
  10.       bmp := Graphics.TBitmap.Create;
  11.       bmp.Width := w; // Texturbreite PowerOf2
  12.       bmp.Height := h; // Texturhöhe PowerOf2
  13.       bmp.PixelFormat := pf32bit;
  14.       bmp.Canvas.StretchDraw(Rect(0, 0, NewImageWidth, NewImageHeight), png);
  15.       AssignFromBitmap(bmp);
  16.       FreeAndNil(bmp);
  17.     end;
  18.  


Natürlich speichere ich mir (später) die Werte für NewImageWidth und NewImageHeight ab, damit die Bilder korrekt proportional im glOrtho-Modus dargestellt werden können.


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mo Aug 15, 2016 17:14 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1278
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
Ich weis nicht, ob du Lazarus oder Delphi verwendest.
Dies geht unter Lazarus schon mal nicht, habe damit auch schon geübt.
Zitat:
bmp.PixelFormat := pf32bit;


Verstehe ich dich richtig ?
Du willst eine sehr grosse PNG in eine OpenGL taugliches Textur-Format bringen.
Aber vorher willst du die PNG in einer TImage verkleinern ?

Dies sollte auch ohne TglBitmap gehen.

Wen du mit Lazarus arbeitest, habe ich eine Funktion, welche die Textur-ID für gängige Grafik-Formate erzeugt.

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mo Aug 15, 2016 18:53 
Offline
DGL Member

Registriert: Mo Jul 17, 2006 13:16
Beiträge: 69
Delphi 2010

Ja das ist richtig. Den Umweg über TImage mach ich aber nur, weil ich nicht weiß, ob/wie man ein TglBitmap2D skalieren kann (also dass aus einer erfolgreiche geladenen 20'000px .bmp oder .png-Datei z.B. eine 2048x1024 Textur wird.

Das Problem ist halt, dass unter den Benutzer so viele verschiedene Dateiformate existieren können, in allen möglichen Auflösungen und Farbformaten, dass ich ja nicht alles Abfangen kann, was an Problemen auftreten kann.

Ich habe seit dem letzten Post auch erst verstanden, dass TBitmap _durchaus_ den Alphakanal beherrscht (ich kann mittlerweile auch ein .png mit Transparenz im TBitmap speichern), da TBitmap sehr <> .bmp-Dateiformat.

Trotzdem habe ich Probleme:
png.Canvas.StretchDraw(Rect(0, 0, ImageWidth, ImageHeight), TPngImage(tmpImage.Picture.Graphic));

Das Bild wird sehr komisch dargestellt. Ich glaube das liegt daran -ich zeichne ja das neue, kleine Bild auf das bestehende Bild und schneide dann die Ränder ab indem ich die Abmessungen des Bildes ändere- dass der Alphakanal, also die Transparenz, NICHT mitgenommen wird bei StretchDraw. Bei anderen Problemen (z.B. mit Canvas.Textout) habe ich gelesen, dass viele Windows APIs/GDI den Alphakanal generell nicht beherrschen und den Wert immer auf 100% durchsichtig stellen oder nicht verändern. Bei mir wird nun also das verkleinerte Bild auf die Alphamap des ursprünglich großen Bildes gezeichnet, was zu den merkwürdigsten Effekten führt.

Auch wenn ich mit
png := TPngImage.CreateBlank(COLOR_RGB, 32, TexturWidth, TexturHeight);
oder
png := TPngImage.CreateBlank(COLOR_RGBAlpha, 32, TexturWidth, TexturHeight);
arbeite, klappt das nicht: Obwohl die Textur gültig ist, wird sie scheinbar 100% transparent dargestellt, ist also nicht zu sehen.

Leider weiß ich nicht, was für PixelFormate die Anwender verwenden werden. Auch jetzt scheitere ich schon daran wenn ich eine gemeinsame Prozedur für .png und .bmp verwende, dass spätestens bei nach AssignFromBitmap(bmp) ja ConvertTo(z.B. ifBGRA8) aufrufen muss, um die Farbpalette zu setzen. Je nach Situation ist hier ifBGRA8, ifRGBA8 oder was anderes erforderlich. Leider weiß ich nicht, wie ich jederzeit gültig das Pixelformat von TBitmap zu TglBitmap2g umgewandelt bekomme, und um ehrlich zu sein, ich weiß auch nicht, warum ich mich um solche Lapalien eigentlich kümmern muss oder sollte. Die technischen Gründe sind mir durchaus klar, aber kann es das nicht von alleine mit einem "genormten" Format machen ohne dass ich da einen Umwandler schreiben muss?

Wahrscheinlich ist ein (anderer) Loader durchaus sinnvoll, wenn Du mir was gutes empfehlen kannst, nur her damit.

Eigentlich sollte mein Projekt ohne SDL auskommen, um nicht wieder in 1000 Abhängigkeiten zu geraten, aber wenn's nicht anders geht...


Gibt es denn tatsächlich keine Möglichkeit, eine Graphik z.B. so in TBitmap zu laden oder "zeichnen", das man keine Möglichkeit mehr hat, das ursprüngliche Dateiformat rauszufinden? Dann würde ich -wie hier probiert- einfach sicherstellen dass die Graphik in TBitmap vorliegt, und der Rest sollte dann immer identisch sein. Z.B. fehlenden Alphakanal selbst dazudichten (immer Alles sichtbar), Pixelformat als "normale" Textur (also nicht Luminanz oder so in dem Format und Bittiefe, wie es am sinnvollsten ist (z.B: 32-Bit RGBA).

Danke für alle Inputs!


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mo Aug 15, 2016 23:14 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1278
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
Hat Delphi den gleichen Aufbau bei TBitmap ?
Gibt es auch ein TBitmap.RawImage ?

Wen ja, werde ich mal meinen Universalloader reinstellen.

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Di Aug 16, 2016 08:01 
Offline
DGL Member

Registriert: Mo Jul 17, 2006 13:16
Beiträge: 69
Ich weiß leider nicht, welchen Aufbau Lazarus bei TBitmap hat.
RawImage gibt es bei TBitmap namentlich nicht, über ScanLine kann man aber auf die einzelnen Pixel zugreifen und "ausnahmsweise" dann wohl auch den AlphaWert ändern.

Kann man denn nicht mit BitBlt oder StretchBlt auf die AlphaWerte mit übernehmen?


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Di Aug 16, 2016 17:46 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1278
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
Zitat:
dann wohl auch den AlphaWert ändern.

Ich würde die Bitmap nicht verändern (ausgenommen die Grösse), sondern je nach dem wie sie aufgebaut ist, direkt an glTexImage2D übergeben.
Für das gibt es dort die Parameter GL_BGRA, GL_RGBA, GL_RGBA8, etc. .

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mi Aug 17, 2016 13:53 
Offline
DGL Member

Registriert: Mo Jul 17, 2006 13:16
Beiträge: 69
Hallo zusammen und nochmals vielen Dank für die Antworten.

Um die Probleme der verschiedenen Formate nicht auf der OpenGL-Schiene abwickeln zu müssen, hatte ich parallel hier um Hilfe gebeten und auch Antworten bekommen: http://www.delphipraxis.net/189980-bild ... ingen.html

Letztendlich gibt es Probleme mit dem AlphaKanal, so dass alle nicht-transparenten Graphiken die reinkommen unter Umständen flächendeckend 100% durchsichtig, und somit unsichtbar sind. Ich weiß nicht, ob das jetzt ein anderes oder das selbe Problem wie mit TBitmap ist. Auf jeden Fall habe ich es nun mit Hilfe vieler Forenmitglieder soweit, dass ich die Graphiken laden kann und auch alles richtig dargestellt wird, siehe verlinkter Thread.

Zu beachten ist aber, dass ich jetzt die GR_32 Bibliothek verwende, also auch TBitmap32, und deshalb für TglBitmap2D die AssignFromBitmap-Prozedur überladen musste. Hier wird nun über ScanLine Pixel-Für-Pixel das unkomprimierte Bild mit den richtig zugeordneten Farbkanälen auf die Textur übertragen. Diese Überladung musste ich vorläufig in der glBitmap.pas machen, da die überladene Prozedur wiederum auf Prozeduren der Unit zugreifen muss, die nicht von Außen zugänglich sind.

Es wurde angemerkt, dass vielleicht glBitmap.AssignFromBitmap überarbeitet werden müsste (ich habe Version 2.0.3 vom 21-03-2010), weil dort Probleme bestehen, wenn ein TBitmap mit PixelFormat 32Bit zugewiesen wird [was nicht transparent ist], weil dann das komplette Bild unsichtbar/durchsichtig ist weil AlphaWerte nicht gesetzt. Oder es besteht ein anderes Problem...

Soweit mein Update. Danke nochmal!


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mi Aug 17, 2016 17:07 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1278
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
Ich wollte auch mal einen Universal-Loader möglichst einfach machen, aber ich musste es aufgeben.

TBitmap ist leider nicht gleich TBitmap, auch wen PixelFormat = pf32bit steht.
Ich musste bis jetzt 4 verschiedene Varianten berücksichtigen, es könnten vielleicht noch mehr werden.
Dazu kommt noch eine für PixelFormat = pf24bit und eine 8Bit für Graustufen.

Aber ein Lichtblick hat es doch, man kann die Formate wenigsten alle direkt an OpenGL übergeben.

_________________
OpenGL


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


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 14 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.009s | 15 Queries | GZIP : On ]