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 :

[GLSL] Calcul de la position écran dans un vertex shader


Sujet :

OpenGL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre très actif Avatar de oxyde356
    Homme Profil pro
    Ingénieur Recherche Imagerie
    Inscrit en
    Février 2006
    Messages
    797
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur Recherche Imagerie

    Informations forums :
    Inscription : Février 2006
    Messages : 797
    Par défaut [GLSL] Calcul de la position écran dans un vertex shader
    Salut tout le monde,

    Je suis en train de bosser sur une simulation de fluide où j'ai besoin de faire un texture lookup dans un vertex shader. Pour cela j'ai besoin de calculer la position écran du point que je dessine à partir de ses coordonnées 3D. Voilà ce que je fais (modelview est à l'identité donc je ne m'en sers pas) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    vec4 Position = gl_ProjectionMatrix * vec4(VertexPosition, 1.0);
    gl_Position = Position;
    Position.xy = (Position.xy / Position.w) * 0.5 + 0.5;
    ...
    vec4 color = texture(mySampler, Position.xy);
    Ce qui marche parfaitement sur une carte ATI (HD 5870) mais ne fonctionne pas sur une NVIDIA (GTX 580), les drivers ont bien été mis à jours.

    Description de l'erreur : Les shaders compilent, mais apparemment il y a une erreur de précision sur mon calcul avec la carte nvidia. En effet, pour pouvoir débugger je coloris mes points en vert quand la position calculé correspond à la position réel (celle rasterizé par la carte graphique) et sinon en rouge. Pour avoir cette info j'effectue une premiere passe ou je dessine mes points dans une texture et dans ma 2° passe ou j'essaye de calculer à la main la position écran de mon point je fais un lookup sur la texture de la passe précédente et je vérifie qu'elle contient bien mon point.
    Sur une carte ATI dans tous les cas les points sont verts.
    Sur une carte NVIDIA ils sont généralement verts, mais quelques fois une ligne ou une colonne devient rouge (je dessine une grille de points).
    Je m'en rend compte en positionnant les points à un certain endroit ou en les déplaçant très lentement.

    Je pense que le problème survient quand les points approchent la limite entre deux pixels et qu'une erreur de précision survient dans mon calcul du point par rapport à celui qui est fait par la carte graphique.

    Sur un autre forum on m'a orienté vers le mot clé "precise" qui permet d'empêcher certaines optimisations sur les calculs flottant surtout sur les cartes nvidia mais cela n'a pas fonctionné.

    Quelqu'un a-t-il une idée à mon insoluble problème

    Merci

  2. #2
    Membre émérite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2011
    Messages
    618
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2011
    Messages : 618
    Par défaut
    Salut,

    Essaye un truc du genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    // floor pour avoir le pixel correspondant, +0.5 pour être au milieu du pixel, et /textureSize pour retourner en [0, 1].
    vec2 positionTex = (floor(Position.xy*textureSize) + 0.5) / textureSize;
    vec4 color = texture(mySampler, positionTex);
    Il faut absolument que ta coord de texture tape au milieu d'un pixel si tu souhaite avoir sa valeur. Si tu tape au bord d'un pixel le résultat n'est pas le même sur NVidia et ATI (en gros, ATI considère le pixel de gauche, NVidia le pixel de droite).

  3. #3
    Membre très actif Avatar de oxyde356
    Homme Profil pro
    Ingénieur Recherche Imagerie
    Inscrit en
    Février 2006
    Messages
    797
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur Recherche Imagerie

    Informations forums :
    Inscription : Février 2006
    Messages : 797
    Par défaut
    Salut et merci pour ta réponse.
    Malheureusement j'ai déjà testé et cela n'a pas fonctionné
    Quand j'évalue la distance entre mon point 3D calculé erroné (avec ta formule aussi) et le centre du pixel, je trouve une valeur = 0.5 + epsilon (128 / 255 quand je le visualise sur la texture) alors que pour qu'il soit valide la distance devrait être inférieur à 0.5.
    On dirait que c'est l'opération
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    vec4 Position = gl_ProjectionMatrix * vec4(VertexPosition, 1.0);
    qui me donne quelque chose d'imprécis mais ça ne me parait pas possible vu que gl_Position est aussi l'input du rasterizer :/
    En fait pour te donner une image du problème, ton calcul avec le floor où floor(X) == Y donne dans mon cas où le point est à une certaine coordonnée qui fait que cela ne fonctionne pas : floor(X) == Y + 1 (car l'epsilon du à l'imprécision doit faire un truc du genre floor(0.99 + e) == 1.0 alors que cela devrait faire 0.0)

    Need heeeelllppp

  4. #4
    Membre émérite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2011
    Messages
    618
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2011
    Messages : 618
    Par défaut
    Hmmm, essaye de remplacer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Position.xy = (Position.xy / Position.w) * 0.5 + 0.5;
    Par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Position.xy = fma(Position.xy / Position.w, 0.5, 0.5);
    fma(a, b, c) a une meilleur précision que a*b+c, ça peut peut être marcher...
    Sinon je ne vois pas trop, ça m'étonne qu'il y ait des erreurs de précisions sur des calculs aussi "simple". A mon avis, c'est plus un "0.5" qui manque quelque part, mais où ?...

  5. #5
    Membre émérite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2011
    Messages
    618
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2011
    Messages : 618
    Par défaut
    Ou alors, les points que tu dessines ne tombent-il pas pile entre 2 pixels écran ?

    Par exemple, avec un viewport de 2x2 et un view volume centré en [-1, 1] (une projection matrix à l'identité), il faut bien dessiner les points en -0.5 et 0.5 pour tomber au milieu du pixel, et non en -1, 0 ou 0, 1.

    Que vaut gl_ProjectionMatrix, VertexPosition et la taille de ton viewport dans ton cas ?

  6. #6
    Membre très actif Avatar de oxyde356
    Homme Profil pro
    Ingénieur Recherche Imagerie
    Inscrit en
    Février 2006
    Messages
    797
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur Recherche Imagerie

    Informations forums :
    Inscription : Février 2006
    Messages : 797
    Par défaut
    Hey, je connaissais pas l'opérateur "fma" mais j'en frémis si ça marche et il y a moyen :p
    Si en effet je pense que mes points erronés sont quasi à cheval entre 2 pixels (c'est ce qui me fait penser à une erreur de précision) et que mon calcul fait que le pixel A est choisi alors que le rasterizer trouve que c'est le B.
    J'utilise une projection ortho (0, 60, 0, 60, -1, 0), VertexPosition appartient au domaine ([0.0 ; 60.0[, [0.0 ; 60.0[) et mon viewport est (0, 0, 512, 512).

    Merci pour l'aide que tu m'apportes ^^

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