ERLEDIGT
NEIN
NEIN
ANTWORTEN
13
13
ZUGRIFFE
594
594
EMPFEHLEN
-
Hallo alle zusammen!
Ich habe ein merkwürdiges Problem. Ich habe eine OpenGL Umgebung in der ich dynamisch (das ist eine Anforderung) Texturen laden will und dies auch schon kann. Nun dauert das laden auf die Grafikkarte (glTexImage2D) relativ lange drum wollt ich diesen Vorgang als Thread in den Hintergrund legen. Gesagt getan. Um Speicher zu sparen möchte ich alte, nicht mehr verwendete OpenGL Texturen wiederverwenden bzw. alte überschreiben. Problem ist, dass wenn ich das synchron mache funktioniert das. Sobald ich das hochladen in einen Thread auslagere werden immer nur die zuerst geladenen Texturen angezeigt.
Hier mal der Code:
PHP-Code:void Texture::useTexture(Image *image) {
// if the opengl texture id already exists
if(_textureID) {
// if the texture has been changed
if(image->getID() != _imageID) {
_imageID = image->getID();
// glBindTexture(GL_TEXTURE_2D, _textureID);
// glTexImage2D(GL_TEXTURE_2D, 0, image->getColorFormat(), image->getWidth(), image->getHeight(), 0, image->getColorFormat(), GL_UNSIGNED_BYTE, image->getPixelData());
load(image, _textureID, _imageID);
}
} else {
GLuint textureID;
// Use tightly packed data
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// Generate a texture object
glGenTextures(1, &textureID);
// Bind the texture object
glBindTexture(GL_TEXTURE_2D, textureID);
// upload the texture
glTexImage2D(GL_TEXTURE_2D, 0, image->getColorFormat(), image->getWidth(), image->getHeight(), 0, image->getColorFormat(), GL_UNSIGNED_BYTE, image->getPixelData());
// Set the filtering mode
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
// glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
// glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
_textureID = textureID;
}
}
Ausgaben vor und in dem Thread haben mir bestätigt, das der Imagepointer und der Pixeldatenpointer auch wirklich die richtigen sind, die in die Funktion eingesetzt werden.PHP-Code:struct texture_t {
Image *image;
int textureID;
int imageID;
};
void createTexture(void *value) {
pthread_detach(NULL);
Image *image = ((texture_t*)value)->image;
// critical section cause of Texture::bind()
pthread_mutex_lock( &mutex );
glBindTexture(GL_TEXTURE_2D, ((texture_t*)value)->textureID);
glTexImage2D(GL_TEXTURE_2D, 0, image->getColorFormat(), image->getWidth(), image->getHeight(), 0, image->getColorFormat(), GL_UNSIGNED_BYTE, image->getPixelData());
pthread_mutex_unlock( &mutex );
// end of critical section
delete (texture_t*)value;
pthread_exit(NULL);
}
void load(Image *image, int texid, int imageID) {
pthread_t thread;
texture_t *tex = new texture_t;
tex->textureID = texid;
tex->imageID = imageID;
tex->image = image;
pthread_create(&thread, NULL, (void* (*)(void*))createTexture, (void*)tex);
}
Wenn ich Zeile 8 und 9 einkommentiere dafür die 10 auskommentiere, dann funktioniert das laden der Texturen so wie es soll, nur das der Ladevorgang zu lange blockiert.
Was ist hier falsch?/* no comment */
-
Hallo,
in deinem neu erzeugten Thread ist kein OpenGL-Kontext gesetzt. *glMakeCurrent gilt immer nur für den aktuellen Thread. Du kannst also entweder 1. im neuen Thread deinen OpenGL-Kontext setzen, musst ihn dann aber im Hauptthread deaktivieren, oder 2. im neuen Thread einen eigenen OpenGL-Kontext anlegen und mit *glShareLists mit dem Hauptkontext verbinden.
Das ganze Vorhaben bringt allerdings nur dann was, wenn du während des Ladevorgangs im Hauptthread die CPU beschäftigst. Die OpenGL-Aufrufe werden nämlich spätestens im Treiber wieder serialisiert. Siehe auch http://www.opengl.org/wiki/OpenGL_and_multithreading
Grüße,
Matthias„Gib einem Menschen einen Fisch, und er wird für einen Tag satt. Lehre ihn Fischen, und er wird ein Leben lang satt.“
“For every complex problem, there is an answer that is short, simple and wrong.”
“Pessimism is safe, but optimism is a lot faster!”
Aktuelles Coding Quiz: #17 - Wörter kreuz und quer
-
Super, das klingt doch mal nach nem Ansatz.
Letzeres klingt nach dem was ich brauche. Der Hauptthread ist gerade damit beschäftigt etwas zu rendern. Der zweite Thread soll ja "nur" die Texturen für den Hauptthread laden./* no comment */
-
Das stellt sich als schwieriger raus als gedacht, aber das liegt daran, dass ich vergessen hatte zu erwähnen das es sich um OpenGLES 2.0 handelt und nicht um das normale OpenGL.
Desweiteren wird das eine Android Implementation (was auch erklärt, warum der texture upload so lange dauert)
@Matthias: die funktion glMakeCurrent habe ich zwar zur Verfügung allerdings bringt mir diese nichts, da beim laden der Textur dann der Mainrenderloop verlassen würde, woraus folgt dass dieser nicht weiter rendert.
glShareLists gibt es im gles nicht.
Ich versuche es mal mit den Contexts. Wenn jemand noch eine andere Lösung hat oder eine hilfestellung geben könnte, wär das echt gut.
Danke/* no comment */
-
Hallo Unicate,
mit OpenGL ES habe ich leider keine Erfahrung. Aber egal wie du es auch drehst und wendest: einen Geschwindigkeitsvorteil wirst du durch das Auslagern des Textur-Uploads in einen eigenen Thread (sofern überhaupt möglich) nicht erfahren.
Grüße,
Matthias„Gib einem Menschen einen Fisch, und er wird für einen Tag satt. Lehre ihn Fischen, und er wird ein Leben lang satt.“
“For every complex problem, there is an answer that is short, simple and wrong.”
“Pessimism is safe, but optimism is a lot faster!”
Aktuelles Coding Quiz: #17 - Wörter kreuz und quer
-
Ich seh ein, dass die GPU im Moment des hochladens blockiert ist, so dass ich meinen "Ruckler" wohl so nicht heraus bekomme.
Hat jemand von euch vielleicht eine Idee wie ich das machen könnte?
Ich hatte schon überlegt, die schon geladenen Texturen im moment des hochladens nicht zu bewegen. Dann sieht man den Upload nicht. Das find ich aber ein wenig "dreckig", wenn ihr wisst was ich meine. Kann man die Textur evtl in kleinen Portionen schicken, sodass der upload der kleinen Teile nicht sichtbar ist? Wenn ja wie? Ich kenn im Moment nur
und da lädt er die ganze Textur hoch.PHP-Code:glTexImage2D(GL_TEXTURE_2D, 0, image->getColorFormat(), image->getWidth(), image->getHeight(), 0, image->getColorFormat(), GL_UNSIGNED_BYTE, image->getPixelData());
/* no comment */
-
Du kannst mit
Teile einer Texture neu setzen. (Link zur OpenGL Dokumentation)Code :1
glTexSubImage2D
-
Super, das geht gut soweit.
Problem hierbei ist die Skalierung. Es sieht so aus, als ob die Texture die ich mit glTexSubImage2D rein lade an die skalierung der vorhergehenden Textur angepasst wird.
Also ich lade zuerst eine textur 1024x1024, danach lade ich per glTexSubImage2D eine 512x512 nach, welche dann nur 1/4 so groß auf dem mesh zu sehen ist. Andersherum misslingt der upload vorgang mit 501-GL_INVALID_VALUE.
Das heisst für mich die nachgeladene Image darf nicht größer sein als die vorhergehende bzw anders herum.
Kann ich das irgendwie umgehen?/* no comment */
-
Nein, vermutlich nicht. glTexImage löscht zuerst den alten Speicherbereich im VRAM und allokiert dann neuen Speicher. Wenn du glTexSubImage verwendest überschreibst du nur Teile des vorher angelegten Speicherbereichs.
Das mit der Skalierung versteh ich nicht ganz: Wenn du einen 512x512 großen Speicherbereich einer 1024x1024 Textur überschreibst solltes du eigentlich eine Textur bekommen die weiterhin 1024x1024 groß ist und irgendwo drinnen ist die neue Textur zu sehen.
-
Ja, verzeihung. Ich habe mich vielleicht etwas ungünstig ausgedrückt. Die alte Textur ist natürlich noch zu sehen, und die "neue" ist dann auf der alten drauf. Das ist das überschreiben.
Kann ich irgendwie dem VRAM einen neuen Speicherbereich alloziieren lassen (und den alten natürlich wieder freigeben) ohne was hinein zu kopieren? Weil ich nehme an, das hier der Kopiervorgang so lange dauert. Wenn ich "nur" den Speicher alloziiere und dann mit SubImage die Textur Stück für Stück hineinkopiere sollte das funktionieren oder?/* no comment */
-
Du kannst bei glTexImage eine NULL Pointer übergeben. Ein kurzer Blick in die Doku hätte hier geholfen:
data may be a null pointer. In this case, texture memory is allocated to accommodate a texture of width width and height height. You can then download subtextures to initialize this texture memory. The image is undefined if the user tries to apply an uninitialized portion of the texture image to a primitive.
-
Sorry, ich habe nicht daran gedacht, dass diese Funktion eine solche Funktionalität bereit stellt, deshalb hatte ich da nicht weiter gesucht. Mit dieser Funktion, ist es das bisher beste Ergebnis was ich erzielen konnte, das Ergebnis aber noch nicht das gelbe vom Ei.
Ich sehe zwar noch keine Möglichkeit das zu fixen, aber vielleicht habt ihr eine Idee. Wenn ich die fkt, wie oben beschrieben mit einem Nullpointer starte, dann braucht die Funktion für diesen Aufruf zu lange.
D.h. ich habe zwar das dynamische laden des Bildes minimiert, aber beim allokieren des Speichers für dieses Bild ruckt es trotzdem. <= Nicht verkraftbar/* no comment */
-
Ich hab leider auch keine Erfahrungswerte mit Androide, was man ev. versuchen könnte ist die Texturegröße von vorneherein auf die maximale Texturgröße zu allokieren und sich dann selbst zu merken welchen Bereich man eigentlich verwendet.
z.B.: Wenn du die Texture auf Größe 2048x2048 allokierst und dann mit subimage 1024x1024 setzt, könntest du nur Texturkoordinaten von 0 bis 0.5 verwenden.
-
Den Versuch habe ich auch schon gemacht. Dabei ist mir aufgefallen, das die Uploadzeiten länger waren als sonst was dazu geführt hat, dass die min. 25 FPS nicht erreicht werden konnten. Ich werds vielleicht nochmal versuchen.
subimage darf MAX. 1000px in eine Richtung (Höhe und Breite) sein. Was zu einem Texturpuzzle führt. Mal sehen.Geändert von Unicate (11.07.11 um 11:21 Uhr)
/* no comment */
Ähnliche Themen
-
OpenGL - Problem mit 0-Terminierung
Von thekiller im Forum C/C++Antworten: 5Letzter Beitrag: 25.04.11, 22:56 -
Unterstützung für OpenGL Entwicklung mit Java via Netbeans und OpenGL Pack
Von Thomas Darimont im Forum JavaAntworten: 0Letzter Beitrag: 04.06.08, 15:13 -
Problem mit OpenGL und SDL
Von FaNo86 im Forum C/C++Antworten: 6Letzter Beitrag: 05.10.07, 21:10 -
OpenGL Problem (BlendFunc)
Von fireblade1282 im Forum Delphi, Kylix, PascalAntworten: 2Letzter Beitrag: 22.08.05, 16:18 -
2D Problem OpenGL VC++6
Von WinDWalker im Forum C/C++Antworten: 3Letzter Beitrag: 05.08.05, 15:17





Zitieren

Login






