[Assimp] Texturierung kaputt

Für Fragen zu Grafik APIs wie DirectX und OpenGL sowie Shaderprogrammierung.
Antworten
Benutzeravatar
mOfl
Beiträge: 37
Registriert: 23.10.2010, 21:53

[Assimp] Texturierung kaputt

Beitrag von mOfl »

Hallo Menschen,

ich arbeite seit vorgestern mit Assimp, um Collada-Models in ein OpenGL-Programm zu laden. Die Zielversion ist OpenGL 2.1, allerdings ohne Immediate Mode, deshalb lade ich die von aiMesh bereitgestellten Arrays mit einem zusätzlichen Indexarray in eine Hilfsklasse Mesh, von woaus ich sie dann als Vertex Attribute Data binde. Auch die Shader sollen ohne Fixed Function Pipeline auskommen. Eigentlich funktioniert alles sehr gut, nur texturiert werden die von mir geladenen Models völlig wirr:

Image is gone.

Im Assimp Viewer wird es korrekt texturiert, wie alle anderen Models auch. Für mich sieht es so aus, als wären bei mir die Texturkoordinaten falsch. Da ich aber keinen Fehler in meinem Code erkennen kann (was vielleicht auch daran liegt, dass ich einfach schon zu lange darauf starre), gehe ich davon aus, dass ich irgendwas an dem Umgang Assimps mit Texturkoordinaten falsch verstanden habe. Vorweg: Ich arbeite überhaupt nicht mit Materials - meinem Verständnis nach sind die zum Anzeigen einer Textur nicht nötig.

Die Fehlerbehandlung etc. mal weggelassen, ist das der komplette Code für die Arrays:

Code: Alles auswählen

aiSetImportPropertyInteger(AI_CONFIG_PP_SBP_REMOVE, aiPrimitiveType_LINE | aiPrimitiveType_POINT);

scene = aiImportFile("C:\\Users\\Dani\\Desktop\\assimp--1.1.700-sdk\\test\\models\\Collada\\duck.dae", aiProcessPreset_TargetRealtime_MaxQuality);

textures = new GLuint[scene->mNumMaterials];

for (int i = 0; i < (int) scene->mNumMaterials; i++) {
     SDL_Surface* tex = SDL_LoadBMP("C:\\Users\\_\\Desktop\\assimp--1.1.700-sdk\\test\\models\\Collada\\duck.bmp");

     glGenTextures(1, &textures[i]);
     glBindTexture(GL_TEXTURE_2D, textures[i]);

     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

     gluBuild2DMipmaps(GL_TEXTURE_2D, 3, tex->w, tex->h, GL_BGR, GL_UNSIGNED_BYTE, tex->pixels);

     SDL_FreeSurface(tex);
}

for (int i = 0; i < numMeshes; i++) {
     aiMesh* currentMesh = scene->mMeshes[i];
     Mesh* newMesh = new Mesh();
     meshes.push_back(newMesh);
     
     newMesh->numFaces = currentMesh->mNumFaces;
     newMesh->numVertices = currentMesh->mNumVertices;
     newMesh->materialIndex = currentMesh->mMaterialIndex;

     newMesh->vertices = new glm::vec4[newMesh->numVertices];
     newMesh->normals = new glm::vec3[newMesh->numVertices];
     newMesh->colors = new glm::vec4[newMesh->numVertices];
     newMesh->texCoords = new glm::vec2[newMesh->numVertices];
     newMesh->indices = new GLint[newMesh->numFaces * 3];

     for (int j = 0; j < newMesh->numVertices; j++) {
          newMesh->vertices[j].x = currentMesh->mVertices[j].x;
          newMesh->vertices[j].y = currentMesh->mVertices[j].y;
          newMesh->vertices[j].z = currentMesh->mVertices[j].z;
          newMesh->vertices[j].w = 1.0f;

          newMesh->normals[j].x = currentMesh->mNormals[j].x;
          newMesh->normals[j].y = currentMesh->mNormals[j].y;
          newMesh->normals[j].z = currentMesh->mNormals[j].z;

          newMesh->colors[j].r = currentMesh->mColors[j]->r;
          newMesh->colors[j].g = currentMesh->mColors[j]->g;
          newMesh->colors[j].b = currentMesh->mColors[j]->b;
          newMesh->colors[j].a = currentMesh->mColors[j]->a;

          if (currentMesh->mTextureCoords[0][j] != NULL) {
               newMesh->texCoords[j].x = currentMesh->mTextureCoords[0][j].x;
               newMesh->texCoords[j].y = currentMesh->mTextureCoords[0][j].y;
          }
     }

     for (int j = 0; j < newMesh->numFaces; j++) {
          newMesh->indices[j * 3] = currentMesh->mFaces[j].mIndices[0];
          newMesh->indices[j * 3 + 1] = currentMesh->mFaces[j].mIndices[1];
          newMesh->indices[j * 3 + 2] = currentMesh->mFaces[j].mIndices[2];
     }
}
Wenn ich mir die Texturkoordinaten ausgeben lasse, kommen recht vernünftige Werte raus:

Code: Alles auswählen

0.544365, 0.975068
0.274953, 0.941360
0.412382, 0.948959
0.078614, 0.893197
0.159929, 0.926191
0.045546, 0.712112
0.029763, 0.775258
0.174568, 0.589926
0.093871, 0.647648
...
Zeichnen tu ich die einzelnen Meshes folgendermaßen:

Code: Alles auswählen

for (int i = 0; i < (int) numMeshes; i++) {
     Mesh* mesh = meshes.at(i);

     glEnableVertexAttribArray(vertexLocation);
     glVertexAttribPointer(vertexLocation, 4, GL_FLOAT, GL_FALSE, 0, mesh->vertices);

     glEnableVertexAttribArray(normalLocation);
     glVertexAttribPointer(normalLocation, 3, GL_FLOAT, GL_FALSE, 0, mesh->normals);

     glEnableVertexAttribArray(texCoordLocation);
     glVertexAttribPointer(texCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, mesh->texCoords);

     glActiveTexture(GL_TEXTURE0);
     glBindTexture(GL_TEXTURE_2D, textures[mesh->materialIndex]);
     glUniform1i(textureLocation, 0);

     glDrawElements(GL_TRIANGLES, mesh->numFaces * 3, GL_UNSIGNED_INT, mesh->indices);
}
In den Shadern dann entsprechend:

Code: Alles auswählen

Vertex Shader:

attribute vec2 inTexCoord;
varying vec2 outTexCoord;

void main() {
     ...
     outTexCoord = inTexCoord;
}


Fragment Shader:

uniform sampler2D texture;
varying vec2 outTexCoord;

void main() {
     ...
     gl_FragColor = texture2D(texture, outTexCoord);
}
Sieht einer, wo der Fehler liegt? Ich habe mit den Postprocessing-Flags schon ein bisschen rumgespielt, weil ich gelesen habe, dass es da Probleme geben könnte, aber selbst, wenn ich 0 angebe, bleibt das Problem. Deshalb denke ich, dass der Fehler eigentlich nur in dem Teil liegen kann, wo ich die Arrays kopiere, aber ich entdecke keine Flüchtigkeitsfehler durch falsche Indizes oder so. Ist es allgemein der richtige Weg, die Texturkoordinaten direkt aus aiMesh auszulesen? Denn ich kenne auch Formate, die Texturkoordinaten in einem separaten Array speichern und dann zu den Vertices selbst nur einen Index auf dieses Array legen.

Ich würde mich wirklich sehr über Hilfe freuen!

Gruß
mOfl
Zuletzt geändert von mOfl am 12.12.2011, 13:48, insgesamt 1-mal geändert.
Benutzeravatar
Aramis
Moderator
Beiträge: 1458
Registriert: 25.02.2009, 19:50
Echter Name: Alexander Gessler
Wohnort: 2016
Kontaktdaten:

Re: [Assimp] Texturierung kaputt

Beitrag von Aramis »

Probier mal die y-Komponente der Texturkoordinaten 1-y zu nehmen :-)
Benutzeravatar
mOfl
Beiträge: 37
Registriert: 23.10.2010, 21:53

Re: [Assimp] Texturierung kaputt

Beitrag von mOfl »

Zauberei! Schwarze Magie!

Vielen Dank für diesen hilfreichen Tipp, auf die Idee bin ich nicht gekommen. Woran liegt das? Ist das Assimp-Policy, die Texturkoordinaten so umzuwandeln? Oder ist das Model-abhängig? Denn mit dem Modelloader sollten später beliebige Models geladen werden können, da wäre es ungünstig, wenn die Texturkoordinaten dann wieder nicht stimmen würden und man wieder y statt 1 - y nehmen müsste.



[Edit] Untenstehendes Problem werde ich vermutlich selbst lösen können, denn das geschulte Auge hätte natürlich schon viel früher erkannt, dass die beiden Meshes EBEN NICHT die gleiche Textur verwenden... :oops:

Es hat sich allerdings ein weiteres Problem ergeben:

Image is gone.

Der Zwerg etwa (aus /test/models/X/dwarf.x) besitzt nach dem Importieren zwei Meshes (Axt und Körper). Leider wird nur der Körper nun korrekt texturiert, die Axt immer noch falsch (anders falsch als vorher, aber trotzdem falsch
:)). Debug-Modus und -Ausgabe zeigen, dass für beide Meshes gültige UV-Koordinaten übernommen werden, Auszüge der Koordinaten der Axt:

Code: Alles auswählen

0.225629, 0.906647
0.257118, 0.770403
0.196806, 0.682930
0.100224, 0.753850
0.159871, 0.589702
0.034839, 0.630259
0.147435, 0.493553
0.018893, 0.506986
0.159871, 0.397404
0.034839, 0.383712
Ist das eventuell auch ein Problem, wo es eine so einfache Abhilfe gibt wie bei den Koordinaten an sich? Würde mich freuen :) Weil es leuchtet mir nicht so recht ein, dass nur eine (die zweite) Mesh korrekt texturiert wird, wenn beidemale die Texturkoordinaten gleich eingelesen und die gleiche Textur verwendet wird. Hm.[/i]
Zuletzt geändert von mOfl am 12.12.2011, 13:49, insgesamt 1-mal geändert.
Benutzeravatar
Schrompf
Moderator
Beiträge: 5162
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas
Wohnort: Dresden
Kontaktdaten:

Re: [Assimp] Texturierung kaputt

Beitrag von Schrompf »

Die Axt benutzt ein anderes Material als der Zwerg. Beachtest Du den Materialindex in der aiMesh-Struktur?
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
Aramis
Moderator
Beiträge: 1458
Registriert: 25.02.2009, 19:50
Echter Name: Alexander Gessler
Wohnort: 2016
Kontaktdaten:

Re: [Assimp] Texturierung kaputt

Beitrag von Aramis »

Woran liegt das? Ist das Assimp-Policy, die Texturkoordinaten so umzuwandeln?
Assimp-Konvention.

Direct3D benutzt eben eine andere Konvention, bzw. genauer: es nutzt ein anderes UV-Koordinatensystem, dessen Ursprung nicht unten links sondern oben links liegt. Daher muss die y-Achse geflippt werden.
Oder ist das Model-abhängig?
Nein, demzufolge nicht.
Benutzeravatar
mOfl
Beiträge: 37
Registriert: 23.10.2010, 21:53

Re: [Assimp] Texturierung kaputt

Beitrag von mOfl »

Herzlichen Dank für eure Antworten!
@Schrompf: Ja, vielen Dank, dass das tatsächlich verschiedene Materialien sind, ist mir erst nach Erstellung des Posts aufgefallen.

@Aramis: Danke auch dafür. Wenn das unabhängig vom Model ist, ist alles in Ordnung :)
Antworten