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 :

Précision des coordoonnées de textures


Sujet :

OpenGL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert Avatar de Djakisback
    Profil pro
    Inscrit en
    Février 2005
    Messages
    2 023
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 2 023
    Par défaut Précision des coordonnées de textures
    Salut,
    j'ai un léger souci pour l'affichage de sous-textures. J'ai par exemple une texture de 256*128 contenant des sous-textures de 16 x 16. Voici en gros comment je calcule les coordonnées des sous-textures :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    	float x = 0, y = 0;
    	float xFactor = framesWidth / (float)texture.getWidth();
    	float yFactor = framesHeight / (float)texture.getHeight();
    	float xPixelFactor = 1 /  (float)texture.getWidth();
    	for (y = 0; y < 1; y += yFactor) {
    		for (x = 0; x < 1; x += xFactor + xPixelFactor) {
    			frames.add(new Frame(name, texture.getTextureObject(), x, y, (float)(x + xFactor) - xPixelFactor, (float)(y + yFactor), framesWidth, framesHeight));
    		}
    	}
    Ceci représentant les coordonnées OGL (dans l'espace 0 -> 1) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    x, y, (float)(x + xFactor) - xPixelFactor, (float)(y + yFactor)
    J'ai introduit un xFactor qui représente la valeur d'un pixel dans l'espace (0 -> 1) pour essai.

    Pour vérifier j'ai mis un fond de couleur différente à chaque sous-texture de 16 x 16 dans l'image source.
    Le problème est qu'à l'affichage on peut voir que les coordonnées des sous-textures ne sont pas bonnes. Le découpage est mauvais et les couleurs de fond se décalent au fur et à mesure (sur x et sur y). J'ai essayé pas mal de trucs mais sans succès. Quelqu'un aurait-il une idée sur la question ?
    Merci d'avance.

  2. #2
    Membre Expert
    Avatar de shenron666
    Homme Profil pro
    avancé
    Inscrit en
    Avril 2005
    Messages
    2 582
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : avancé

    Informations forums :
    Inscription : Avril 2005
    Messages : 2 582
    Par défaut
    premièrement, pour un maximum de précision, tu devrais calculer tes coordonnées en entiers et transformer en float uniquement à la fin
    ton float étant une approximation que utilise et cumule, tu cumules l'imprécision aussi

    ensuite il faut aussi que tu penses à prendre en compte les sous pixels dans tes coordonées
    si tu prends comme exemple une texture contenant 4 sous-textures, la coordonnée de texture (0.5, 0.5) se situe pile au centre et concerne 4 pixels de 4 sous-textures
    cela te donnera des effets indésirables dans le cadre du filtrage de texture, où la couleur de la sous-texture voisine va être utilisée pour le lissage du bord
    il faut donc calculer un décalage de la moitié d'un pixel pour éviter ces problèmes
    Tutoriels OpenGL
    Je ne répondrai à aucune question en MP
    - Si c'est simple tu dis que c'est compliqué et tu le fait
    - Si c'est compliqué tu dis que c'est simple et tu le sous-traite ou le fait faire par un stagiaire.

  3. #3
    Membre Expert Avatar de Djakisback
    Profil pro
    Inscrit en
    Février 2005
    Messages
    2 023
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 2 023
    Par défaut
    Je te remercie pour ta réponse, effectivement c'est beaucoup mieux de convertir en float au dernier moment. (Je n'y avais pas pensé car actuellement j'utilise uniquement des ^2 et le problème de précision des float ne se pose jamais il me semble)

    En revanche j'ai du mal avec le principe du décalage d'un demi-pixel. Si j'ai une image de 32*16 avec 2 textures les coordonnées en x seront bien 0->15 et 16->31 ? Ce qui me donne bien 0.0->0.5 et 0.5->1 ?
    Voici le nouveau code si quelqu'un a une idée

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    for (y = 0; y < texture.getHeight(); y += framesHeight) {
    	for (x = 0; x < texture.getWidth(); x += framesWidth) {
    		frames.add(new Frame(name, texture.getTextureObject(),
    		x / texture.getWidth(), y / texture.getHeight(),
    		((x + framesWidth) / texture.getWidth()), (y + framesHeight) / texture.getHeight(),
    		framesWidth, framesHeight));
    	}
    }
    Il faudrait que je décale à gauche et à droite, sauf pour la texture tout à gauche et celle toute à droite ?

    texture.getWidth() étant la largeur en pixel de l'image
    framesWidth étant la largeur en pixel de chaque sous-texture (chaque sous-texture ayant les mêmes dimensions)
    (D'ailleurs dans l'exemple de la FAQ les coordonnées semblent bien être 0.5 et 0.5)

  4. #4
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Mars 2005
    Messages
    249
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Bas Rhin (Alsace)

    Informations forums :
    Inscription : Mars 2005
    Messages : 249
    Par défaut
    Citation Envoyé par Djakisback Voir le message
    Si j'ai une image de 32*16 avec 2 textures les coordonnées en x seront bien 0->15 et 16->31 ? Ce qui me donne bien 0.0->0.5 et 0.5->1 ?
    Justement non, si j'ai bien suivi l'intervention de shenron, 0->15 ; 16->31 donnerait 0.0->0.5-0.5/(float)width ; 0.5+0.5/(float)width ->1 . à tester...

  5. #5
    Membre Expert Avatar de Djakisback
    Profil pro
    Inscrit en
    Février 2005
    Messages
    2 023
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 2 023
    Par défaut
    Merci je viens de tester et ça marche... presque
    Le résultat est meilleur mais c'est pas encore ça. Voici donc comment je procède maintenant :


    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
    for (y = 0; y < texture.getHeight(); y += framesHeight) {
    	for (x = 0; x < texture.getWidth(); x += framesWidth) {
    		left = (float)x / texture.getWidth();
    		bottom = (float)y / texture.getHeight();
    		right = (float)(x + framesWidth) / texture.getWidth();
    		top = (float)(y + framesHeight) / texture.getHeight();
     
    		frames.add(new Frame(name, texture.getTextureObject(),
    				left + left / texture.getWidth(),
    				bottom + bottom / texture.getHeight(),
    				right - right / texture.getWidth(),
    				top - top / texture.getHeight(),
    				framesWidth, framesHeight));
    	}
    }

    Et voici 3 screens de ce que j'obtiens :






    à partir ce cette texture source :


    Est-ce que j'aurais fait une erreur grossière ?

    Je poste aussi l'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
     
    float texX = sprite.getCurrentFrame().getX2();
    float texY = sprite.getCurrentFrame().getY2();
     
    ...
    this.getGL().glBegin(GL.GL_POLYGON);
    this.getGL().glTexCoord2f(sprite.getCurrentFrame().getX(), texY);
    this.getGL().glVertex2f(sprite.getVertex(0).getX(), sprite.getVertex(0).getY());
    this.getGL().glTexCoord2f(texX, texY);
    this.getGL().glVertex2f(sprite.getVertex(1).getX(), sprite.getVertex(1).getY());
    this.getGL().glTexCoord2f(texX, sprite.getCurrentFrame().getY());
    this.getGL().glVertex2f(sprite.getVertex(2).getX(), sprite.getVertex(2).getY());
    this.getGL().glTexCoord2f(sprite.getCurrentFrame().getX(), sprite.getCurrentFrame().getY());
    this.getGL().glVertex2f(sprite.getVertex(3).getX(), sprite.getVertex(3).getY());
    this.getGL().glEnd();
    Le résultat est identique que j'utilise des float ou des double ainsi que glTexCoord2f() ou glTexCoord2d().
    Images attachées Images attachées     

  6. #6
    Membre Expert

    Profil pro
    Programmeur
    Inscrit en
    Août 2002
    Messages
    1 091
    Détails du profil
    Informations personnelles :
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Programmeur

    Informations forums :
    Inscription : Août 2002
    Messages : 1 091
    Par défaut
    cela s'appelle le filtrage bilinéaire et c'est normal si tu l'as activé (ou s'il est activé par défaut).

    Il y a d'autres formes de filtrages plus avancées (bicubique, lanczos, hq3x/hq4x, etc), mais qui ne seront que partiellement accélérés par le hardware (avec l'aide de shaders).

    Enfin tout dépend ce que tu veux faire..

    LeGreg

    Mon site web | Mon blog | Mes photos | Groupe USA
    > BONJOUR, JE SUIS NOUVEAU SUR CE FORUM
    > presse la touche caps lock, stp
    > OH.. MERCI C EST BEAUCOUP PLUS FACILE COMME CA

  7. #7
    Membre Expert
    Avatar de shenron666
    Homme Profil pro
    avancé
    Inscrit en
    Avril 2005
    Messages
    2 582
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : avancé

    Informations forums :
    Inscription : Avril 2005
    Messages : 2 582
    Par défaut
    Citation Envoyé par Djakisback Voir le message
    En revanche j'ai du mal avec le principe du décalage d'un demi-pixel. Si j'ai une image de 32*16 avec 2 textures les coordonnées en x seront bien 0->15 et 16->31 ? Ce qui me donne bien 0.0->0.5 et 0.5->1 ?
    LeGreg parle de texel, moi je tape dans le demi pixel, ce qui est suffisant pour éviter les bavures (et le dernier pixel peut-etre suffisamment important pour le pas le "sacrifier" intégralement)

    concrètement une image de 32 * 16 donnera non pas
    0.0->0.5 et 0.5->1.0 sur les U
    et 0.0->1.0 sur les V
    mais
    0,015625->0,484375 et 0,515625->0,984375 sur les U
    0,03125->0,96875 sur les V

    calculé à partir des coordonnées que tu donnes moins la moitié d'un pixel sur chaque axe
    ton image faisant 32 pixels de large, un demi-pixel fait 1/64 = 0,015625 sur l'axe U et 1/32 = 0.03125 sur l'axe V
    on ajoute le demi-pixel à la coordonnée entrante et on le soustrait à la coordonnée sortante

    0.5 est non pas une coordonnée située sur un pixel mais entre 2 pixels
    comme l'a expliqué LeGreg, la couleur des pixels environnants est utilisée pour calculer le filtrage
    enfin visiblement tu as compris comment tout cela fonctionnait, bon courage pour la suite
    Tutoriels OpenGL
    Je ne répondrai à aucune question en MP
    - Si c'est simple tu dis que c'est compliqué et tu le fait
    - Si c'est compliqué tu dis que c'est simple et tu le sous-traite ou le fait faire par un stagiaire.

  8. #8
    Membre Expert

    Profil pro
    Programmeur
    Inscrit en
    Août 2002
    Messages
    1 091
    Détails du profil
    Informations personnelles :
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Programmeur

    Informations forums :
    Inscription : Août 2002
    Messages : 1 091
    Par défaut
    Citation Envoyé par shenron666 Voir le message
    LeGreg parle de texel, moi je tape dans le demi pixel, ce qui est suffisant pour éviter les bavures (et le dernier pixel peut-etre suffisamment important pour le pas le "sacrifier" intégralement)
    Non ce n'est pas moi qui ai parlé de demi-texel (ou demi-pixel). J'ai juste dit que les formules toutes faites ça ne marche que pour les situations toutes faites. Mais pour le reste il n'y a pas d'autre solution que les maths sur la feuille de papier ce qui dans ce cas là revient à calculer la couverture des pixels sur sa texture. La formule que les gens sortent habituellement (décaler d'un demi pixel), n'a aucun sens ici à cause du zoom x4 ou x16 ou x685 (cf les screenshots que djak a posté).

    LeGreg

    Mon site web | Mon blog | Mes photos | Groupe USA
    > BONJOUR, JE SUIS NOUVEAU SUR CE FORUM
    > presse la touche caps lock, stp
    > OH.. MERCI C EST BEAUCOUP PLUS FACILE COMME CA

  9. #9
    Membre Expert Avatar de Djakisback
    Profil pro
    Inscrit en
    Février 2005
    Messages
    2 023
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 2 023
    Par défaut
    Salut Shenron,
    je te remercie pour ces précisions, tout fonctionne maintenant à merveille en sacrifiant un demi-pixel
    C'est d'ailleurs ce que j'avais plus ou moins essayé de faire au début en sacrifiant un pixel entier avec : float xPixelFactor = 1 / (float)texture.getWidth(); mais je m'y prenais très mal ^^

    [edit] LeGreg, pourtant quand je zoom/dézoom les proportions semblent bien rester les mêmes.

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

Discussions similaires

  1. [Javascript] Précision des float
    Par NicoNours dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 15/03/2006, 09h12
  2. Réponses: 4
    Dernier message: 03/03/2006, 16h03
  3. Export : définition de la précision des arrondis
    Par Aurèl90 dans le forum Access
    Réponses: 14
    Dernier message: 13/12/2005, 16h45
  4. [Sécurité] Eviter des erreurs de textures ....
    Par cyber_N dans le forum OpenGL
    Réponses: 14
    Dernier message: 09/09/2005, 16h49
  5. Réponses: 17
    Dernier message: 04/08/2005, 14h49

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