Discussion: flat-shading algorithm and shaders. [OpenGL 3.x]

  1. #1
    Membre expérimenté
    Avatar de Luke spywoker
    Homme Profil pro
    Etudiant informatique autodidacte
    Inscrit en
    juin 2010
    Messages
    1 037
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant informatique autodidacte

    Informations forums :
    Inscription : juin 2010
    Messages : 1 037
    Points : 1 718
    Points
    1 718

    Par défaut flat-shading algorithm and shaders.

    Bonjours les GL,

    j'ai le problème suivant: je n'arrive pas a faire fonctionner le concept de shading.

    Ou plutôt a implémenter le fonctionnement d'une source lumineuse qui projetterai de la lumière sur un polyèdre

    ayant une couleur uniforme pour toutes ses faces.

    Le but étant bien sur de calculer le taux de lumière réfracter donc a illuminer mon polyèdre de multiples intensités d'une couleurs,

    selon la position de la source de lumière.

    J'utilise pour l'instant l'algorithme de flat-shading: qui se base sur un calcule de deux vecteurs.

    1. Le vecteur de position du vertex a colorer.

    2. La source de lumière.

    Et qui renvoie un cosinus dont ont peut se servir de la valeur (a condition que valeur == -1.0-0 ; // face a la lumière)

    pour multiplier la valeur de départ de la couleur.

    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
    if (cos(alpha) < 0) {
     
      // The vertex and the light vectors make an angle of 90°-270°.
     
      // So the light is refracted in relationship to his position.
     
      color = vertex * -cos(alpha) ;
     
    }
    else {
     
      // The vertex is not lighted.
     
      color = color ;
    }
    :note: En fait le flat-shading n'est pas exact mais acceptable comme algorithme d'illumination et il demande peu de calcule.

    ---

    J'ai essayer de multiples manières et selon le procéder suivant:

    en implémentant la fonction de calcule du multiplicateur dans le shader.

    ---

    Bon un du code est bien mieux que du blabla.

    Voici ma méthode d'affichage:

    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
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
     
     
     void Ellipsoid::display() {
     
        GLint color_id    ;
        GLint mv_matrix   ;
        GLint cam_matrix  ;
        GLint proj_matrix ;
     
        GLint light_src_id ;
     
        light_src_id = glGetUniformLocation(program, "lighting_pos") ;
     
        color_id   = glGetUniformLocation(program, "color_vec") ;
     
        mv_matrix  = glGetUniformLocation(program, "mv_matrix") ;
        cam_matrix = glGetUniformLocation(program, "cam_matrix") ;
        proj_matrix = glGetUniformLocation(program, "proj_matrix") ;
     
        // So that we can get the value for debugging purpose.
        GLint testing_id = glGetUniformLocation(program, "testing") ;
     
        glUseProgram(program) ;
     
     
        glUniformMatrix4fv(proj_matrix, 1, GL_FALSE, glm::value_ptr(proj))    ;
        glUniformMatrix4fv(cam_matrix,  1, GL_FALSE, glm::value_ptr(camera))  ;
        glUniformMatrix4fv(mv_matrix,   1, GL_FALSE, matrix.data() )  ;
     
        GLint position_id    = glGetAttribLocation(program,  "position");
        GLint text_sampler2D = glGetUniformLocation(program, "myTextureSampler");
        GLint texture_id     = glGetAttribLocation(program,  "vertexUV");
        GLint intensity_id   = glGetUniformLocation(program,  "color_intensity");
     
     
        glUniform1i(text_sampler2D, 0);
     
        glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
        glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, 0, NULL) ;
     
        glBindBuffer(GL_ARRAY_BUFFER, buffers[1]);
        glVertexAttribPointer(texture_id,  2, GL_FLOAT, GL_FALSE, 0, NULL);
     
        glEnableVertexAttribArray(position_id);
        glEnableVertexAttribArray(texture_id);
     
        /** Start draw ellipsoid_sphere. **/
     
        int offset = 0 ;
     
        for (uint32_t c=0 ; c < number_of_quads ; c++) {
     
          if (use_colors) {
     
            if (uni) { // Boolean member value.
              if (not colors.empty()) {
                glUniform4fv(color_id, 1, colors.at(0).get_vector()) ;
              }
            }
            else {
              if (not colors.empty()) {
     
                glUniform4fv(light_src_id, 1, glm::value_ptr(lighting_vector)) ;
     
                glUniform4fv(color_id, 1, colors.at(c % colors.size()).get_vector()) ;
     
                #if 1
                // We grab the value of the output of the shadering function for displaying it's value: It always equal zero.zero.
                float testing_val  = 0 ;
                glGetUniformfv(program, testing_id, &testing_val) ;
     
                 fprintf(stderr,"-> %.12f\n", testing_val) ;
                #endif
     
              }
            }
          }
          else if (use_textures) { // Boolean member value.
     
            if (uni) {
              glBindTexture(GL_TEXTURE_2D, texture_ids.at(0));
            }
            else {
              glBindTexture(GL_TEXTURE_2D, texture_ids.at(c));
            }
          }
          if (show_faces) { // Boolean member value.
            glDrawArrays(GL_TRIANGLE_FAN, offset,  4);
          }
          if (show_lines) { // Boolean member value.
            glUniform4fv(color_id, 1, lines_colors.get_vector()) ;
            glDrawArrays(GL_LINE_LOOP, offset,  4);
          }
     
          offset += 4 ;
     
        }
     
        /** End draw ellipsoid_sphere. **/
     
     
     
        glDisableVertexAttribArray(position_id);
        glDisableVertexAttribArray(texture_id);
     
     
     
     
    }
    Vous voyez bien que j'implémente les vertices dans un buffer mais le(s) couleur(s) sont passer par une variable uniform (Une couleur par face).

    Du coup Il m'est pas possible de multiplier un vertice par une fonction qui renvoie le cosinus des deux vecteurs.

    Autrement dit d'implémenter la fonction de calcule autre part que dans le shader.

    Et en plus comme je ne peut accéder au vertice qui est dans le buffer mais je ne peut utiliser ma méthode de flat-shading

    qui consiste a multiplier la valeur de la couleur d'origine du polyèdre par le cosinus si celui ci < 0.

    ---

    Le shader de vertice est le suivant:


    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
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    #version 150 core
    //#version 430 core
     
    in vec4 position ;
     
    out VS_OUT {
     
        vec4 color;                               
     
    } vs_out ;                                     
     
    #if 1
    float test(vec3 vertex, vec3 lighting_pos) {
     
      float vertex_vec_length = length(vertex) ;
     
      float lighting_pos_length = length(lighting_pos) ;
     
      vertex = normalize(vertex) ;  lighting_pos = normalize(lighting_pos) ;
     
      float cos_of_dot = (vertex[0] * lighting_pos[0] + vertex[1] * lighting_pos[1] + vertex[2] * lighting_pos[2]) / (vertex_vec_length * lighting_pos_length) ;
     
      return cos_of_dot ;
     
    }
    #endif
     
    uniform vec4 color_vec  ;                                
     
    uniform vec4 lighting_pos ;
     
     
    uniform mat4 mv_matrix ;                                              
    uniform mat4 cam_matrix ;
    uniform mat4 proj_matrix ;
     
    uniform float color_intensity ;
     
    #if 1
    uniform float testing = test(position, lighting_pos) ;
    #endif
     
    void main(void)                               
    {
     
     
        gl_Position  = proj_matrix * cam_matrix * mv_matrix * position ;
        vs_out.color = color_vec ; // The goal is to multiplicate: color_vec * test(position, lighting_pos) but test(...) return always 0.0  ;                 
     
        //vs_out.color = color_vec * test(position, lighting_pos) ; // In this case it display nothing....
    }
    Le problème est aussi que la même fonction nommer test(...) implémenté dans le code source fonctionne: elle ne renvoie pas toujours zéro.

    par contre dans le shader elle ne fonctionne pas (elle renvoie toujours zero.zero) ce qui me parait bizarroid...

    ---

    Toute aide, conseils, réponses est la bienvenue.

    Merci de bien vouloir éclairé ma lanterne.

    P.S: J'ai essayer de maintes fois et j'avais même réussis a implémenter le concept en thrash python.
    Pour faire tes armes:
    Use du présent pour construire ton futur sinon use de ce que tu as appris auparavant.
    Et sois toujours bien armé avant de te lancer.
    Le hasard ne sourit qu'aux gens préparés...
    Site: Website programmation international (www.open-source-projects.net)
    Site: Website imagerie 3D (www.3dreaming-imaging.net)
    Testez aux moins pendant une semaine l'éditeur avec terminaux intégrées it-edit Vous l'adopterai sûrement !
    FUN is HARD WORK !!!

  2. #2
    Expert éminent

    Avatar de dragonjoker59
    Homme Profil pro
    Software Developer
    Inscrit en
    juin 2005
    Messages
    1 739
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Software Developer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : juin 2005
    Messages : 1 739
    Points : 9 012
    Points
    9 012
    Billets dans le blog
    3

    Par défaut

    Salut!

    Que ce soit en flat ou en smooth shading, la fonction de calcul de l'éclairage ne change pas.
    Ce qui change, c'est la manière dont tu calcules tes normales.
    Hors là, tu ne passes pas les normales de ton polyèdre au shader (on les met généralement dans le VBO, avec la position et les coordonnées de texture).
    Commence par faire ça, et ça te simplifiera grandement la vie.
    Si vous ne trouvez plus rien, cherchez autre chose...

    Vous trouverez ici des tutoriels OpenGL moderne.
    Mon moteur 3D: Castor 3D, presque utilisable (venez participer, il y a de la place)!
    Un projet qui ne sert à rien, mais qu'il est joli (des fois) : ProceduralGenerator (Génération procédurale d'images, et post-processing).

  3. #3
    Membre expérimenté
    Avatar de Luke spywoker
    Homme Profil pro
    Etudiant informatique autodidacte
    Inscrit en
    juin 2010
    Messages
    1 037
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant informatique autodidacte

    Informations forums :
    Inscription : juin 2010
    Messages : 1 037
    Points : 1 718
    Points
    1 718

    Par défaut

    Merci pour la réponse,

    est-t-il possible:

    1. d'utiliser plusieurs buffer en entrée de shader.

    Comme cela je pourrai mieux contrôler les couleurs.

    2. de récupérer les données du buffer.

    Si oui, comment ?

    Merci pour vos réponses.

    P.S: Un petit patron de shader m'aiderai, merci.
    Pour faire tes armes:
    Use du présent pour construire ton futur sinon use de ce que tu as appris auparavant.
    Et sois toujours bien armé avant de te lancer.
    Le hasard ne sourit qu'aux gens préparés...
    Site: Website programmation international (www.open-source-projects.net)
    Site: Website imagerie 3D (www.3dreaming-imaging.net)
    Testez aux moins pendant une semaine l'éditeur avec terminaux intégrées it-edit Vous l'adopterai sûrement !
    FUN is HARD WORK !!!

  4. #4
    Expert éminent

    Avatar de dragonjoker59
    Homme Profil pro
    Software Developer
    Inscrit en
    juin 2005
    Messages
    1 739
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Software Developer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : juin 2005
    Messages : 1 739
    Points : 9 012
    Points
    9 012
    Billets dans le blog
    3

    Par défaut

    1) Oui, tu peux avoir plusieurs VBO en entrée d'un shader, il faut juste que leur contenu corresponde.
    Supposons que tu as dans ton premier VBO les positions, normales, et coordonnées de texture, et dans le second VBO les couleurs.
    Le layout du premier VBO ressemblerait à ceci : V0N0T0,V1N1T1, ..., VnNnTn.
    Le layout du second VBO doit alors ressembler à ceci: C0,C1, ..., Cn.
    Tu pourrais même envisager d'avoir un VBO pour chaque composante d'un sommet (donc 4 dans cet exemple):
    V0,V1,...,Vn
    N0,N1,...,Nn
    T0,T1,...,Tn
    C0,C1,...,Cn

    2) Pour la récupération des données d'un buffer, ce n'est pas possible via les VBO, car le vertex shader aura en entrée pour notre exemple Vi, Ni, Ti, Ci.
    Si tu veux faire autrement (pour les couleurs par exemple), il te faut alors stocker les couleurs dans un autre buffer : UBO si tu en as peu (il est limité en taille) ou SSBO si tu en as beaucoup (il n'est pas limité en taille, mais les accès sont un peu moins rapides qu'un UBO).
    Et il te faut alors stocker l'index de la couleur voulue dans une composante d'un VBO.

    3) Un patron de shader ?
    En voilà un (non testé) pour une lumière directionnelle (donc sans position, et avec une direction).
    J'utilise un SSBO pour le stockage des couleurs, et un UBO pour le stockage des données de la lumière.

    Vertex Shader :
    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
    #version 450
     
    in vec3 position;
    in vec3 normal;
    in vec2 texture;
    in int index;
     
    uniform mat4 world;
    uniform mat4 view;
    uniform mat4 projection;
     
    out vec3 pxl_position;
    out vec3 pxl_normal;
    out vec3 pxl_texture;
    flat out int pxl_index;
     
    void main()
    {
      vec4 pos = vec4( position, 1.0 );
      pos = view * world * pos;
      pxl_position = pos.xyz;
      pxl_normal = mat3( transpose( inverse( world ) ) ) * normal;
      pxl_texture = texture;
      pxl_index = index;
      gl_Position = projection * pos;
    }
    Fragment Shader :
    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
    39
    40
    41
    42
    43
    44
    45
    46
    #version 450
     
    in vec3 pxl_position;
    in vec3 pxl_normal;
    in vec3 pxl_texture;
    in int pxl_index;
     
    uniform vec3 cameraWorldPos;
     
    layout( std130, binding = 0 ) uniform Light
    {
      vec3 lightColour;
      vec3 lightDirection;
      vec3 lightIntensity; // (ambient, diffuse, specular)
    }
     
    layout( std430, binding = 1 ) buffer Colours
    {
      vec4 colour[];
    };
     
    out vec4 out_fragColour;
     
    void main()
    {
      // On récupère la couleur de l'objet :
      vec4 objColour = colour[pxl_index];
     
      // Composante ambiante de la lumière.
      vec3 lightAmbient = lightColour * lightIntensity.x;
     
      // Composante diffuse de la lumière.
      vec3 lightDir = normalize( -lightDirection );
      vec3 normal = normalize( pxl_normal );
      float diffuseFactor = max( dot( normal, lightDir ), 0.0);
      vec3 lightDiffuse = diffuseFactor * lightColour * lightIntensity.y;
     
      // Composante spéculaire de la lumière.
      vec3 viewDir = normalize( cameraWorldPos - pxl_position);
      vec3 reflectDir = reflect(-lightDir, normal );
      float specularFactor = pow( max( dot( viewDir, reflectDir ), 0.0 ), 32 );
      vec3 lightSpecular = specularFactor * lightColour * lightIntensity.z;
     
      // Combine les 4 pour obtenir le résultat.
      out_fragColour = objColour * vec4( lightAmbient + lightDiffuse + lightSpecular, 1.0 );
    }
    Si vous ne trouvez plus rien, cherchez autre chose...

    Vous trouverez ici des tutoriels OpenGL moderne.
    Mon moteur 3D: Castor 3D, presque utilisable (venez participer, il y a de la place)!
    Un projet qui ne sert à rien, mais qu'il est joli (des fois) : ProceduralGenerator (Génération procédurale d'images, et post-processing).

  5. #5
    Membre expérimenté
    Avatar de Luke spywoker
    Homme Profil pro
    Etudiant informatique autodidacte
    Inscrit en
    juin 2010
    Messages
    1 037
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant informatique autodidacte

    Informations forums :
    Inscription : juin 2010
    Messages : 1 037
    Points : 1 718
    Points
    1 718

    Par défaut

    Merci pour la réponse,

    je ne suis pas un pro de OpenGL donc j'apprécie ton aide et je regrette l'ancien OpenGL (<= 2.0).

    Car je ne comprends pas la abbréviation UBO nie SSBO par contre un VBO c'est un (Vertex Buffer Object ???) si je me trompe pas.

    Quand ont utilise des abbréviations il vaut mieux mettre la définition entre parenthèse au moins une fois.

    Car même si je savait ce qu'ils veulent dire d'autres pourraient tomber sur ce poste.

    Encore merci aussi pour les patrons je vais les essayer...

    :Info: Les 2 types de shaders ont pour extension de nom de fichier: glslv (Vertex shader) et glslf (Fragment shader).
    Pour faire tes armes:
    Use du présent pour construire ton futur sinon use de ce que tu as appris auparavant.
    Et sois toujours bien armé avant de te lancer.
    Le hasard ne sourit qu'aux gens préparés...
    Site: Website programmation international (www.open-source-projects.net)
    Site: Website imagerie 3D (www.3dreaming-imaging.net)
    Testez aux moins pendant une semaine l'éditeur avec terminaux intégrées it-edit Vous l'adopterai sûrement !
    FUN is HARD WORK !!!

  6. #6
    Expert éminent

    Avatar de dragonjoker59
    Homme Profil pro
    Software Developer
    Inscrit en
    juin 2005
    Messages
    1 739
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Software Developer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : juin 2005
    Messages : 1 739
    Points : 9 012
    Points
    9 012
    Billets dans le blog
    3

    Par défaut

    UBO => Uniform Buffer Object (dans le core depuis la version 3.1 : GL wiki).
    SSBO => Shader Storage Buffer Object (dans le core depuis la version 4.3 : GL wiki).

    Moi je ne regrette absolument pas les glBegin/glEnd ni les display lists

    :info: Il n'y a pas d'extension standard pour les fichiers de shader GLSL
    Si vous ne trouvez plus rien, cherchez autre chose...

    Vous trouverez ici des tutoriels OpenGL moderne.
    Mon moteur 3D: Castor 3D, presque utilisable (venez participer, il y a de la place)!
    Un projet qui ne sert à rien, mais qu'il est joli (des fois) : ProceduralGenerator (Génération procédurale d'images, et post-processing).

  7. #7
    Membre expérimenté
    Avatar de Luke spywoker
    Homme Profil pro
    Etudiant informatique autodidacte
    Inscrit en
    juin 2010
    Messages
    1 037
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant informatique autodidacte

    Informations forums :
    Inscription : juin 2010
    Messages : 1 037
    Points : 1 718
    Points
    1 718

    Par défaut

    Il n'y a pas d'extension standard pour les fichiers de shader GLSL
    Peut être que ce n'est pas normer mais mon éditeur que j'ai créer reconnait ses extension et son dans sa liste d'extensions pris en charge.

    Et du coup la coloration syntaxique pour les deux extension sont fort pratique.

    Encore merci, comme je fait un break après un demi-paver de lecture de l'âge des dinosaures de la programmation 3D (OpenGL et DirectX), je verrai tes patrons shaders un peu plus tard.

    D'ailleurs ce vieux bouquin explique tout ce que vous fournis OpenGL automatiquement rastérisation, z-buffer, Bresenham, ... clipping.

    Tout a la mains sans invoquer aucune fonction OpenGL ou presque...

    Merci gracieusement pour ton aide, en espérant que j'arrive a mes fins d'ailleurs j'ai créer un générateur de simple ou double dégradé afin de colorier mes polyèdre.
    Pour faire tes armes:
    Use du présent pour construire ton futur sinon use de ce que tu as appris auparavant.
    Et sois toujours bien armé avant de te lancer.
    Le hasard ne sourit qu'aux gens préparés...
    Site: Website programmation international (www.open-source-projects.net)
    Site: Website imagerie 3D (www.3dreaming-imaging.net)
    Testez aux moins pendant une semaine l'éditeur avec terminaux intégrées it-edit Vous l'adopterai sûrement !
    FUN is HARD WORK !!!

  8. #8
    Expert éminent

    Avatar de dragonjoker59
    Homme Profil pro
    Software Developer
    Inscrit en
    juin 2005
    Messages
    1 739
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Software Developer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : juin 2005
    Messages : 1 739
    Points : 9 012
    Points
    9 012
    Billets dans le blog
    3

    Par défaut

    Et bien ajoute les extension .glsl, .vert, .frag, .geom, .ctrl, .eval, .comp à ton éditeur, du coup
    Si vous ne trouvez plus rien, cherchez autre chose...

    Vous trouverez ici des tutoriels OpenGL moderne.
    Mon moteur 3D: Castor 3D, presque utilisable (venez participer, il y a de la place)!
    Un projet qui ne sert à rien, mais qu'il est joli (des fois) : ProceduralGenerator (Génération procédurale d'images, et post-processing).

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

Discussions similaires

  1. algorithme branch and bound
    Par logo98 dans le forum Mathématiques
    Réponses: 3
    Dernier message: 31/03/2009, 00h57
  2. "Programming Vertex, Geometry and Pixel Shaders" gratuitement
    Par Bakura dans le forum Développement 2D, 3D et Jeux
    Réponses: 6
    Dernier message: 04/01/2009, 15h26
  3. Programmation algorithme branch and bound en C
    Par mca_183 dans le forum Général Algorithmique
    Réponses: 4
    Dernier message: 13/01/2006, 15h37
  4. pas d'éclairage du tout avec un shader "phong shading&q
    Par captainSeb dans le forum OpenGL
    Réponses: 3
    Dernier message: 06/06/2005, 11h48

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