IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

OpenGL Discussion :

[VBO] Seul mon dernier objet créé est affiché, une idée?


Sujet :

OpenGL

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Février 2005
    Messages
    208
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 208
    Points : 109
    Points
    109
    Par défaut [VBO] Seul mon dernier objet créé est affiché, une idée?
    Bonjour bonjour,

    Dans le programme sur lequel je suis en train de travailler, j'ai un petit soucis au niveau de l'affichage de mes objets 3D.

    Chacun de mes objets 3D contient :

    _ un nom,
    _ un tableau de coordonnées de sommets,
    _ un tableau de coordonnées de textures,
    _ un tableau de coordonnées de normales,
    _ un tableau d'indices
    ....
    ....

    Ces objets sont stockés dans un tableau d'Objets 3D, repérés par leur nom.

    Pour chaque occurrence de mon tableau, je créer les buffers qui vont bien pour ensuite afficher mes objets.
    La création et le remplissage de mes buffers s'effectuent de la manière suivante :

    _ Pour chaque objet du tableau
    _ TabObjet[i].VerticesBuffer = gl.createBuffer();
    _ Blind du buffer et remplissage
    _ TabObjet[i].TextureCoordBuffer= gl.createBuffer();
    _ Blind du buffer et remplissage
    ....
    ....

    Je remplis ensuite un tableau d'Objets à afficher, ayant pour paramètre l'Objet3D auquel l'objet à afficher fait référence.
    Ainsi, si je veux 3 cubes dans mon application, je vais créer 3 Objets à afficher faisant référence à mon Objet3D "cube".
    Ma fonction d'affichage va quand à elle parcourir mon tableau d'Objets à afficher, et donc pour chacun d'entre eux, dessiner à partir des buffers de l'Objet 3D en référence.

    Tous mes objets ont été testé séparément et sont correctement affichés.
    L'affichage de plusieurs occurrences d'un même objet marche également.

    Exemple :

    Mon tableau d'Objets3D contient : Cube.
    Mon tableau d'Objets à afficher contient : {Cube01,Cube},{Cube02,Cube},{Cube02,Cube}

    J'ai bien 3 Cubes à l'écran.

    Idem si mon tableau d'Objets3D contient un plan, une sphère ou tout ce qu'on veut.

    Le soucis apparait lorsque mon tableau d'Objets3D contient plusieurs objets3D.

    Exemple :

    Mon tableau d'Objets3D contient : Cube,Sphère,Pyramide

    Je n'aurais à l'écran que les Objets à afficher ayant pour référence le dernier Objet3D chargé, ici "Pyramide".
    Je me suis dit que je devais écraser les précédents buffers.
    _Mais si c'était le cas, mes Objets à afficher autre que le dernier charger devraient plutôt être remplacés par le dernier charger non?
    Dans le doute, j'ai affiché les infos des buffers, juste avant l'affichage des objets concernés :

    Nom Objet[0] : Plan
    Buffer Position Vertex : [object WebGLBuffer] / Size : 60 pour 5 Vertices
    Buffer Coord Texture : [object WebGLBuffer] / Size : 40 pour 5 Coordonnées
    Buffer Indice : [object WebGLBuffer] / Size : 12 pour 6 Indices
    Nom Objet[1] : Sphere01
    Buffer Position Vertex : [object WebGLBuffer] / Size : 7044 pour 587 Vertices
    Buffer Coord Texture : [object WebGLBuffer] / Size : 4696 pour 587 Coordonnées
    Buffer Indice : [object WebGLBuffer] / Size : 5760 pour 2880 Indices
    Les buffers associés à chacun de mes objets existent bien, et non pas la même taille, j'en déduis donc que le problème ne vient pas de là.
    Pourtant, je n'ai bien qu'une sphère à l'écran, alors que je devrais avoir un plan et une sphère.
    Si je charge d'abord la sphère et ensuite le plan, alors je n'aurais que le plan à l'écran.
    A noter que je ne reçois aucune erreur, sur un buffer inexistant, un nombre d'éléments trop important ou autre.

    Une piste pour résoudre ce problème?

  2. #2
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 905
    Points : 220 164
    Points
    220 164
    Billets dans le blog
    126
    Par défaut
    Bonjour,

    Comme cela, je n'ai pas vraiment d'idée. A part que la pensée que j'ai eu, c'est qu'il se passe la chose suivante:
    Activation buffer pour le cube
    Activation buffer pour le cone
    Activation buffer pour la pyramde
    Dessin
    Et là ... on peut voir que seulement la pyramide est affiché.
    Mais sérieusement je doute que cela soit le problème ... depuis que vous arrivez à affiché trois cube.

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Février 2005
    Messages
    208
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 208
    Points : 109
    Points
    109
    Par défaut
    Bonjour LittleWhite, et merci pour ta réponse.

    Ci dessous la partie de ma fonction d'affichage, affichant (théoriquement) les objets de mon tableau, il y a peut être un truc qui m'échappe et qui vous sautera aux yeux :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
     
    function DrawScene(gl)
    {
    	gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
     
    	perspectiveMatrix = makePerspective(45, gl.viewportWidth / gl.viewportHeight , 0.1, 100.0);
     
    	loadIdentity();
     
            var i=0;
     
    	while(i < TabObjetsAff.length)
    	{
    		var Objet3D = TabObjetsAff[i].Objet3D;             // << on récupère l'Objet3D associé
     
    		mvPushMatrix();
    		mvTranslate([TabObjetsAff[i].Position._X, TabObjetsAff[i].Position._Y, TabObjetsAff[i].Position._Z]);
     
    		gl.bindBuffer(gl.ARRAY_BUFFER, TabObjets3D[Objet3D].VerticesBuffer);
    		gl.vertexAttribPointer(vertexPositionAttribute, TabObjets3D[Objet3D].VerticesBuffer.itemSize, gl.FLOAT, false, 0, 0);
     
    		gl.bindBuffer(gl.ARRAY_BUFFER, TabObjets3D[Objet3D].TextureCoordBuffer);
    		gl.vertexAttribPointer(textureCoordAttribute, 2, gl.FLOAT, false, 0, 0);
     
    		gl.activeTexture(gl.TEXTURE0);
    		gl.bindTexture(gl.TEXTURE_2D, TabObjets3D[Objet3D].TextureGL);
    		gl.uniform1i(shaderProgram.samplerUniform, 0);
     
    		gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, TabObjets3D[Objet3D].IndexBuffer);
    		setMatrixUniforms(gl);
     
    		gl.drawElements(gl.TRIANGLES, TabObjets3D[Objet3D].IndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
     
    		mvPopMatrix();
     
    		i++;
    	}
    }
    D'ailleurs, en relisant cette portion de code, je me rend compte que j'active toujours la gl.TEXTURE0, il va falloir que je corrige ça.
    Et mon code de création de texture fait pareil : j'utilise toujours gl.TEXTURE0.

    M'enfin même avec cette erreur, je devrais avoir le bon objet d'affiché, juste texturé avec la dernière texture passé, non?

    Edit : Et bien si ! Il semblerait que le soucis vient de ma / mes textures.
    Je viens de déclarer une seule texture globale, et j'ai remplacé la ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    gl.bindTexture(gl.TEXTURE_2D, TabObjets3D[Objet3D].TextureGL);
    par :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    gl.bindTexture(gl.TEXTURE_2D, TextureGlobale.TextureGL);
    Et tous mes objets sont affichés, avec la même texture, mais ils sont là!
    J'avoue que je ne comprends pas tout...

    Ou alors si, je crois que j'ai compris.
    Je n'active que la texture gl.activeTexture(gl.TEXTURE0);
    Ce qui fait que lorsque je "bind" une texture, elle n'est pas forcement activée.

    Mais alors, si seule la texture "TEXTURE0" est activée, ce n'est pas plutôt le premier Objet3D qui devrait être affiché, et non le dernier?

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Février 2005
    Messages
    208
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 208
    Points : 109
    Points
    109
    Par défaut
    C'est encore moi.

    Au début de mon programme, j'ai interrogé mon context OpenGL avec le pname MAX_TEXTURE_IMAGE_UNITS :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS);
    Le résultat retourné est le suivant :
    Textures disponibles : 32
    J'en conclu donc (dites moi si je me trompe), que je peux utiliser 32 textures, allant de 0 à 31.
    Je peux donc faire un appel à glActiveTexture(), avec un paramètre allant de GL_TEXTURE0 à GL_TEXTURE31.

    J'imagine que, lorsque je créé une nouvelle texture, il me faut activer un nouvel espace pour cette texture, en appelant glActiveTexture().

    J'ai ensuite interrogé mon context avec le pname ACTIVE_TEXTURE.
    J'imagine que ça doit me retourner la texture active.

    La doc m'apprend ceci :
    The initial value is GL_TEXTURE0.
    Je m'attendais donc à ce que gl.getParameter(gl.ACTIVE_TEXTURE); me retourne TEXTURE0.
    Mais la valeur retournée est : 33984.

    Dois je en conclure que 33984 est la valeur de GL_TEXTURE0 ?

    Autrement dit, si je veux activer dynamiquement une nouvelle texture, je dois partir de glActiveTexture(33984); jusqu'à glActiveTexture(34015); en incrémentant de 1 à chaque nouvelle texture ?
    Dois je activer la texture avant de la créer?

    Je patauge un minimum là

    En interrogeant mon context avant chaque dessin d'un Objet3D, ça semble correcte, voici ce que j'obtiens :

    Objet 0
    Texture liée : ./Images/Image01.gif
    Texture active : 33984
    Objet 1
    Texture liée : ./Images/Image02.JPG
    Texture active : 33985
    TEXTURE0 est bien active pour Objet 0, avec la bonne image.
    TEXTURE1 est bien active pour Objet 1, avec la bonne image.
    Résultat à l'écran => rien.
    Mes deux objets sont noirs.

    Si j'active la TEXTURE0, quelque soit mon objet, j'obtiens :

    Objet 0
    Texture liée : ./Images/Image01.gif
    Texture active : 33984
    Objet 1
    Texture liée : ./Images/Image02.JPG
    Texture active : 33984
    TEXTURE0 est bien active pour Objet 0, avec la bonne image.
    TEXTURE0 est bien active pour Objet 1, avec la bonne image.
    Résultat à l'écran => Objet 1 (la sphère) est correctement affiché, objet 0 (mon plan) est noir.

    Si j'active la TEXTURE1, quelque soit mon objet, j'obtiens :

    Objet 0
    Texture liée : ./Images/Image01.gif
    Texture active : 33985
    Objet 1
    Texture liée : ./Images/Image02.JPG
    Texture active : 33985
    TEXTURE1 est bien active pour Objet 0, avec la bonne image.
    TEXTURE1 est bien active pour Objet 1, avec la bonne image.
    Résultat à l'écran => Mes deux objets sont blanc.

    Sachant que dans ma fonction de création de texture, j'active TEXTURE0 avant la création de la texture propre à mon plan (Objet 0), et TEXTURE1 avant la création de la texture propre à ma sphère (Objet 1).

    J'oublie peut être quelque chose?

  5. #5
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 905
    Points : 220 164
    Points
    220 164
    Billets dans le blog
    126
    Par défaut
    Si un objet sur lequel on applique une texture est blanc:
    -> La texture n'est pas valide
    Si un objet sur lequel on applique une texture est noir:
    -> La texture est valide (utilisable par OpenGL) mais elle est mal appliqué / ou les coordonnées sont fausses

    J'ai l'impression que vous n'avez pas tout compris sur les textures d'OpenGL.
    En fait, la première texture utilisé par un objet, c'est toujours la texture 0. Pour chaque texture, OpenGL vous renvoie (associe) un id (un numéro). Celui peut être tout est n'importe quoi (aucune raison que ce soit 0 ou 1 ou autre chose)
    Il n'y a pas de rapport entre un id et la texture active. Vous pouvez avoir 32 textures actives (je suis un peu étonné du nombre) mais vous pouvez aussi chargé plus de 32 textures dans votre programme (par contre, on ne pourra donc pas les utiliser toutes en même temps)

  6. #6
    Membre régulier
    Profil pro
    Inscrit en
    Février 2005
    Messages
    208
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 208
    Points : 109
    Points
    109
    Par défaut
    Effectivement, je n'avais pas tout à fait compris le fonctionnement des textures apparemment.

    Il y avait effectivement un problème lors de la création de ma texture.

    En effet, travaillant (pour la première fois) sur WebGL, le chargement de l'image à utiliser comme texture reprend le principe des images HTML.
    Il est possible de savoir si l'image à été chargée par le navigateur en utilisant la fonction mon_image.onload() = function{ //Image chargée, je peux la lier à ma texture OpenGL }.

    En me penchant sur ma fonction onload(), je me suis rendu compte que la texture WebGL que je passais à ma fonction d'affectation d'image à une texture, n'était pas correctement incrémenté.

    Donc, pour la texture de mon Objet1, Objet2, Objet3...Objetn, ma fonction d'affectation recevait toujours Objet3D[Objetn].

    J'ai résolu ce problème en créant un attribut "Num" à mon, correspondant à ma position dans mon tableau d'Objet3D.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    var i=0;
    while(i < TabObjets3D.length)
    {
          TabObjets3D[i].TextureGL = gl.createTexture();
          TabObjets3D[i].TextureGL.image = new Image();
          TabObjets3D[i].TextureGL.image.onload = function()
          {
                handleLoadedTexture(gl,TabObjets3D[this.Num].TextureGL);
          }
          TabObjets3D[i].TextureGL.image.src = TabObjets3D[i].TabMaterial[j].Texture;
          TabObjets3D[i].TextureGL.image.Num = i;
          i++
    }

    Edit : Un p'tit screen pour montrer que ça fonctionne et que je suis CONTENT!


+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Copie de pages web, seul le dernier fichier n'est pas vide
    Par Beginner. dans le forum Développement Web en Java
    Réponses: 3
    Dernier message: 13/12/2014, 00h28
  2. cet objet n'est pas une fonction
    Par Goundy dans le forum jQuery
    Réponses: 12
    Dernier message: 25/01/2010, 00h47
  3. Réponses: 2
    Dernier message: 19/06/2009, 16h39
  4. Quel objet utiliser pour afficher une liste de plusieurs résultats
    Par jlachapelle dans le forum Windows Forms
    Réponses: 1
    Dernier message: 15/08/2008, 20h33
  5. L'objet Query est-il une collection ?
    Par shawty dans le forum Struts 1
    Réponses: 2
    Dernier message: 05/04/2007, 21h01

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo