glCopyTex(Sub)Image

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • glCopyTex(Sub)Image

    Ich bin aktuell dabei, mir OpenGL beizubringen, aber ich weiß nicht weiter.
    Mein Ziel ist es, einen Teilausschnitt einer Textur auf eine andere kopieren so das ich eine Subtextur der ersten haben, aber irgendwie funktioniert es nicht.
    Ich probiere schon seit mehreren Tagen alles mögliche aus und habe auch das Netz bereits viele male durchsucht doch die Beispiele und Doku dazu ist mehr als dürftig.

    Unten ist mein Code zu sehen, der "nicht ganz" funktioniert. Ich habe den Viewport korrekt eingestellt und alles weitere bedacht, aber irgendwie bekomme ich beim versuch es zu rendern immer keine Ausgabe.

    Quellcode

    1. Texture my_sub_image(const Rect rect) { assert(rect !is null); /// Damit bleibt das gesamte Fenster weiß. /* glMatrixMode(GL_MODELVIEW_MATRIX); glLoadIdentity(); */ glViewport(0, 0, rect.width, rect.height); GLuint subId; glGenTextures(1, &subId); // Binden den Zieltextur glBindTexture(GL_TEXTURE_2D, subId); // Parameter der Zieltextur glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); //glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); glTexImage2D(GL_TEXTURE_2D, 0, this._format, rect.width, rect.height, 0, this._format, GL_UNSIGNED_BYTE, null); // Quelltextur binden this.bind(); // Quelltextur zeichnen glBegin(GL_QUADS); // top left glTexCoord2i(0, 0); glVertex2f(0, 0); // top right glTexCoord2i(1, 0); glVertex2f(rect.width, 0); // bottom right glTexCoord2i(1, 1); glVertex2f(rect.width, rect.height); // bottom left glTexCoord2i(0, 1); glVertex2f(0, rect.height); glEnd(); // Zieltextur binden glBindTexture(GL_TEXTURE_2D, subId); // kopieren glCopyTexSubImage2D( GL_TEXTURE_2D, 0, rect.get_x(), rect.get_x(), // x, y 0, 0, rect.width, rect.height ); glViewport(0, 0, 400, 400); return new Texture(null, subId, this); }


    Wenn ich diese Methode vor meiner Game Loop aufrufe und dann das besagte ergebnis anzeigen lassen will -> fail.
    Rufe ich diesen Teil allerdings in jedem Frame auf sehe ich in der Tat ein Quadrat von der angegebenen Größe am rechten Rand in der Mitte. Es ist allerdings völlig schwarz.

    Wenn ich weitere Bilder davor und/oder danach rendere sehe ich auf dem schwarzen Dreieck die rote Schrift der original Texturen. Es sieht praktisch aus wie ein Thumbnail. Die anderen Bilder und Texturen sind allerdings komplett schwarz und flimmern hin und wieder.

    Ich hab dafür mal ein paar Bilder hochgeladen, dann sieht man sicher besser was ich meine:
    Einmal wie es ohne den Versuch aussieht, also die Ausgangssituation: imageshack.us/photo/my-images/814/copyotherwise.png/
    Einmal wie es mit dem Code oben, ohne andere Texture/Primitive zu rendern, aussieht: imageshack.us/photo/my-images/…rentingamelooprender.png/
    Einmal wie es mit dem Code von oben mit dem rendern von anderen Texturen/Primitiven aussieht: imageshack.us/photo/my-images/…yingameloopmitrender.png/
    Einmal, wenn ich den Code nicht (wie in den obigen 3 Situationen) _in_ der GameLoop aufrufe, sondern davor deklariere und dann in der GameLoop zeichnen möchte: imageshack.us/photo/my-images/…yvorgameloopmitrende.png/
    Einmal wenn ich die Quelltextur binde und dann _nur_ das Quad zeichne: imageshack.us/photo/my-images/141/copyonlyprimitive.png/
    Und einmal wie es aussieht, wenn ich

    Quellcode

    1. glMatrixMode(GL_MODELVIEW_MATRIX);glLoadIdentity();
    verwenden: imageshack.us/photo/my-images/…pywithglloadidentity.png/
  • Das du keine richtige Hilfe bekommst liegt vl. daran, dass dein Code beschi*** Formatiert ist und man den Zussamenhang nur schwer Überblickt.

    Habs mal für dich Formatiert:

    Quellcode

    1. Texture my_sub_image(const Rect rect)
    2. {
    3. assert(rect !is null);
    4. /// Damit bleibt das gesamte Fenster weiß.
    5. /*
    6. glMatrixMode(GL_MODELVIEW_MATRIX);
    7. glLoadIdentity();
    8. */
    9. glViewport(0, 0, rect.width, rect.height);
    10. GLuint subId;
    11. glGenTextures(1, &subId);
    12. // Binden den Zieltextur
    13. glBindTexture(GL_TEXTURE_2D, subId);
    14. // Parameter der Zieltextur
    15. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    16. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    17. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    18. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    19. //glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
    20. glTexImage2D(GL_TEXTURE_2D, 0, this._format, rect.width, rect.height, 0, this._format, GL_UNSIGNED_BYTE, null);
    21. // Quelltextur binden
    22. this.bind();
    23. // Quelltextur zeichnen
    24. glBegin(GL_QUADS);
    25. // top left
    26. glTexCoord2i(0, 0);
    27. glVertex2f(0, 0);
    28. // top right
    29. glTexCoord2i(1, 0);
    30. glVertex2f(rect.width, 0);
    31. // bottom right
    32. glTexCoord2i(1, 1);
    33. glVertex2f(rect.width, rect.height);
    34. // bottom left
    35. glTexCoord2i(0, 1);
    36. glVertex2f(0, rect.height);
    37. glEnd();
    38. // Zieltextur binden
    39. glBindTexture(GL_TEXTURE_2D, subId);
    40. // kopieren
    41. glCopyTexSubImage2D( GL_TEXTURE_2D, 0, rect.get_x(), rect.get_x(), // x, y
    42. 0, 0, rect.width, rect.height );
    43. glViewport(0, 0, 400, 400);
    44. return new Texture(null, subId, this);
    45. }
    Alles anzeigen


    Ohne weiteres kann ich dir jetzt zwar auch nicht genau sagen woran das liegt, aber für mich sieht es so aus als ob du die TextureIDs (Quelle <-> Ziel) vertauscht hast btw. oder gar falasche ID verwendest.

    // Edit: glCopyTexSubImage2D setzt mal Parameter 3->rect.get_x() und 4->rect.get_x() auf 0, das gibt den (X,Y)-Offset in der Zieltexture an

    Mfg Rushh0ur

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von Rushh0ur ()

  • Das war ein versehen, ich meinte nicht "SubImage" sondern normales kopieren.
    Dazu habe ich, dank nochmaligen Lesens eurer Tutorials, dieses Resultat erzielt:
    imageshack.us/photo/my-images/27/wringcopy.png/

    Es ist allerdings nicht gerade das gelbe vom Ei, denn dies ist das eigentliche Original Bild:
    imageshack.us/photo/my-images/210/test2cf.png/
    Weißt du/ihr was da noch schief läuft?

    Hier der Code, diesmal als Link, damit ihr es formatiert seht, dank Chrome scheint es beim Posten des Codes immer zur zunichte machung der Code Formation zu kommen.

    rswhite.de/code/index.php?q=30684580353e43c1a3db5b33091f57b2
  • Hab mal ein Wenig rumporbiert:

    Mit der Funktion glTexImage2D werden die Eigenschaften der Textur festgelegt,
    wobei als letzter Parameter ein Speicherblock mit Rohdaten im angegebenen Format angegeben werden kann, daraus wird schliesslich dann eine Texture generiert
    -> Nützlich um zB. Daten aus einer Datei Daten zu verarbeit. Für dein vorhaben sollte da NULL stehen (Die Texture wird mit einer Standartfarbe gefüllt).

    Mit den Funktionen glCopyTexImage2D und glCopyTexSubImage2D kann der aktuelle Backbuffer auf die aktuell Selektierte Texture gerendert werden.
    Damit das Kopieren erfolgreich ist müssen mehrere Kriterien gegben sein, genauers siehe verlinkte Seiten unter Fehlermeldungen, isbesondere sei hier erwähnt das der kopierende Abshcnitt kleiner gleich der Texturgröße sein muss.
    Im Falle eines Fehlers wird kein Kopiervorgang durchgeführt und die Zieltexture weird nicht geändert. (Evtl. nach durchführung dieser Operationen den Fehlerstatus abfragen.)

    Nun zum korekten Rendern auf den Backbuffer:
    Zunächst muss der Viewport und die Projektionsmatrix korekt gesetzt werden und schlisslich eine Texture auf den Backbuffer gerendert werden.
    Ist dies Erfolgreich geschehen kann ma sich zur vergewisserung mal das Bild auf dem Monitor ausgeben lassen und wenn dies korrekt ist auf eine Textur kopieren.

    Beispiel:

    Quellcode

    1. glGenTextures(1, &texture[0]); // Create The first Texture
    2. // Typical Texture Generation Using Data From The Bitmap
    3. glBindTexture(GL_TEXTURE_2D, texture[0]);
    4. glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
    5. glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    6. glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    7. glGenTextures(1, &texture[1]); // Create The second Texture (SubTexture from)
    8. glBindTexture(GL_TEXTURE_2D, texture[1]);
    9. glTexImage2D(GL_TEXTURE_2D, 0, 3, 245, 95, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL /*TextureImage[0]->data*/);
    10. glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    11. glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    12. // Render 2D Scene
    13. glEnable(GL_TEXTURE_2D);
    14. glDisable(GL_DEPTH_TEST);
    15. glShadeModel(GL_FLAT);
    16. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    17. glViewport(0, 0, 256, 256);
    18. glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
    19. glLoadIdentity(); // Reset The Projection Matrix
    20. glOrtho(0, 256, 0, 256, 1, -1);
    21. glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
    22. glLoadIdentity(); // Reset The Modelview Matrix
    23. glBindTexture(GL_TEXTURE_2D, texture[0]); // Render first Texture to Backbuffer
    24. glBegin(GL_QUADS);
    25. glColor3f(1,1,1);
    26. glTexCoord2f(0, 1); glVertex2f(0, 0);
    27. glTexCoord2f(1, 1); glVertex2f(0 + 256, 0);
    28. glTexCoord2f(1, 0); glVertex2f(0 + 256, 0 + 256);
    29. glTexCoord2f(0, 0); glVertex2f(0, 0 + 256);
    30. glEnd();
    31. glEnable(GL_DEPTH_TEST);
    32. glBindTexture(GL_TEXTURE_2D, texture[1]); // Selekt second Texture and Copy Backbuffer
    33. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    34. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    35. glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 5, 30, 245, 95);
    36. //glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, 245, 95, 0);
    Alles anzeigen


    Links PreRendered Textur auf dem Back/Frontbuffer, Rechts nach kopieren eines Teilbereichs (inkl. eines 3D Würfels mit org. Texture)
    [Blockierte Grafik: http://img813.imageshack.us/img813/1663/unbenannt2wn.jpg]
    Uploaded with ImageShack.us


    So wie ich dass sehe scheint bei die korekte festleggung der Projektionsmatrix zu Fehlen.

    Also mit glOrtho wird die Projektiosnmatrix auf 2D stellen.
    Und mit gluPerspective wird die Projektionsmatrix auf 3D gestellt.

    Mfg Rushh0ur
  • Ah ich glaube ich habe einen meiner Fehler entdeckt. Ich habe vorher immer bei Aufrufen von "this.bind()" geprüft, ob die Texturt schon gebunden ist. Mit diesem Code
    rswhite.de/code/index.php?q=0e613d383f1aeefa579acf8eb5140b89 erhalte ich nun folgenden Output:
    imageshack.us/photo/my-images/542/firstresultat.png/
    Des Weiteren ist mir aufgefallen, dass bei meinem Code es keinerlei Unterschied macht ob ich jetzt

    Quellcode

    1. glCopyTexImage2D(GL_TEXTURE_2D, 0, this._format, 0, 0, w, h, 0);
    oder

    Quellcode

    1. glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, -25, 25, w, h);
    verwende.
  • Es macht kein unterschied?
    Dann wird die Funktion nciht ausgeührt.

    Jetzt ganz langsam was willst du machen?
    Willst du nun aus einer schon vorhanden Textur eine Teiltexture in eine zweite extrahieren oder willst du einfach nur eine Texture aus einem Bild laden?

    Ja mit dem jetzigen Code machst du auch nix anderes als die Standart Texture zu rendern.

    So sollte es Funktionieren, insofern du im Anschluss die Projektions- und Modelmatrix korekt setzs.

    Quellcode

    1. Texture subimage(const Rect rect)
    2. {
    3. assert(rect !is null); // Rechteck gülltig?
    4. GLuint SubTexture;
    5. glGenTextures(1, &SubTexture); // Texture erstellen (1)
    6. glBindTexture(GL_TEXTURE_2D, SubTexture); // Und Binden
    7. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    8. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    9. glTexImage2D(GL_TEXTURE_2D, 0, 3, rect.width, rect.height, 0, this._format, GL_UNSIGNED_BYTE, null); // Texture Dimensionen festlegen (this._format == GL_RGB[A]?)
    10. // Backbuffer rendern
    11. glEnable(GL_TEXTURE_2D);
    12. glDisable(GL_DEPTH_TEST);
    13. glShadeModel(GL_FLAT);
    14. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    15. glViewport(0, 0, rect.width, rect.height);
    16. glMatrixMode(GL_PROJECTION);
    17. glLoadIdentity();
    18. glOrtho(0, rect.width, 0, rect.height, 1, -1);
    19. glMatrixMode(GL_MODELVIEW);
    20. glLoadIdentity();
    21. //glBindTexture(GL_TEXTURE_2D, this.textureid());
    22. this.bind();
    23. glBegin(GL_QUADS);
    24. glColor3f(1, 1, 1);
    25. glTexCoord2f(0, 1); glVertex2f(0, 0 + rect.height);
    26. glTexCoord2f(1, 1); glVertex2f(0 + rect.width, 0 + rect.height);
    27. glTexCoord2f(1, 0); glVertex2f(0 + rect.width, 0 );
    28. glTexCoord2f(0, 0); glVertex2f(0, 0);
    29. glEnd();
    30. glFlush();
    31. // Teilrechteck auf neue Texture kopieren
    32. glBindTexture(GL_TEXTURE_2D, SubTexture);
    33. glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, rect.get_x(), rect.get_y(), rect.width, rect.height);
    34. return new Texture(null, SubTexture, this);
    35. }
    Alles anzeigen


    Mfg Rushh0ur
  • Ich habe es schon mithilfe von deiner Vorarbeit und eines anderen Forums nun gelöst. Es gibt nur noch ein, zwei kleinere Probleme:
    wenn ich nun das Subimage erstelle und versuche zu zeichnen klappt das. Versuche ich nun auch das Original Bild zu zeichnen, sehe ich nicht das Originalbild sondern quasi den Teil der skalierten Original Textur, den ich gerade "ausgeschnitten" habe: imageshack.us/photo/my-images/585/strangeg.png/
    Dazu kommt noch, dass die Texturen nach wenigen Sekunden verschwinden und ich ein weißes Fenster habe, obwohl ich sie eig. in jedem Frame neu zeichne. Habe auch bereits die "bind" Methoden gelogt, die werden regelmäßig aufgerufen und binden die korrekten Texturen.


    Hier aber erstmal der Code: rswhite.de/code/index.php?q=1df9af7e9dc11bac3a40e468ab83db7d
  • Quellcode

    1. Texture sub_image(const Rect rect) { assert(rect !is null); assert(this._pixels !is null); GLuint Screen; glGenTextures(1, &Screen); glBindTexture(GL_TEXTURE_2D, Screen); // Daten in den Speicher, Lineares Filtering aktivieren glTexImage2D(GL_TEXTURE_2D, 0, 4, rect.width, rect.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, null); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); //glClearColor(0.0, 0.0, 0.0,0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glBindTexture(GL_TEXTURE_2D, Screen); this.bind_anyway(); const ushort vp_w = Texture._window_width; const ushort vp_h = Texture._window_height; const float percent_x = cast(float)(vp_w) / this._width; const float percent_y = cast(float)(vp_h) / this._height; //glViewport(0, 0, vp_w, vp_h); glBegin(GL_QUADS); // top left glTexCoord2f(0, 0); glVertex2f(0, 0); // top right glTexCoord2f(1, 0); glVertex2f(vp_w, 0); // bottom right glTexCoord2f(1, 1); glVertex2f(vp_w, vp_h); // bottom left glTexCoord2f(0, 1); glVertex2f(0, vp_h); glEnd(); //glViewport(0, 0, this._width, this._height); glBindTexture(GL_TEXTURE_2D, Screen); glCopyTexImage2D( GL_TEXTURE_2D, 0, this._format, cast(uint)(rect.get_x() * percent_x), cast(uint)(rect.get_y() * percent_y), //rect.x, rect.y, rect.width, rect.height, 0 ); /+ // Zeichnen der Sub Textur glBindTexture(GL_TEXTURE_2D, Screen); /* const float tx = 300; const float ty = 100; */ glBegin(GL_QUADS); // top left glTexCoord2f(0, 0); glVertex2f(0, 0); // top right glTexCoord2f(1, 0); glVertex2f(rect.width, 0); // bottom right glTexCoord2f(1, 1); glVertex2f(rect.width, rect.height); // bottom left glTexCoord2f(0, 1); glVertex2f(0, rect.height); glEnd(); glDeleteTextures(1, &Screen); +/ // Löschen des Color-Buffers. Deaktiviert sieht man eine weitere Textur unten. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); return new Texture(rect, Screen, this); //return null;}

    Das funktioniert schon fast, ich erhalte die korrekte Sub Textur. Nur wenn ich das Originalbild auch nochmals blitten möchte, kommt so etwas: imageshack.us/photo/my-images/18/doublestrange.png/
    Lässt sich das umgehen?