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

Aktuelle Zeit: Fr Jul 04, 2025 01:53

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



Ein neues Thema erstellen Auf das Thema antworten  [ 12 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: Probleme mit DrawPixel
BeitragVerfasst: Do Jun 25, 2009 09:25 
Offline
DGL Member

Registriert: Fr Jan 16, 2009 13:36
Beiträge: 75
Hallo,

Ich habe mal wieder ein kleines Anfängerproblem. Nachdem ich nun eine ganze Weile mit GLScene gearbeitet habe und ich manchmal nicht weiss, was dieses an bestimmten Stellen im Hintergrund macht, möchte ich nun komplett mit dem Standard OpenGL arbeiten. Mein Problem ist nun folgendes:

Ich möchte einen bestimmten Bereich mit Pixeln füllen (momentan noch Zufallspixel) in einem Quadrat von 200x200 (alles in 2d) anschliessend würde ich mit diesem gerne bestimmte Bildverarbeitungsoperationen (Convolution,etc) druchführen. Hinzukommt noch ein überlblenden von diesem entandenen Quadrat mit einem anderen 200x200 Bild.

Ich habe mich an der Templatevorlage von dem Einsteigertutorial gehalten.

Mein Sourcecode für das Zeichnen sieht wie folgt aus:


Code:
  1. var temp : PByte;
  2.     i,j  : integer;
  3.     bmp  : TBitmap;
  4.     pixelData : array of array of gluByte;
  5. begin
  6.   glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  7.  
  8.   glMatrixMode(GL_PROJECTION);
  9.   glLoadIdentity;
  10.   gluPerspective(45.0, ClientWidth/ClientHeight, NearClipping, FarClipping);
  11.  
  12.   glMatrixMode(GL_MODELVIEW);
  13.   glLoadIdentity;
  14.  
  15.   glTranslatef(0, 0, -5);
  16.   setlength(pixeldata,200,200);
  17.  
  18.    for i:=0 to 200-1 do
  19.    begin
  20.       for j:=0 to 200-1 do
  21.       begin
  22.          pixeldata[i,j] := Random(255*255*255);
  23.       end;
  24.    end;
  25.  
  26.  
  27.  
  28.     glDrawPixels(100,100,GL_RGB,GL_UNSIGNED_BYTE,pixeldata); //Das funktioniert
  29.    // glDrawPixels(199,199,GL_RGB,GL_UNSIGNED_BYTE,pixeldata); //Das funktioniert nicht
  30.     glFlush();
  31.  
  32.   SwapBuffers(DC);
  33.  


Ich bin für jede Hilfe sehr dankbar. Ich habe auch gelesen, dass man dies besser nicht mit glDrawPixels macht (weil zu langsam), aber wie würde man dann mit
glTexImage2d machen?

heavenssake007


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Jun 25, 2009 10:19 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mär 30, 2007 18:35
Beiträge: 331
Dazu musst du eine Textur erstellen:

Code:
  1.  
  2. glGenTextures(1, @TexID);
  3. glBindTexture(GL_TEXTURE_2D, TexID);
  4. glTexImage2D(...)
  5.  


Das brauchst du nur einmal am Anfang deines Programms aufzurufen, danach nurnoch glTexSubImage2D. Dann hast du deine Daten in einer Textur, die kannst du dann einfach mit einem Quad darstellen. Für die Parameter kannst du dir den Artikel im Wiki durchlesen.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Jun 25, 2009 11:01 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 05, 2002 10:35
Beiträge: 4234
Wohnort: Dortmund
Dem was Markus gesagt hat kann ich nur beiflichten. Allerdings noch eine generelle Anmerkung zu deiner Erstellung. Du hast ein "array of array of gluByte" allerdings übergibst du deine Werte als GL_RGB. GL_RGB impliziert aber, dass es sich dabei um Bildmaterial handelt welches 3 Kanäle hat. Dein Material hat aber nur einen Kanal. Damit würdest du bei einer Größe von 199x199 auch deutlich über den eigentlichen Speicherbereich hinweg greifen. 100x100 geht wiederrum, da 100x100x3 kleiner als 200x200x1 ist. Du damit also innerhalb deines Speicherbereiches bleibst.

Du solltest also so etwas wie "array of array of array [0..2] of gluByte" machen. Wie man aber daran schon erkennt ist dieses Konstrukt wohl interessant. Ich persönlich würde da wohl auch zu einem ganzen Speicherblock, der mit GetMem/AllocMem alloziiert wurde, tendieren.

PS: Bei Texturen solltest du darauf achten, dass diese eine Potenz von 2 haben. Also auch wenn du nur 200x200 benötigst solltest du die Textur 256x256 groß machen. Alles andere kann zu Performanceengpässen führen.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Jun 25, 2009 11:16 
Offline
DGL Member
Benutzeravatar

Registriert: Do Sep 02, 2004 19:42
Beiträge: 4158
Programmiersprache: FreePascal, C++
Dein array of array of Konstrukt ist noch aus einem anderen Grund böse. Denn ein Array Of ist immer ein Pointer. So hast du also einen Pointer auf ein Array welches Pointer auf weitere Arrays, die dann deine gluByte-Dinger enthalten. Du solltest also eher ein array of gluByte nehmen, welches dann eine Größe von 200x200x3 bekommt. Alternativ kann man auch mit GetMem oder ähnlichem arbeiten, je nach dem, wie gut man mit Pointergeballere klar kommt ;).

Gruß Lord Horazont

_________________
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:
BeitragVerfasst: Do Jun 25, 2009 16:42 
Offline
DGL Member

Registriert: Fr Jan 16, 2009 13:36
Beiträge: 75
Vielen Dank für Eure Hilfe. Muss schon sagen, dass ich dieses Forum echt genial finde.
Eine Sache hätte ich noch:

Ich wollte mein Array noch behalten, da ich mich bei Zeigern immer etwas schwer tue (okay früher oder später muss ich die wohl anwenden).
Ich hab das jetzt mal so gemacht:

Code:
  1.  
  2. procedure TForm1.Render;
  3. var temp : PByte;
  4.     i,j  : integer;
  5.     bmp  : TBitmap;
  6.     pixelData : array of array of array [0..2] of gluByte;
  7. begin
  8.   glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  9.  
  10.   glMatrixMode(GL_PROJECTION);
  11.   glLoadIdentity;
  12.   gluPerspective(45.0, ClientWidth/ClientHeight, NearClipping, FarClipping);
  13.  
  14.   glMatrixMode(GL_MODELVIEW);
  15.   glLoadIdentity;
  16.  
  17.   glTranslatef(0, 0, -5);
  18.  
  19.   setlength(pixeldata,0);
  20.   setlength(pixeldata,200,200);
  21.  
  22.    for i:=0 to 200-1 do
  23.    begin
  24.       for j:=0 to 200-1 do
  25.       begin
  26.          pixeldata[i,j,0] := Random(255);
  27.          pixeldata[i,j,1] := Random(255);
  28.          pixeldata[i,j,2] := Random(255);
  29.       end;
  30.    end;
  31.  
  32.    GLGenTextures(1,@FTexName);
  33.    glBindTexture(GL_TEXTURE_2D,FtexName[0]);
  34.    glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,200,200,0,GL_RGBA,GL_UNSIGNED_BYTE,@pixelData); //Problem
  35.  
  36.    //hier fehlt noch das Quad, ist aber kein Problem
  37.   SwapBuffers(DC);
  38.  
  39.  
  40. end;
  41.  
  42.  


Das Problem ist, dass das pixeldata nicht so das Richtige für das glTexImage2d ist. In dem oben genannten Artikel von Markus steht ja, dass der Typ des format-Parameters der glTexImage2d mit dem Pixelparameter übereinstimmen soll. GL_Unsigned_Byte oder GL_Byte habens bei mir noch nicht gebracht, obwohl gluByte ja von TByte ist, welches wiederum ein ByteTyp ist.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Jun 25, 2009 16:49 
Offline
DGL Member

Registriert: Fr Jan 16, 2009 13:36
Beiträge: 75
okay, hab's. Klar, das pixeldata muss ja noch einen zusätzlichen Alpha-Kanal haben.

So jetzt werd ich mal probieren ob der Rest funktioniert.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Jun 25, 2009 17:42 
Offline
DGL Member
Benutzeravatar

Registriert: Do Sep 02, 2004 19:42
Beiträge: 4158
Programmiersprache: FreePascal, C++
Also mich wundert ehrlichgesagt extrem, dass das ganze mit deinem array of array of überhaupt funktioniert. Sollte nicht. Mich würde interessieren, obs klappt, wenn du die farben abhängig von x und y festlegst (also nen Farbverlauf baust).

Ansonsten wurde hier auch schon gesagt, dass du glTexImage2D im Renderloop vermeiden solltest. Du solltest deine Textur einmal außerhalb des Renderns mit glTexImage2D (und dem zugehörigen glGenTextures) in den entsprechenden Ausmaßen vorbereiten (nil als Data-Pointer übergeben). Dann im Renderloop nurnoch glTexSubImage2D verwenden, weil dies um einiges schneller ist, aber nicht die Größe der Textur ändern kann (und auch keine neue erstellen). Es dient halt wirklich nur zum setzen der Pixelinformationen, wärend glTexImage2D (schlimmstenfalls) den Puffer neu reserviert.

Auch sollte der letzte Parameter von glTexSubImage2D dann @pixelData[0] sein... Es verwundert mich immer mehr, dass das ganze so funktioniert ;).

Gruß Lord Horazont

_________________
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:
BeitragVerfasst: Do Jun 25, 2009 17:47 
Offline
DGL Member

Registriert: Fr Jan 16, 2009 13:36
Beiträge: 75
@Lord Horazont

Tut's nicht. :(
Werd wohl doch Deinen weg einschlagen. Ich halte Euch auf dem Laufenden.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Jun 25, 2009 19:02 
Offline
DGL Member
Benutzeravatar

Registriert: Do Sep 02, 2004 19:42
Beiträge: 4158
Programmiersprache: FreePascal, C++
Du musst dich ja nicht mit Pointern rumschlagen. Du kannst ja auch ein dynamisches Array anlegen, welches die Anzahl der benötigten Bytes als größe hat (für 200x200 in RGBA wäre das dann 200*200*4 => 160000). Wenn du dann noch den Rat befolgst, anstatt @pixelData einfach @pixelData[0] zu übergeben, sollte das ganze auch funktionieren.

Gruß Lord Horazont

_________________
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:
BeitragVerfasst: Fr Jun 26, 2009 08:40 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 05, 2002 10:35
Beiträge: 4234
Wohnort: Dortmund
Arrays: Da hat Lord Horazont schon vollkommen recht. "A: Array of". Dabei ist A ein Pointer auf einen Speicherbereich der echten Werte hält. Ist das dann wieder ein Array of, dann stecken in dem ersten Arrays wieder nur Pointer auf weitere Arrays. Da das allerdings mit SetLength gemacht wurde kann es sein, dass die resultierenden Daten aber doch an einem Stück im Speicher liegen. Da die größe ja auch an einem Stück gesetzt wird. Aber darauf sollte man sich nicht unbedingt verlassen.

@PixelData vs @PixelData[0]. Um da noch etwas ins Detail zu gehen. @ gibt die Speicheradresse der jeweiligen Variable zurück. Dabei muss man immer darauf achten was man eigentlich haben will. Im Fall von dynamischen Arrays enthält die Variable (PixelData) aber einen Pointer auf die echten Daten. Mit @PixelData würdest du also lediglich den Inhalt der Pointervariable ansprechen können. Wenn du aber expliziet die Daten meinst, dann solltest du immer auch direkt sagen, dass du die Daten meinst. Also @PixelData[0]. Damit meinst du expliziet die erste Stelle des Arrays. Bei Mehrdimensionalen Arrays kann man das entsprechend weiterführen.

Pointer: Vor Pointern braucht man keine Angst haben. Ich finde Pointer bei so etwas sogar deutlich besser und offensichlicher als Arrays. Dynamische
Arrays verschleiern ein bisschen, dass sie eigentlich auch nur Pointer sind. Und obwohl man glaubt, dass man das Richtige zu übergeben ist es doch nicht das Richtige. Siehe Abschnitt darüber.

Bei Pointern ist es nur wichtig, dass man beachtet, dass die eigentlichen Daten in wirklich ganz woanders liegen. Also was immer man mit einem Pointer macht. Sobald man auf die Daten zugreift muss man dereferenzieren. Also das Dach "^".
Code:
  1. var
  2.   pBuff, pTemp: PRGBQuad;
  3.   X, Y: Integer;
  4. begin
  5.   // Buffer erstellen 200*200*die Größe des Pixels
  6.   pBuff := AllocMem(200*200*SizeOf(TRGBQuad));
  7.   try
  8.     // Arbeitspointer auf bufferanfang setzen
  9.     pTemp := pBuff;
  10.  
  11.     for Y := 0 to 199 do begin    // erst zeilenweise
  12.       for X := 0 to 199 do begin  // dann Spalten
  13.         pTemp^.rgbBlue     := Blau;
  14.         pTemp^.rgbGreen    := Grün;
  15.         pTemp^.rgbRed      := Rot;
  16.         pTemp^.rgbReserved := Alpha;
  17.  
  18.         // nächstes Pixel
  19.         inc(pTemp);
  20.       end;
  21.     end;
  22.  
  23.     // Wichtig hierbei das TRGBQuad ist auf BGRA und nicht auf RGBA ausgelegt.
  24.     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 200, 200, GL_BGRA, GL_UNSIGNED_BYTE, pBuff);
  25.   finally
  26.     // Buffer wird nicht mehr benötigt also kann er wieder gelöscht werden
  27.     FreeMem(pBuff);
  28.   end;
  29. end;

Ungetestet aber sollte so funktionieren.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: So Jun 28, 2009 19:28 
Offline
DGL Member

Registriert: Fr Jan 16, 2009 13:36
Beiträge: 75
Jaaaaa, es läuft alles. Also hab's jetzt mit der Variante von Lossy eX gelöst. Vielen Dank. Ich denke für die nächste Frage müsste ich wohl noch einen Thread aufmachen, wie kann man in zwei Device Contexts rendern. Wenn ich nun zwei Images, oder Panel habe auf denen ich jeweils etwas anderes rendern möchte?

heavenssake007


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: So Jun 28, 2009 20:15 
Offline
DGL Member
Benutzeravatar

Registriert: Do Sep 02, 2004 19:42
Beiträge: 4158
Programmiersprache: FreePascal, C++
Im DGLSDK gibts nen Template für Rendern in zwei verschiedene DCs/RCs... Musst du mal reinschauen.

Gruß Lord Horazont

_________________
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  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 12 Beiträge ] 
Foren-Übersicht » Programmierung » Einsteiger-Fragen


Wer ist online?

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