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 :

Défauts de précision dans le rendu


Sujet :

OpenGL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Août 2013
    Messages
    309
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2013
    Messages : 309
    Par défaut Défauts de précision dans le rendu
    Bonsoir, je fais face à un étrange problème de précision dans mon simulateur de système solaire : Au plus les planètes sont éloignées de l'origine du repère 3D au plus les sommets semblent avoir subi un décalage. Jugez par vous-mêmes ce qu'il en est de Pluton :

    Nom : AlphaSun-2021-05-10-23-23-24-67.gif
Affichages : 170
Taille : 700,8 Ko

    Voici le résultat si je mets Pluton sur l'orbite de Mercure :

    Nom : AlphaSun-2021-05-10-23-26-11-83.gif
Affichages : 153
Taille : 1,13 Mo

    Pour modéliser des sphères j'utilise une classe "PRIM_Solid" qui contient un VBO et des méthodes d'initialisation et de rendu :

    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
    typedef struct PRIM_VBO
    {
        vector<float> coordVertices;
        vector<float> coordTex;
        vector<float> normales;
        vector<float> couleurs;
        GLuint bufferVRAM;
        GLuint VAO;
        vector<GLuint> textures;
    }PRIM_VBO;
     
    class PRIM_Solid
    {
        private :
     
        PRIM_VBO data;
     
        public :
     
        void InitBrick(const float width,const float depth,const float height,glm::vec4 color=glm::vec4(1.0,1.0,1.0,1.0),GLuint tex=0);
        void InitSphere(const float radius,const int slices,const int stacks,glm::vec4 color=glm::vec4(1.0,1.0,1.0,1.0),GLuint tex=0);
        void InitDisk(const float radiusInt,const float radiusExt,const int slices,glm::vec4 color=glm::vec4(1.0,1.0,1.0,1.0),GLuint tex=0);
        void InitVBO(void);
        void Draw(GLuint shaderUser,glm::mat4 projection=glm::mat4(1.0),glm::mat4 modele=glm::mat4(1.0),glm::mat4 vue=glm::mat4(1.0));
        void Free(void);
    };
    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
    void PRIM_Solid::InitSphere(const float radius,const int slices,const int stacks,glm::vec4 color,GLuint tex)
    {
        float latitude=-90.0,longitude;
        glm::vec3 sommets[4];
        glm::vec2 coordtex[4];
        glm::vec3 normales[4];
        const float deltaLong=360.0/slices;
        const float deltaLat=180.0/stacks;
     
        while(1)
        {
            longitude=0.0;
            while(1)
            {
                ...// Calcul coordonnées vertices, coordonnées texture, normales
     
                longitude+=deltaLong;
                if(longitude>=360.0)
                    break;
            }
     
            latitude+=deltaLat;
            if(latitude>=90.0)
                break;
        }
     
        ////////////////////////////////////////////////////////////
     
        int compteur=0;
        while(1)
        {
            data.couleurs.push_back(color.x);		//Ajout couleur
            data.couleurs.push_back(color.y);
            data.couleurs.push_back(color.z);
            data.couleurs.push_back(color.w);
     
            compteur++;
            if(compteur==data.coordVertices.size())
                break;
        }
     
        data.textures.push_back(tex);		//Ajout texture
     
        ////////////////////////////////////////////////////////////
     
        InitVBO();
    }
    Initialisation VBO :

    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
    void PRIM_Solid::InitVBO(void)
    {
        glGenVertexArrays(1,&data.VAO);
        glGenBuffers(1,&data.bufferVRAM);
     
        glBindVertexArray(data.VAO);
        glBindBuffer(GL_ARRAY_BUFFER,data.bufferVRAM);
     
        glBufferData(GL_ARRAY_BUFFER,data.coordVertices.size()*sizeof(float)+data.coordTex.size()*sizeof(float)+data.normales.size()*sizeof(float)+data.couleurs.size()*sizeof(float),NULL,GL_STREAM_DRAW);
     
        glBufferSubData(GL_ARRAY_BUFFER,0,data.coordVertices.size()*sizeof(float),&data.coordVertices[0]);
        glBufferSubData(GL_ARRAY_BUFFER,data.coordVertices.size()*sizeof(float),data.coordTex.size()*sizeof(float),&data.coordTex[0]);
        glBufferSubData(GL_ARRAY_BUFFER,data.coordVertices.size()*sizeof(float)+data.coordTex.size()*sizeof(float),data.normales.size()*sizeof(float),&data.normales[0]);
        glBufferSubData(GL_ARRAY_BUFFER,data.coordVertices.size()*sizeof(float)+data.coordTex.size()*sizeof(float)+data.normales.size()*sizeof(float),data.couleurs.size()*sizeof(float),&data.couleurs[0]);
     
        glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,3*sizeof(float),(void*)0);
        glEnableVertexAttribArray(0);
     
        glVertexAttribPointer(1,2,GL_FLOAT,GL_FALSE,2*sizeof(float),(void*)(data.coordVertices.size()*sizeof(float)));
        glEnableVertexAttribArray(1);
     
        glVertexAttribPointer(2,3,GL_FLOAT,GL_FALSE,3*sizeof(float),(void*)(data.coordVertices.size()*sizeof(float)+data.coordTex.size()*sizeof(float)));
        glEnableVertexAttribArray(2);
     
        glVertexAttribPointer(3,4,GL_FLOAT,GL_FALSE,4*sizeof(float),(void*)(data.coordVertices.size()*sizeof(float)+data.coordTex.size()*sizeof(float)+data.normales.size()*sizeof(float)));
        glEnableVertexAttribArray(3);
     
        glBindVertexArray(0);
        glBindBuffer(GL_ARRAY_BUFFER,0);
    }
    Rendu sphère :

    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
    void PRIM_Solid::Draw(GLuint shaderUser,glm::mat4 projection,glm::mat4 modele,glm::mat4 vue)
    {
        glUseProgram(shaderUser);
     
        glUniformMatrix4fv(glGetUniformLocation(shaderUser,"projection"),1,false,glm::value_ptr(projection));
        glUniformMatrix4fv(glGetUniformLocation(shaderUser,"modele"),1,false,glm::value_ptr(modele));
        glUniformMatrix4fv(glGetUniformLocation(shaderUser,"vue"),1,false,glm::value_ptr(vue));
     
        glBindVertexArray(data.VAO);
     
        glBindTexture(GL_TEXTURE_2D,data.textures[0]);
     
        if(data.textures[0]==0)
            glUniform1i(glGetUniformLocation(shaderUser,"textured"),false);
        else
            glUniform1i(glGetUniformLocation(shaderUser,"textured"),true);
     
        glDrawArrays(GL_TRIANGLES,0,data.coordVertices.size()/3);
     
        glBindVertexArray(0);
    }
    Pour représenter les planètes j'utilise une structure "Planete" contenant entre autres une instance de PRIM_Solid et les caractéristiques orbitales.
    J'utilise une classe Map contenant un tableau d'instances de "Planete" ainsi que les shaders, les matrices et les méthodes d'initialisation et de rendu.

    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
    void Map::chargeCaracPlanetes(Bureau *bur)
    {
        FILE *fichier=fopen("AlphaSun/data/CaracPlanetes.txt","r");
     
        Planete p;
     
        while(1)
        {
            ...// Chargement données depuis fichier
     
            p.sphere.InitSphere(p.rayon,40,40,glm::vec4(1.0,1.0,1.0,1.0),loadTexture(cheminTex.c_str(),1));		//Initialisation sphère
     
            planetes.push_back(p);
        }
     
        fclose(fichier);
    }
    Le rendu :

    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
    void Map::rendu(Camera *cam,Bureau *bur)
    {
        if(!bur->getPleinEcran())
            matriceProjection=glm::perspective(FOVY,4.0/3,NEAR,FAR);
        else
            matriceProjection=glm::perspective(FOVY,(double)bur->getRatio(),NEAR,FAR);
     
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
     
        matriceVue=glm::lookAt(glm::vec3(cam->getPosition().x,cam->getPosition().y,cam->getPosition().z),
                                     glm::vec3(cam->getCible().x,cam->getCible().y,cam->getCible().z),
                                     glm::vec3(0.0,0.0,1.0));
     
        matriceModele=glm::mat4(1.0);
     
        renduSystSolaire(bur,cam);
    }
    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
    void Map::renduSystSolaire(Bureau *bur,Camera *cam)
    {
        int compteur=0;
     
        while(1)
        {
            glUseProgram(shaderPlanetes);
     
            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     
    	glm::mat4 sauvegarde=matriceModele;
     
            matriceModele=glm::rotate(matriceModele,(float)planetes[compteur].LongitudeNoeudAsc,glm::vec3(0.0,0.0,1.0));
            matriceModele=glm::rotate(matriceModele,(float)planetes[compteur].inclinaisonOrbite,glm::vec3(1.0,0.0,0.0));
            matriceModele=glm::rotate(matriceModele,(float)planetes[compteur].angleRevolution,glm::vec3(0.0,0.0,1.0));
            matriceModele=glm::translate(matriceModele,glm::vec3(planetes[compteur].demiGrandAxe,0.0,0.0));
            matriceModele=glm::rotate(matriceModele,(float)-planetes[compteur].angleRevolution,glm::vec3(0.0,0.0,1.0));
            matriceModele=glm::rotate(matriceModele,(float)-planetes[compteur].inclinaisonOrbite,glm::vec3(1.0,0.0,0.0));
            matriceModele=glm::rotate(matriceModele,(float)-planetes[compteur].LongitudeNoeudAsc,glm::vec3(0.0,0.0,1.0));
            matriceModele=glm::rotate(matriceModele,(float)(angleObliquite*180/M_PI),glm::vec3(vecteurRotation.x,vecteurRotation.y,vecteurRotation.z));
            matriceModele=glm::rotate(matriceModele,(float)planetes[compteur].angleRotation,glm::vec3(0.0,0.0,1.0));
    	//Transformations géométriques
     
            planetes[compteur].sphere.Draw(shaderPlanetes,matriceProjection,matriceModele,matriceVue);		//Rendu
     
            matriceModele=sauvegarde;
     
            compteur++;
            if(compteur==planetes.size())
                break;
        }
    }
    Les shaders :

    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
    #version 330 core
     
    layout (location=0) in vec3 vertex;
    layout (location=1) in vec2 coordTex;
    layout (location=2) in vec3 normale;
    layout (location=3) in vec4 color;
     
    uniform mat4 projection;
    uniform mat4 modele;
    uniform mat4 vue;
     
    out vec2 coordTexFrag;
    out vec4 couleurFrag;
     
    void main(void)
    {
    	vec4 vertex2=vec4(vertex,1.0);
     
    	vec4 vertexApresTranf=modele*vertex2;
     
    	vec4 normaleApresTransf=modele*vec4(normale,0.0);
     
    	gl_Position=projection*vue*modele*vertex2;
     
    	coordTexFrag=coordTex;
     
    	vec3 rayonLumiere=vec3(0.0-vertexApresTranf.x,0.0-vertexApresTranf.y,0.0-vertexApresTranf.z);
     
    	float luminosite=dot(normalize(vec3(normaleApresTransf.x,normaleApresTransf.y,normaleApresTransf.z)),normalize(rayonLumiere));
    	//Eclairage
     
    	luminosite=clamp(luminosite,0.05,1.0);
     
    	couleurFrag=vec4(luminosite*color[0],luminosite*color[1],luminosite*color[2],1.0);
    }
    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
    #version 330 core
     
    uniform sampler2D tex;
     
    in vec2 coordTexFrag;
    in vec4 couleurFrag;
     
    out vec4 FragColor;
     
    uniform bool textured;
     
    void main(void)
    {
    	if(!textured)
    		FragColor=couleurFrag;
    	else
    		FragColor=texture(tex,coordTexFrag.xy)*couleurFrag;
    }
    Voilà en gros comment fonctionne ce simulateur, je ne vois pas d'où pourrait venir ce problème de précision, il doit bien y avoir un moyen de le corriger étant donné que des logiciels comme Stellarium n'ont pas ce problème.

    Merci en avant pour votre aide.

  2. #2
    Expert confirmé

    Avatar de dragonjoker59
    Homme Profil pro
    Software Developer
    Inscrit en
    Juin 2005
    Messages
    2 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Bas Rhin (Alsace)

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

    Informations forums :
    Inscription : Juin 2005
    Messages : 2 035
    Billets dans le blog
    12
    Par défaut
    Bonjour !

    De quel ordre sont les distances pour les orbites ?
    Il faut savoir que les flottants ont une précision limitée, que ce soit pour les décimales, comme pour les parties entières (pour les grandes valeurs), d'où ma question.
    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 éclairé
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Août 2013
    Messages
    309
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2013
    Messages : 309
    Par défaut
    Salut, ça va jusqu'à une valeur de 5900898440. J'ai essayé de stocker les coordonnées des vertices dans des long double mais après ça plus rien ne s'affichait à l'écran, d'ailleurs comment gérer cela dans les shaders ? Il n'y a pas de type long double en GLSL

  4. #4
    Membre éclairé
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Août 2013
    Messages
    309
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2013
    Messages : 309
    Par défaut
    Du coup pas d'idée ?

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


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

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

    Informations forums :
    Inscription : Mai 2008
    Messages : 27 157
    Billets dans le blog
    152
    Par défaut
    Bonjour,

    Pour les long double, ils sont certainement sur 8 octets, il faut donc changer la configuration des tampons pour correspondre à ce changement.
    Pour le problème de distance, il serait plus intéressant de faire une mise à l'échelle, ou alors de faire un déplacement de tous les objets afin que ceux qui soient dans la vision, soit toujours "proches", mais il faudrait faire attention que cela n'implique pas la modification des tampons GPU à chaque déplacement de caméra.
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  6. #6
    Expert confirmé
    Avatar de Kannagi
    Homme Profil pro
    cyber-paléontologue
    Inscrit en
    Mai 2010
    Messages
    3 226
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : cyber-paléontologue

    Informations forums :
    Inscription : Mai 2010
    Messages : 3 226
    Par défaut
    Citation Envoyé par KevinduC Voir le message
    d'ailleurs comment gérer cela dans les shaders ? Il n'y a pas de type long double en GLSL
    Oui encore heureux tu n'aura jamais du long double en CG
    Et meme les doubles ,non seulement les doubles prenne plus en mémoire , mais sont bien plus long, mais en plus ça demande d'avoir des unités de calcul spécifique pour (et sur une CG actuelle , vu qu'il y'a des milliers d'unité de float , il faudrait donc avoir des milliers de double).
    Néanmoins sur sur les carte graphique Nvidia haut de gamme (et non Intel graphics ou AMD), il y a certaine carte qui ont du double en hard, mais en beaucoup moins que les float ,ils sont donc du coup plus "long" , ce ne sais pas si ça peut s’utiliser via des shader , mais avec CUDA certainement.

    Sinon le long double n'est pas forcément du double (8 octets) , c'est souvent du double , mais ça peut être plus (par exemple le float 80 bits d'intel).
    Donc c'est pas forcément un truc très utilisé , et même déconseillé vu la portabilité du truc :p

Discussions similaires

  1. Réponses: 1
    Dernier message: 21/11/2006, 17h00
  2. [XSLT] inserer un espace dans le rendu html
    Par hysah dans le forum XSL/XSLT/XPATH
    Réponses: 5
    Dernier message: 04/11/2006, 11h45
  3. Problème de précision dans une requête
    Par Le Pharaon dans le forum Requêtes et SQL.
    Réponses: 4
    Dernier message: 09/08/2006, 14h16
  4. mettre par défaut un champ dans liste déroulante
    Par zouzou1010 dans le forum AWT/Swing
    Réponses: 1
    Dernier message: 09/05/2006, 14h12
  5. [XSLT] Variable par défaut ou non dans un 'IF'
    Par Johnbob dans le forum XSL/XSLT/XPATH
    Réponses: 4
    Dernier message: 25/01/2004, 17h00

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