Salut salut.
Je partage avec vous un bug qui me ronge depuis quatre jours déjà et dont je n'ai toujours pas pu identifier la source.
Contexte
J'ai identifié pour la première fois ce bug quand quelqu'un (avec qui je suis en contact sur Skype) m'a annoncé un comportement étrange sur les coordonnées de textures de la classe Sprite: Le point d'origine des coordonnées de texture (0,0) est situé en bas à gauche.
Sachant que le moteur inverse les texture pour que le point d'origine apparaisse comme étant en haut à gauche, ça me paraissait étrange.
Après plusieurs tests, je me suis rendu compte que la classe Sprite n'était pas en cause, ce problème est global et affecte tout ce que le moteur affiche.
Je me suis alors demandé comment ça se faisait que les modèles que j'affichais jusque là avaient des UV correctes, et il s'avère que j'ai commis quelques erreurs:
- J'inversais les UV dans le loader MD5 alors que je ne devais pas (ça aide de relire les spécifications)
- Je n'inverse pas les UV dans le loader Assimp alors que je devais (Assimp ayant par défaut ses UV avec pour origine le coin bas-gauche)
- Je suspecte mon vaisseau (.obj) d'avoir des UV inversées (n'arrivant pas à afficher les textures sur d'autres viewer totalement indépendants du moteur)
J'ai alors décidé d'approfondir mes tests et de court-circuiter le code du moteur petit à petit, pour identifier le problème.
Mais j'en suis arrivé au point que mon affichage ne dépend plus que d'appels OpenGL natifs et le bug se produit toujours.
Résumé
Le problème est que l'origine de mes coordonnées de texture semble être le coin en haut à gauche alors que selon les spécifications OpenGL, il est en bas à gauche.
J'ai fait un programme de test n'utilisant que de l'OpenGL natif (se servant néanmoins du moteur pour l'initialisation et le fenêtrage)
Dans mon programme de test, j'affiche cette image:
Afin de clairement identifier chaque sommet et m'assurer que l'image en elle-même n'est pas retournée, les sommets sont colorés et l'image modifiée au runtime (deux carrés 2x2 colorés pour s'assurer que la classe NzImage ne retourne pas l'image).
Voici donc les sommets:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | struct ColoredVertex { NzVector3f pos; NzVector2f uv; NzVector3f color; }; ColoredVertex vertices[4]; vertices[0].pos = NzVector3f(-0.5f, 0.5f, 0.f); vertices[0].uv = NzVector2f(0.f, 0.f); vertices[0].color = NzVector3f(1.f, 0.f, 0.f); vertices[1].pos = NzVector3f(0.5f, 0.5f, 0.f); vertices[1].uv = NzVector2f(1.f, 0.f); vertices[1].color = NzVector3f(0.f, 1.f, 0.f); vertices[2].pos = NzVector3f(-0.5f, -0.5f, 0.f); vertices[2].uv = NzVector2f(0.f, 1.f); vertices[2].color = NzVector3f(0.f, 0.f, 1.f); vertices[3].pos = NzVector3f(0.5f, -0.5f, 0.f); vertices[3].uv = NzVector2f(1.f, 1.f); vertices[3].color = NzVector3f(1.f, 0.f, 1.f); |
(À noter qu'aucune matrice n'est utilisée, le rendu est fait dans le clipspace)
Et voici le résultat:
Si j'utilisais DirectX, ce serait exactement le résultat attendu.
Mais je n'utilise pas DirectX.
Pour être complet, j'ai également testé en me passant de la classe NzImage:
(En désactivant les couleurs des sommets dans le shader)
1 2 3 4 5 | char buffer[4][4] = {{255, 0, 0, 255}, {255, 255, 255, 255}, {255, 255, 255, 255}, {0, 0, 255, 255}}; width = 2; height = 2; ptr = &buffer[0][0]; |
Ce qui me donne le résultat suivant:
J'ai pensé à incriminer le driver, mais le problème se produisant chez tout le monde, tant du côté AMD, NVidia et Intel, je me suis dit que ça se serait vu.
Voici l'archive avec l'exécutable de test (et son code source): http://nazara.digitalpulsesoftware.com/files/BugUV.7z
Je ne doute pas que le problème soit en réalité très con, mais si quelqu'un pouvait m'aider à le résoudre je lui offrirais volontiers une bière la prochaine fois qu'il passe à Liège !
Merci.