Pages vues depuis 25/07/2007 : 25 374 574
Index du forum »» Création-Développement »» Dungeon Crawler (Odyssey) Os4
Ouhlà tu m'a mis le doute comme ça fais un an que j'ai plus touché à cette partie de Microbe3D
je viens de vérifier et effectivement je pense faire comme toi
J'ai une liste de vertex V
Une liste de vertex-normal VN
Je fais le transform de V et VN puis remplit la liste de points P qui elle subit le lighting sur tout les points
Sur OBJ on parle dans le vide voici un exemple:
C'est une pyramide comme en Egypte cad 4 faces triangulaires + une face de base carrée soit 5 faces
Les fichiers .obj sont des fichiers textes
Les lignes qui commencent par # sont des commentaires
pyramid.mtl est un autre fichier texte decrivant les materiaux/textures
(mtllib = materials library = bibliotheque de matériaux)
VERTEX:
Il y a 5 sommets (=vertex) les quatre de la base carrée plus le sommet
Ils sont notées v suivies de leur valeur x y z
UV:
Ma pyramide exemple est texturée selon Y cad la texture est "projetée" à la verticale comme une diapo
Ces coordonnées textures sons appelées U et V et vont de 0.0 à 1.0
Ici donc les quatre coins de la base carrée vont aux quatre coins de la texture et le sommet au centre (0.5 0.5)
Ils sont notées vt suivies de leur valeur u v
NORMALES:
Ensuite on a les normales : c'est la direction que regarde la face, il faut imaginer ça comme une fleche qui partirait du centre de chaque face avec la pointe vers l'exterieur
C'est une normale de face
Ces normales servent à l'éclairage : en faisant un "ratio" entre le direction de la lampe et celle de cette normale : on obtient une couleur. Cad si on regarde "vers" la lampe c'est clair sinon foncé
Quand l'objet est arrondi comme une boing-ball on comprends intuitivement que les sommets (coins de chaque face) serait mieux si il regardait vers une valeur moyenne: l'éclairage des faces serait adouci
https://msdn.microsoft.com/en-us/library/windows/desktop/IC36578.gif
C'est cette valeur "moyenne" de normale par sommet qu'on appelle vertex-normal et qui est très utilisée sur les cartes 3D
Elles sont notées vn suivies de leur valeur nx ny nz
LES POINTS:
Au final on reconstitue les vrais points P à tracer constitués de leurs valeurs x y z u v nx ny nz
Ainsi
f 1/1/3 2/2/5 3/3/8 4/4/10
est une face de 4 points (base pyramide) chacun faisant reference à 3 trucs
1/1/3 veut dire:
ce point est fait avec la valeur du 1er vertex avec la valeur des 1ere coordonnées textures et la valeur de la 3éme normale
donc
xyz 1.000000 -1.000000 1.000000 uv 1.000000 1.000000 nxyz 0.000000 -1.000000 0.000000
ON TRACE:
Une fois qu'on a tout les points (3 points par triangle) sous forme de liste on la trace
avec la fonction W3D_DrawArray()pour Warp3D ou son équivalent OpenGL glDrawArrays()
LE RESTE:
g defaut
definit un groupe (un sous objet quoi) ici nommé defaut
usemtl marble
veut dire utiliser le materiau marble definit dans le fichier des materiaux ici pyramid.mtl
(usemtl =use material)
---------------------------------------------------------------------------
mtllib pyramid.mtl
# 5 vertices
v 1.000000 -1.000000 1.000000
v -1.000000 -1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v 1.000000 -1.000000 -1.000000
v 0.000000 1.000000 0.000000
# 5 texcoords
vt 1.000000 1.000000
vt 0.000000 1.000000
vt 0.000000 0.000000
vt 1.000000 0.000000
vt 0.500000 0.500000
# 12 normals
vn 0.577350 0.577350 0.577350
vn 0.000000 -1.000000 0.000000
vn 0.000000 -1.000000 0.000000
vn -0.577350 0.577350 0.577350
vn 0.000000 -1.000000 0.000000
vn -0.577350 0.577350 -0.577350
vn 0.000000 -1.000000 0.000000
vn 0.000000 -1.000000 0.000000
vn 0.577350 0.577350 -0.577350
vn 0.000000 -1.000000 0.000000
vn 0.554700 0.832050 0.000000
vn -0.894427 0.447214 0.000000
g default
usemtl marble
f 1/1/3 2/2/5 3/3/8 4/4/10
f 3/3/6 5/5/11 4/4/9
f 2/2/4 5/5/12 3/3/6
f 1/1/1 5/5/11 2/2/4
f 4/4/9 5/5/11 1/1/1
---------------------------------------------------------------------------
Alain:
C'est bien ainsi que je faisais il y a encore peu. Depuis comme je l'expliquais je suis passé à un buffer unique. Ainsi donc, avec un buffer de vertex unique, il n'y a pas de normale de face mais des normales de vertex, pour obtenir le même résultat que toi, je devrais donc dupliquer les vertex. Perte sêche sur le coup, mais le gain se refait rapidement:
Par exemple au moment de ton lightning, tu fais ton éclairage selon la normale de la face, tu récupères les 3 vertex de cette face, et tu écris un array "final" qui contiendra tes 3 vertex éclairés selon la face. ->Au final, à ce moment là, tu dupliques quand mêmes les vertex.
Avec la méthode "OpenGL", le lightning est très simple: On éclaire les vertex les uns à la suites des autres selon sa propre normale. Fin de l'histoire. Du coup, on le fait pendant la transformation, d'où le terme "transform AND lightning".
En fait, je n'utilise même plus DrawArray(), mais DrawElement(), équivalent OpenGL de DrawIndexedArray(), réputé bien plus performant.
En fait, voici "en gros" comment fonctionne un moteur "OBJ" utilisant DrawArray().
-un buffer SOURCE de vertex
-un buffer SOURCE de UV
-un buffer SOURCE de normale
-un buffer SOURCE d'indices pointant vertex/UV/normale
puis:
-un buffer DESTINATION de vertex transformés
puis:
-un array FINAL de vertex transformés, incluant XYZ/COULEUR/UV, que l'on envoi à DrawArray. Un triangle = 3 vertex, ainsi, si un vertex strictement unique dans le mesh sert à 18 polygones, il apparaitra 18 fois dans ce buffer.
puis:
-DrawArray(array FINAL)
Voici maintenant simplement comment fonctionne OpenGL (et pourquoi je l'ai copié à mort)
-un buffer SOURCE de vertex incluant XYZ/COULEUR/UV/NORMALE
-un buffer SOURCE d'indices pointant les vertex
puis:
-un buffer DESTINATION de vertex transformés/éclairés incluant XYZ/COULEUR/UV
puis:
-DrawElement(). La SOURCE d'indice, toujours valable, pointant les vertex DESTINATION. Si un vertex strictement unique dans le mesh sert à 18 polygones, seul l'indice sera copié 18 fois.
Bref: OpenGL pousse à dupliquer les vertex plutôt qu'à multiplier les buffers de pointage. Mais c'est très vite rentable...
Oui c'est une très bonne idée sur les VN
Ton raisonnement tiens : Mais es tu vraiment sûr que DrawArray() est plus lent que DrawElement() avec Warp3D ?!?
Je veut dire les points finaux sont toujours copié un à un de RAM vers GPU (y pas de vbo)
"-un buffer SOURCE de vertex incluant XYZ/COULEUR/UV/NORMALE"
"-un buffer DESTINATION de vertex transformés/éclairés incluant XYZ/COULEUR/UV"
A ce moment là autant être radical et utiliser UN SEUL buffer
X Y Z /X2 Y2 Z2/RGBA/UV/VNX VNY VNZ
avec X2 Y2 V2 les valeurs transformés de X Y Z
En fait là je bosse pas du tout sur ce sujet (du rendu) mais sur le load/save des données de Microbe3D vers une sorte de fichier IFF binaire +- compressé
Alain
Ouhlà beaucoup de sujets
edit: Au fait MERCI pour le truc de l'éclairage
>Comme tu dis il faudrait un x2/y2/z2... mais aussi un r2/g2/b2/a2
Ok tu as une liste de points (appelons la P) avant transformation avec moins de champs mais de toute façon il te faut presque tout les champs dans la liste de points tranformés (appelons la P2)
donc autant utiliser P2 tout le temps
edit: les seuls champs qui servent plus à rien dans P2 (une fois le transform/lighting est fait) c'est VNX VNY VNZ ils peuvent alors contenir la couleur éclairage RGB
>des vertex et des indices créés de toute part à chaque frame à cause du clipping
Si si je m'étais posé la question quand je générais ma liste P (à partir des liste XYZ , VN, UV) "pourquoi ne pas garder P pour la frame suivante ? " puis j'avais réalisé que c'étais pas les mêmes points à cause du clipping
mais là avec ton système d'indices je me dis on peut exclure/ajouter des points:
Admettons un objet de 100 points, 10 points sont clippés qui génerent 20 nouveaux points
Si la liste P est assez grande pour ces nouveaux points alors on ajoute juste les nouveaux points à la fin : 120 points dans P, les 100 premiers inchangés/pas copiés
edit:Puis on pioche, avec les indices, les seuls triangles visibles parmi ces 120 points
>c'est très bien géré en hardware: On ne transfère qu'une seule fois le vertex par frame en VRAM, et ensuite Warp3D envoie les pointer au GPU.
T'es vraiment sûr de ça ? benchmark ? source Hans ?
Alain
>les seuls champs qui servent plus (une fois le transform/lighting fait) c'est VNX VNY VNZ ils peuvent alors contenir la couleur éclairage RGB
A titre perso, comme je fais du normal mapping, j'ai un Vector3f normal, Vector3f binormal, et Vector3f tangent. Ca fait quand même 9 floats inutiles au rendu par vertex.
Et même sans ça, si tu mets ton R/G/B dans VNX/VNY/VNZ, comment tu calcules ton éclairage à la frame suivante? :) Et ton A de RGBA? :)
Autre chose, dans une optique où on a plein de mesh différents. Si tu ne travaille qu'avec un seul buffer source, comme tu ne sais pas combien de vertex seront créés, chaque mesh devra avoir une réserve de vertex suffisantes -> consommation mémoire. Alors qu'avec des mesh figés et un buffer destination suffisant de vertex libres, on est peinard. :)
Pareil pour les indices en fait, j'ai finalement aussi un buffer destination, vu que le culling supprime des indices.
En fait un mesh c'est 2 buffers vertex/indice, et mon espace de rendu c'est 2 buffers vertex/indice. A mon humble avis, c'est optimal. Plus encore si on pense en "Library", si le moteur doit devenir une lib OpenGL, il est évident qu'il ne faut pas modifier les buffers utilisateurs.
>T'es vraiment sûr de ça ? benchmark ? source Hans ?
Pas de certitude, pas de source. Juste une supposition: Un GPU sait gérer des vertex indexés à très grande vitesse, j'ose supposer que W3D utilise au moins ça.
Niveau benchmark depuis la refonte de moteur je suis épaté. Laissez moi quelques jours/semaine pour appuyer ça d'un teaser, y'a moyen de choquer le peuple... :)