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 :

Récupérer la couleur d'un pixel


Sujet :

OpenGL

  1. #1
    Membre habitué
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2006
    Messages
    116
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2006
    Messages : 116
    Points : 163
    Points
    163
    Par défaut Récupérer la couleur d'un pixel
    Bonjour,

    Afin d'implémenter plusieurs algorithme de remplissage en c++ pour effectuer une comparaison sur leur efficacité / rendement etc... je suis amené dans l'un d'eux à devoir récupérer la valeur d'un pixel de coordonnées (x,y).

    La couleur de fond choisie est le noir (0,0,0) ou , la couleur de tracé choisie est le blanc (1 , 1 , 1) ou (255 , 255 , 255).

    Mon problème est le suivant, lorsque j'utilise glreadpixels(...) la couleur récupérée est toujours celle de la couleur de fond (noir). Je procède comme suit :

    Je trace un polygone

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     glColor3f(1.0 , 1.0 , 1.0);
        glBegin(GL_LINE_LOOP);
     
        /**
        Tracé du contour du polygone en blanc (1,1,1)
        */
        for(int i = 0 ; i < nb_sommet ; i++)
        {
            glVertex2f(POLY[i]->x , POLY[i]->y);
        }
        glEnd();
    Lequel est initialisé comme suit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Point * POLY[255] = {
            new Point(-50 , 80)
            , new Point(0 , 20)
            , new Point(60 , 40)
            , new Point(40 , -50)
            , new Point(-50 , -50)
        };
    Je prend un point dont je suis certain qu'il est à l'intérieur du polygone et je décrémente son abscisse. Je trace au fur à mesure les points sur lesquels je travail en rouge (1,0,0) ou (255,0,0)... si et seulement si la couleur du pixel en question est noir.

    Pour commencer, j'aimerais que l'algorithme s'arrete quand il rencontre un pixel blanc (ce qui est obligatoire puisqu'on démarre à l'intérieur du polygone). Le soucis c'est qu'une fois arrivé sur l'un des côté tracé en blanc, il ne récupère que du noir... J'utilise la fonction comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Point first = Point(0 , 0);
    unsigned char * pixel = new unsigned char[18];
    //...
    glReadPixels(first.x , first.y , 1 , 1 , GL_RGBA , GL_UNSIGNED_BYTE , pixel);
    Plus étrange encore, si je trace un point BLANC aux coordonnées (0,0) et que je tente
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    glReadPixels(0 , 0 , 1 , 1 , GL_RGBA , GL_UNSIGNED_BYTE , pixel);
    C'est quand même la couleur du fond récupérée. Pour être sur que les (0,0,0) ne soient pas dus à des valeurs NULLES j'ai testé en changeant la couleur de fond, par exemple en bleu (0.0.1) et c'est bien cette couleur de fond qui est récupérée et non pas la couleur du tracé.

    De temps en temps je récupère une valeur totalement absurde (142,2,96) par exemple, qui n'a rien avoir avec les trois couleurs simples que j'ai dans ma fenêtre. Je me demande donc si ça n'est pas un problème de coordonnées.

    J'utilise
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    glOrtho(-1000 , 1000 , -1000 , 1000 , -1 , 1);
    au début de mon code.

    Par ailleurs, j'ai pu voir qu'il fallait souvent utiliser glreadpixels avec la fonction glreadbuffer() mais je n'ai jamais compris à quoi correspondent les front buffer, back buffer etc... lequel choisir ?

  2. #2
    Membre du Club Avatar de clodo13
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    67
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Octobre 2007
    Messages : 67
    Points : 58
    Points
    58
    Par défaut
    c'est du c#?

  3. #3
    Membre habitué
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2006
    Messages
    116
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2006
    Messages : 116
    Points : 163
    Points
    163
    Par défaut
    Autant pour moi je n'ai pas précisé, il s'agit de c++.

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

    Informations professionnelles :
    Activité : avancé

    Informations forums :
    Inscription : Avril 2005
    Messages : 2 524
    Points : 5 183
    Points
    5 183
    Par défaut
    si tu travailles en double buffer, tu dessines dans le BACK
    il faut donc vérifier avec glreadbuffer que tu vas bien lire le back buffer

    il faut lire ton pixel avec glReadPixel après avoir dessiné ton polygone (logique) et avant de faire un swap, à moins que tu n'en fasses pas ?

    par contre le polygone que tu dessines n'est qu'un contour : glBegin(GL_LINE_LOOP)
    donc il est "rempli" par la couleur de fond
    pour moi c'est logique que n'importe quel point à l'intérieur soit de la couleur de fond
    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.

  5. #5
    Membre habitué
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2006
    Messages
    116
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2006
    Messages : 116
    Points : 163
    Points
    163
    Par défaut
    Bin justement. Le polygone que je construit doit être initialement rempli par la couleur de fond et entouré par du blanc.

    Ainsi, je dois changer la couleur de chacun des pixels ayant la couleur de fond par une autre (rouge par exemple) Le problème c'est qu'une fois mes indices correspondant aux points de contour blanc, le glreadpixels ne les trouve que de la couleur du fond et pas de la couleur de contour.

    il faut lire ton pixel avec glReadPixel après avoir dessiné ton polygone (logique) et avant de faire un swap, à moins que tu n'en fasses pas ?
    C'est effectivement déjà le cas.

    Pour le buffer, j'ai mis glReadBuffer(GL_BACK); juste avant le premier glreadpixels();

    Voici le code complet de ma fonction 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
    int couleur_bg[3] = {0 , 0 , 0};
     
    void affichage(void)
    {
        glOrtho(-1000 , 1000 , -1000 , 1000 , -1 , 1);
     
        /**
        Nombre de sommets du polygone
        */
        int nb_sommet = 5;
        unsigned char * pixel = new unsigned char[18];
        int couleur_contour[3] = {1 , 1 , 1};
        int couleur_contenu[3] = {1 , 0 , 0};
     
        stack<Point> pile;
     
        /**
        Liste des sommets du polygone
        */
        Point * POLY[255] = {
            new Point(-50 , 80)
            , new Point(0 , 20)
            , new Point(60 , 40)
            , new Point(40 , -50)
            , new Point(-50 , -50)
        };
     
        Point first = Point(0 , 0);
        Point cur;
     
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     
        glColor3f(1.0 , 1.0 , 1.0);
        glBegin(GL_LINE_LOOP);
     
        /**
        Tracé du contour du polygone en blanc (1,1,1)
        */
        for(int i = 0 ; i < nb_sommet ; i++)
        {
            glVertex2f(POLY[i]->x , POLY[i]->y);
        }
        glEnd();
     
        glReadBuffer(GL_BACK);
        glReadPixels(first.x , first.y , 1 , 1 , GL_RGBA , GL_UNSIGNED_BYTE , pixel);
     
        /**
        FIN - Tracé du contour du polygone en blanc (1,1,1)
        */
     
        glColor3f(couleur_contenu[0] , couleur_contenu[1] , couleur_contenu[2]);
     
     
        if(pixel[0] == couleur_bg[0] * 255 && pixel[1] == couleur_bg[1] * 255 && pixel[2] == couleur_bg[2] * 255)
        {
            pile.push(first);
     
            while(pile.size() != 0 && pile.size() < 50000)
            {
                cur.x = pile.top().x;
                cur.y = pile.top().y;
     
                pile.pop();
     
                glBegin(GL_POINTS);
                glVertex2f(cur.x , cur.y);
                glEnd();
     
                glReadPixels(cur.x , cur.y +1 , 1 , 1 , GL_RGBA , GL_UNSIGNED_BYTE , pixel);
                if((int)pixel[0] == couleur_bg[0] * 255 && (int)pixel[1] == couleur_bg[1] * 255 && (int)pixel[2] == couleur_bg[2] * 255)
                    pile.push(Point(cur.x , cur.y +1));
     
                glReadPixels(cur.x , cur.y -1 , 1 , 1 , GL_RGBA , GL_UNSIGNED_BYTE , pixel);
                if((int)pixel[0] == couleur_bg[0] * 255 && (int)pixel[1] == couleur_bg[1] * 255 && (int)pixel[2] == couleur_bg[2] * 255)
                    pile.push(Point(cur.x , cur.y -1));
     
                glReadPixels(cur.x +1 , cur.y , 1 , 1 , GL_RGBA , GL_UNSIGNED_BYTE , pixel);
                if((int)pixel[0] == couleur_bg[0] * 255 && (int)pixel[1] == couleur_bg[1] * 255 && (int)pixel[2] == couleur_bg[2] * 255)
                    pile.push(Point(cur.x +1 , cur.y));
     
                glReadPixels(cur.x -1 , cur.y , 1 , 1 , GL_RGBA , GL_UNSIGNED_BYTE , pixel);
                if((int)pixel[0] == couleur_bg[0] && (int)pixel[1] * 255 == couleur_bg[1] * 255 && (int)pixel[2] == couleur_bg[2] * 255)
                    pile.push(Point(cur.x -1 , cur.y));
     
            }
        }
     
        glFlush();
        glutSwapBuffers();
    }

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

    Informations professionnelles :
    Activité : avancé

    Informations forums :
    Inscription : Avril 2005
    Messages : 2 524
    Points : 5 183
    Points
    5 183
    Par défaut
    ok je comprend mieux, tu testes un des sommets de ton polygone
    sauf que vu ton code, tu ne risques pas d'avoir de résultat probant
    tout d'abord, un avertissement, c'est une mauvaise idée de vouloir travailler au pixel avec opengl vu qu'il s'agit d'un traitement vectoriel
    je te rassure, il est tout de même possible de s'en sortir

    je commence par une question : en quelle résolution travailles tu ?
    cette question est important car tu travailles sur des pixels

    logiquement on pourrait penser que tu as une résolution de 2000 x 2000 pixels
    ce qui m'étonnerai

    donc pour une résolution de largeur x hauteur, il faut que configure ton glOrtho correctement pour travailler au pixel, par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    glOrtho(0 , largeur, 0 , hauteur, -1 , 1);
    si tu veux que la coordonnée 0, 0 se situe au centre de l'écran :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    float midLarg = ((float)largeur) / 2.0f;
    float midHaut = ((float)hauteur) / 2.0f;
    glOrtho(-midLarg, midLarg, -midHaut, midHaut, -1 , 1);
    de façon à ce qu'une coordonnée en 2D d'un vertex corresponde le plus exactement possible à un pixel
    sachant qu'il y a toujours un risque d'erreur et qu'un glVertex2i(10, 10) n'allume pas le pixel en 10, 10 mais en 11, 10 par exemple

    autre chose : le glReadPixels
    il n'est pas basé sur les coordonnées de ton glOrtho
    donc si ta coordonnée 0, 0 est au centre de l'écran
    pour trouver le pixel allumé par glVertex(0, 0) il faut un glReadPixel aux coordonnées (largeur / 2, hauteur / 2)
    avec un risque de tomber à côté
    c'est pourquoi je te conseille de travailler avec la coordonnée en 0, 0 dans le coin gauche (haut ou bas selon ta préférence) de ton écran

    en me relisant, je me dit que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    glOrtho(0 , largeur, 0 , hauteur, -1 , 1);
    n'est peut-etre pas exact
    puisqu'en partant de 0, pour avoir largeur pixels, il fadrait prendre (largeur - 1)

    bon le principal c'est que tu comprennes le pourquoi de ton problème
    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.

  7. #7
    Membre habitué
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2006
    Messages
    116
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2006
    Messages : 116
    Points : 163
    Points
    163
    Par défaut
    Alors voilà la taille de ma fenetre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    const int g_nWidth = 1280;
    const int g_nHeight = 1024;
    glutInitWindowSize(g_nWidth, g_nHeight);
    La résolution que j'utilise est 1280x1024

    J'ai modifié le glortho comme tu l'as précisé :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    float midLarg = ((float)g_nWidth) / 2.0f;
    float midHaut = ((float)g_nHeight) / 2.0f;
    glOrtho(-midLarg, midLarg, -midHaut, midHaut, -1 , 1);
    Problème maintenant, je n'ai que le contour de mon polygone qui est tracé

    En revanche, il suffit que réduise la feneter et que je l'agrandisse a nouveaux pour que le tracé du contour disparaisse et à la place je me retrouve avec mon tracé rouge qui va vers la gauche sans s'arreter...

    Aussi j'ai cette impression : Une fois le tracé du contour terminé, le tracé rouge prend la relève mais "ailleurs" et c'est "ailleurs" que le glreadpixels est effectué... Quand j'agrandi a nouveau la fenêtre le blanc disparait mais le rouge apparait... donc s'il se base là dessus normal qu'il ne trouve pas de blanc.

    Je suis paumé

    Voilà mon code complet :

    main.cpp
    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
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    #include <windows.h>
    #include <GL/glut.h>
    #include <GL/gl.h>
    #include <GL/glu.h>
    #include <stack>
    #include <iostream>
     
    #include "Point.h"
    #include "fonctions.h"
     
    using namespace std;
     
    int nWindowID;
    const int g_nWidth = 1280;
    const int g_nHeight = 1024;
     
    void affichage(void);
    void attente(void);
    void clavier(unsigned char touche, int x, int y);
     
    int couleur_bg[3] = {0 , 0 , 0};
     
    int main(int argc,char *argv[])
    {
    	// initialisation de GLUT
    	glutInit(&argc, argv);
     
        glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
        glutInitWindowSize(g_nWidth, g_nHeight);
     
        int g_nWindowID = glutCreateWindow("Remplissage par germes");
     
        glutDisplayFunc(affichage);
        glutIdleFunc(attente);
     
        glClearColor(couleur_bg[0], couleur_bg[1], couleur_bg[2], 0);
     
        glutMainLoop();
     
    	return 0;
    }
     
    void affichage(void)
    {
        float midLarg = ((float)g_nWidth) / 2.0f;
        float midHaut = ((float)g_nHeight) / 2.0f;
        glOrtho(-midLarg, midLarg, -midHaut, midHaut, -1 , 1);
     
        /**
        Nombre de sommets du polygone
        */
        int nb_sommet = 5;
        unsigned char * pixel = new unsigned char[18];
        int couleur_contour[3] = {1 , 1 , 1};
        int couleur_contenu[3] = {1 , 0 , 0};
     
        stack<Point> pile;
     
        /**
        Liste des sommets du polygone
        */
        Point * POLY[255] = {
            new Point(-50 , 80)
            , new Point(0 , 20)
            , new Point(60 , 40)
            , new Point(40 , -50)
            , new Point(-50 , -50)
        };
     
        Point first = Point(0 , 0);
        Point cur;
     
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     
        glColor3f(1.0 , 1.0 , 1.0);
        glBegin(GL_LINE_LOOP);
     
        /**
        Tracé du contour du polygone en blanc (1,1,1)
        */
        for(int i = 0 ; i < nb_sommet ; i++)
        {
            glVertex2f(POLY[i]->x , POLY[i]->y);
        }
        glEnd();
     
        glReadBuffer(GL_BACK);
        glReadPixels(first.x , first.y , 1 , 1 , GL_RGBA , GL_UNSIGNED_BYTE , pixel);
     
        /**
        FIN - Tracé du contour du polygone en blanc (1,1,1)
        */
     
        glColor3f(couleur_contenu[0] , couleur_contenu[1] , couleur_contenu[2]);
     
     
        if(pixel[0] == couleur_bg[0] * 255 && pixel[1] == couleur_bg[1] * 255 && pixel[2] == couleur_bg[2] * 255)
        {
            pile.push(first);
     
            while(pile.size() != 0 && pile.size() < 500000)
            {
                cur.x = pile.top().x;
                cur.y = pile.top().y;
     
                pile.pop();
     
                glBegin(GL_POINTS);
                glVertex2f(cur.x , cur.y);
                glEnd();
     
                glReadBuffer(GL_BACK);
                glReadPixels(cur.x , cur.y +1 , 1 , 1 , GL_RGBA , GL_UNSIGNED_BYTE , pixel);
                if((int)pixel[0] == couleur_bg[0] * 255 && (int)pixel[1] == couleur_bg[1] * 255 && (int)pixel[2] == couleur_bg[2] * 255)
                    pile.push(Point(cur.x , cur.y +1));
     
                glReadPixels(cur.x , cur.y -1 , 1 , 1 , GL_RGBA , GL_UNSIGNED_BYTE , pixel);
                if((int)pixel[0] == couleur_bg[0] * 255 && (int)pixel[1] == couleur_bg[1] * 255 && (int)pixel[2] == couleur_bg[2] * 255)
                    pile.push(Point(cur.x , cur.y -1));
     
                glReadPixels(cur.x +1 , cur.y , 1 , 1 , GL_RGBA , GL_UNSIGNED_BYTE , pixel);
                if((int)pixel[0] == couleur_bg[0] * 255 && (int)pixel[1] == couleur_bg[1] * 255 && (int)pixel[2] == couleur_bg[2] * 255)
                    pile.push(Point(cur.x +1 , cur.y));
     
                glReadPixels(cur.x -1 , cur.y , 1 , 1 , GL_RGBA , GL_UNSIGNED_BYTE , pixel);
                if((int)pixel[0] == couleur_bg[0] && (int)pixel[1] * 255 == couleur_bg[1] * 255 && (int)pixel[2] == couleur_bg[2] * 255)
                    pile.push(Point(cur.x -1 , cur.y));
     
            }
        }
     
        glFlush();
        glutSwapBuffers();
    }
     
    /* Fréquence de rafraichissement de l'image */
    void attente(void)
    {
    	static int nWaitUntil = glutGet(GLUT_ELAPSED_TIME);
    	int nTimer = glutGet(GLUT_ELAPSED_TIME);
    	if(nTimer >= nWaitUntil)
    	{
    		glutPostRedisplay();
    		nWaitUntil = nTimer + 10000000;
    	}
    }
    Point.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #ifndef POINT_H
    #define POINT_H
     
    class Point
    {
        public :
        int x , y;
        Point(int , int);
        Point();
    };
     
    #endif
    Point.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #include "Point.h"
     
    Point::Point(int a = 0 , int b = 0)
    {
        x = a;
        y = b;
    }
     
    Point::Point()
    {
        x = 0;
        y = 0;
    }

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

    Informations professionnelles :
    Activité : avancé

    Informations forums :
    Inscription : Avril 2005
    Messages : 2 524
    Points : 5 183
    Points
    5 183
    Par défaut
    Citation Envoyé par jbeaussier Voir le message
    Problème maintenant, je n'ai que le contour de mon polygone qui est tracé
    étant donné que tu dessine avec un GL_LINE_LOOP c'est normal que tu ais un contour non ?
    par contre, si tu veux parler du fait qu'il devrait se remplir, c'est peut-etre parceque le point que tu donnes n'est pas à l'intérieur mais sur le contour ?
    sinon je ne vois pas ce que ça pourrait être d'autre qu'un problème de code

    En revanche, il suffit que réduise la feneter et que je l'agrandisse a nouveaux pour que le tracé du contour disparaisse et à la place je me retrouve avec mon tracé rouge qui va vers la gauche sans s'arreter...

    Aussi j'ai cette impression : Une fois le tracé du contour terminé, le tracé rouge prend la relève mais "ailleurs" et c'est "ailleurs" que le glreadpixels est effectué... Quand j'agrandi a nouveau la fenêtre le blanc disparait mais le rouge apparait... donc s'il se base là dessus normal qu'il ne trouve pas de blanc.
    lorsque la fenêtre est restaurée, est-ce que le contour est redessiné ?

    je comprend pas trop ton code, ce qu'il est sensé faire pour être exact
    remplir le polygone dont tu as tracé le contour ?
    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.

  9. #9
    Membre habitué
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2006
    Messages
    116
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2006
    Messages : 116
    Points : 163
    Points
    163
    Par défaut
    Alors oui, mes explications ont dues êtres confuses. Mon objectif est de programmer différents algorithmes de remplissage 2D et à terme 3D (oui openGL sait le faire tout seul, mais l'objectif est de découvrir et tester comment le faire en bas niveau, avec juste lecture d'un pixel et tracé d'un pixel.). Avec ces différents algorithmes, certains sont itératifs d'autres non. De la même manière qu'il y a peu je testais plusieurs algo de tracé de ligne, puis de tracé de cercle afin de se rapprocher au plus prêt de l'efficacité des fonctions openGL qui le font. Je sais c'est un peu tordu de vouloir connaitre ceci, mais c'est dans le cadre de mes études et je trouve intéressant de comprendre comment fonctionnent toutes ces fonctions qui tracent des traits, pourquoi elles sont plus rapides et moins couteuses que d'autres etc..

    Bref, mon problème ici est le suivant. J'ai un polygone, identifié par l'ensemble de ses sommets :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Point * POLY[255] = {
            new Point(-50 , 80)
            , new Point(0 , 20)
            , new Point(60 , 40)
            , new Point(40 , -50)
            , new Point(-50 , -50)
        };
    Mon objectif est de faire un algo de remplissage par liste et par test de la couleur d'un pixel. Il se base sur l'étude des couleurs qui sont les suivantes : contour en blanc, couleur par défaut en noir et couleur de remplissage en rouge. Je veux donc au final avoir un polygone de contour BLANC remplis par du ROUGE le tout dans une fenêtre remplie de NOIR. Dans l'ordre :
    - On trace le contour du polygone (d'où le GL_LINE_LOOP).
    - On prend un point de départ situé à l'intérieur du polygone (je l'ai appelé first)
    - On change la couleur du premier point et on empile son pixel nord, sud, est et ouest.
    - Pour chacun des pixels empilés, si la couleur est la couleur par défaut (ici le NOIR) alors c'est qu'on est encore DANS le polygone. On change donc sa couleur par le rouge et on empile encore une fois le nord sud est et ouest. Si la couleur est celle du contour ou est celle de remplissage, on ne fait rien hormis dépiler le pixel.
    - Au final on est censés obtenir un polygone de contour blanc rempli de rouge dans une fenêtre noire... en théorie.

    En pratique :

    Le polygone se trace bien (contours blanc uniquement).
    Le point de départ est bien le bon puisque si on regarde les coordonnées du polygone, il contient bien le point (0,0)
    MAIS le tracé rouge n'apparait pas.

    Si je change la taille de la fenêtre, que je la réduit, maximise ou même juste déplacer, le contour qui était en blanc disparait. En revanche à ce moment là apparait tout ce qui a été tracé en rouge et qui n'apparaissait pas avant... Et c'est bien celà le problème, car visiblement le test de couleur de pixel est effectué dans cette sorte de buffer qui s'affiche que quand on bouge la fenêtre, ce même buffer qui ne prend plus en compte le précédent tracé... et donc les tests ne risquent pas de trouver du blanc quelque part...

    C'est surtout cette dernière partie qui merdouille. L'algo etc.. je sais qu'il fonctionne. Ce qui marche pas c'est que les pixels que je met en rouge ne s'affichent que quand je bouge la fenêtre, et qu'alors les pixels tracés en blanc précédemment disparaissent.

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

    Informations professionnelles :
    Activité : avancé

    Informations forums :
    Inscription : Avril 2005
    Messages : 2 524
    Points : 5 183
    Points
    5 183
    Par défaut
    je me demande si ton problème ne vient pas de la confusion entre le tracé dans le backbuffer / swap / remplissage dans le backbuffer

    je ne me trompe pas, tu fonctionnes bien en double buffer ?
    est-ce que tu as bien conscience du fonctionnement du double buffering ?

    tu dessine dans un buffer invisible
    tu échanges avec le buffer visible
    tu dessine dans le buffer qui était visible mais ce qu'il contient n'était pas forcément ce que tu voyais

    si tu redimensionnes ta fenêtre, il faut que tu redessines ton contour et que tu redimensionnes ton viewport et ton glOrtho pour qu'il respecte les nouvelles dimensions

    j'ai bien compris ce que tu voulais faire et je pense sincèrement que OpenGL n'est pas du tout fait pour cela, même si c'est possible à réaliser
    à ta place, je passerai au moins en simple buffering
    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.

  11. #11
    Membre habitué
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2006
    Messages
    116
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2006
    Messages : 116
    Points : 163
    Points
    163
    Par défaut
    je passerai au moins en simple buffering
    Comment fait-on ?

    Pour le choix d'opengl, comme je le disais c'est dans le cadre de mes études et j'ai pas vraiment le choix

    Si d'ici ce soir je n'arrive pas à récupérer la couleur du pixel de tenterais une méthode qui ne change pas l'algo mais dont les performances sont bien moindres : enregistrer dans un tableau la liste des pixels non noirs... Mais si je peux réussir avec la couleur elle même c'est pas plus mal ^^

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

    Informations professionnelles :
    Activité : avancé

    Informations forums :
    Inscription : Avril 2005
    Messages : 2 524
    Points : 5 183
    Points
    5 183
    Par défaut
    pour le mode simple buffer, au lieu de faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
    tu fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_SINGLE);
    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.

  13. #13
    Membre habitué
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2006
    Messages
    116
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2006
    Messages : 116
    Points : 163
    Points
    163
    Par défaut
    Alors alors... le dernier problème est corrigé grâce à la modif que tu m'as proposé avec le simple buffer... MAIS nous sommes revenus au problème précédent.

    Le premier point est celui du centre. Il trace du rouge jusqu'a rencontrer le contour blanc... en théorie. En pratique il trouve pas le contour blanc. Et donc il continu. Voici un screen agrandi pour montrer :



    Problème, quand j'affiche la couleur des pixels, il trouve un truc totalement incohérent : 162 , 1 , 72 un truc comme ça... Du coup je me demande s'il récupère pas la couleur du pixel ailleurs que sur la fenêtre. Sur le bureau par exemple ???

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

    Informations professionnelles :
    Activité : avancé

    Informations forums :
    Inscription : Avril 2005
    Messages : 2 524
    Points : 5 183
    Points
    5 183
    Par défaut
    tu as bien modifié la lecture du buffer à FRONT pour glReadPixels ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    glReadBuffer(GL_FRONT);
    glReadPixels(first.x , first.y , 1 , 1 , GL_RGBA , GL_UNSIGNED_BYTE , pixel);
    je te conseille aussi d'utiliser glColor3ub pour passer la couleur en 3 "unsigned byte" plutot qu'en float
    vu que la couleur n'est pas stockée sur des réels
    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.

  15. #15
    Membre habitué
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2006
    Messages
    116
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2006
    Messages : 116
    Points : 163
    Points
    163
    Par défaut
    J'ai passé la lecture du buffer à FRONT ça n'a rien changé. J'ai testé en mettant une seule fois et une fois avant chaque glreadpixels pour être sur...

    Concernant la couleur, c'est effectivement plus propres à ta façon mais le problème ne vient pas de là je vais donc éviter de m'embrouiller encore plus ^^

    Dans le doute je remet le code tel qu'il est maintenant :


    main.cpp
    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
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    #include <windows.h>
    #include <GL/glut.h>
    #include <GL/gl.h>
    #include <GL/glu.h>
    #include <stack>
    #include <iostream>
     
    #include "Point.h"
    #include "fonctions.h"
     
    using namespace std;
     
    int nWindowID;
    const int g_nWidth = 1280;
    const int g_nHeight = 1024;
     
    void affichage(void);
    void attente(void);
    void clavier(unsigned char touche, int x, int y);
     
    int couleur_bg[3] = {0 , 0 , 0};
     
    int main(int argc,char *argv[])
    {
    	// initialisation de GLUT
    	glutInit(&argc, argv);
     
        glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_SINGLE);
        glutInitWindowSize(g_nWidth, g_nHeight);
     
        int g_nWindowID = glutCreateWindow("Remplissage par germes");
     
        glutDisplayFunc(affichage);
        glutIdleFunc(attente);
     
        glClearColor(couleur_bg[0], couleur_bg[1], couleur_bg[2], 0);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     
        glutMainLoop();
     
    	return 0;
    }
     
    void affichage(void)
    {
        float midLarg = ((float)g_nWidth) / 2.0f;
        float midHaut = ((float)g_nHeight) / 2.0f;
     
        glOrtho(-midLarg, midLarg, -midHaut, midHaut, -1 , 1);
     
        /**
        Nombre de sommets du polygone
        */
        int nb_sommet = 5;
        unsigned char * pixel = new unsigned char[18];
        int couleur_contour[3] = {1 , 1 , 1};
        int couleur_contenu[3] = {1 , 0 , 0};
     
        stack<Point> pile;
     
        /**
        Liste des sommets du polygone
        */
        Point * POLY[255] = {
            new Point(-50 , 80)
            , new Point(0 , 20)
            , new Point(60 , 40)
            , new Point(40 , -50)
            , new Point(-50 , -50)
        };
     
        Point first = Point(0 , 0);
        Point cur;
     
        glColor3f(1.0 , 1.0 , 1.0);
        glBegin(GL_LINE_LOOP);
     
        /**
        Tracé du contour du polygone en blanc (1,1,1)
        */
        for(int i = 0 ; i < nb_sommet ; i++)
        {
            glVertex2f(POLY[i]->x , POLY[i]->y);
        }
        glEnd();
     
        glReadBuffer(GL_FRONT);
        glReadPixels(first.x , first.y , 1 , 1 , GL_RGBA , GL_UNSIGNED_BYTE , pixel);
     
        /**
        FIN - Tracé du contour du polygone en blanc (1,1,1)
        */
     
        glColor3f(couleur_contenu[0] , couleur_contenu[1] , couleur_contenu[2]);
     
        if(!eq(couleur_contour , pixel) && !eq(couleur_contenu , pixel))
        {
            pile.push(first);
     
            while(pile.size() != 0 && pile.size() < 500000)
            {
                cur.x = pile.top().x;
                cur.y = pile.top().y;
     
                pile.pop();
     
                glBegin(GL_POINTS);
                glVertex2f(cur.x , cur.y);
                glEnd();
     
                glReadBuffer(GL_FRONT);
                glReadPixels(cur.x , cur.y +1 , 1 , 1 , GL_RGBA , GL_UNSIGNED_BYTE , pixel);
                afficher(pixel);
                if(!eq(couleur_contour , pixel) && !eq(couleur_contenu , pixel))
                    pile.push(Point(cur.x , cur.y +1));
     
                glReadBuffer(GL_FRONT);
                glReadPixels(cur.x , cur.y -1 , 1 , 1 , GL_RGBA , GL_UNSIGNED_BYTE , pixel);
                afficher(pixel);
                if(!eq(couleur_contour , pixel) && !eq(couleur_contenu , pixel))
                    pile.push(Point(cur.x , cur.y -1));
     
                glReadBuffer(GL_FRONT);
                glReadPixels(cur.x +1 , cur.y , 1 , 1 , GL_RGBA , GL_UNSIGNED_BYTE , pixel);
                afficher(pixel);
                if(!eq(couleur_contour , pixel) && !eq(couleur_contenu , pixel))
                    pile.push(Point(cur.x +1 , cur.y));
     
                glReadBuffer(GL_FRONT);
                glReadPixels(cur.x -1 , cur.y , 1 , 1 , GL_RGBA , GL_UNSIGNED_BYTE , pixel);
                afficher(pixel);
                if(!eq(couleur_contour , pixel) && !eq(couleur_contenu , pixel))
                    pile.push(Point(cur.x -1 , cur.y));
            }
        }
     
        glFlush();
        glutSwapBuffers();
    }
     
    /* Fréquence de rafraichissement de l'image */
    void attente(void)
    {
    	static int nWaitUntil = glutGet(GLUT_ELAPSED_TIME);
    	int nTimer = glutGet(GLUT_ELAPSED_TIME);
    	if(nTimer >= nWaitUntil)
    	{
    		glutPostRedisplay();
    		nWaitUntil = nTimer + 100000;
    	}
    }
    Point.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #include "Point.h"
     
    Point::Point(int a = 0 , int b = 0)
    {
        x = a;
        y = b;
    }
     
    Point::Point()
    {
        x = 0;
        y = 0;
    }
    fonctions.cpp
    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
    #include "fonctions.h"
    #include <math.h>
    #include <iostream>
    using namespace std;
     
    #define PI 3.14159265
     
    bool eq(int clr[3], unsigned char * pixel)
    {
        return (pixel[0] == clr[0] * 255 && pixel[1] == clr[1] * 255 && pixel[2] == clr[2] * 255);
    }
     
    void afficher(unsigned char * pixel)
    {
        cout<<(int)pixel[0]<<":"<<(int)pixel[1]<<":"<<(int)pixel[2]<<endl;
    }
     
    /**
    Retourne l'angle entre deux vecteurs. Ces vecteurs sont dans notre cas ceux formés
    Par le point et deux des sommets
    */
    double angle_2v(double x1, double y1, double x2, double y2)
    {
       double dt,at1,at2;
     
       at1 = atan2(y1,x1);
       at2 = atan2(y2,x2);
       dt = at2 - at1;
     
       while (dt > PI)
          dt -= 2 * PI;
     
       while (dt < -PI)
          dt += 2 * PI;
     
       return(dt);
    }
     
    /**
    Retourne vrai si le point de coordonnées x et y se trouve dans le polygone POLY
    Cette méthode se base sur le calcul de la somme des angles avec les sommets
    */
    bool interieur(int x, int y, Point * POLY [255] , int nb_sommet)
    {
        double somme_angle = 0;
        Point p1 , p2;
     
        for (int i = 0 ; i < nb_sommet ; i++)
        {
            p1.x = POLY[i]->x - x;
            p1.y = POLY[i]->y - y;
     
            p2.x = POLY[(i+1) % nb_sommet]->x - x;
            p2.y = POLY[(i+1) % nb_sommet]->y - y;
     
            somme_angle += angle_2v( p1.x , p1.y , p2.x , p2.y);
        }
     
        if (fabs(somme_angle) < PI)
            return false;
     
        else return true;
    }
    Point.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #ifndef POINT_H
    #define POINT_H
     
    class Point
    {
        public :
        int x , y;
        Point(int , int);
        Point();
    };
     
    #endif
    fonctions.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #ifndef FONCTIONS_H
    #define FONCTIONS_H
     
    #include "Point.h"
     
    bool eq(int [],  unsigned char *);
    double angle_2v(double, double, double, double);
    bool interieur(int, int, Point * [] , int);
    void afficher(unsigned char *);
     
    #endif

  16. #16
    Membre habitué
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2006
    Messages
    116
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2006
    Messages : 116
    Points : 163
    Points
    163
    Par défaut
    Alors alors. En relisant tous ces messages j'ai vu que la solution était dedans, mais encore fallait-il le savoir ^^

    En fait, comme tu l'avais précisé, le glReadPixels() et les glVertex2f() n'utilisent pas le même repère orthonormé. Le glOrtho() permet de modifier le repère utilisé mais n'agit PAS sur le repère utilisé par le glreadpixels(). Il faut donc procéder à un changement de repère pour que ça fonctionne.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    glReadPixels(cur.x +(int)midLarg , cur.y +1+(int)midHaut , 1 , 1 , GL_RGBA , GL_UNSIGNED_BYTE , pixel);
    Voilà donc la solution, à ceux qui liront ce post : le glreadpixels() utilise un repère dont l'origine est le bord inférieur gauche de la fenêtre et celà peu importe le glOrtho(...) que vous pouvez faire. Soit donc vous adaptez avec glOrtho(...) pour utiliser ce même repère, soit vous transposez les coordonnées au moment du readpixels() (ce que j'ai fait, cf le code ci-dessus).

    Merci pour cette aide en tout cas

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

Discussions similaires

  1. Récupérer la couleur d'un pixel sur le bureau Windows
    Par darioo2 dans le forum Débuter
    Réponses: 13
    Dernier message: 17/04/2013, 19h40
  2. récupérer les couleurs d'un pixel d'une image
    Par sys1 dans le forum Débuter
    Réponses: 12
    Dernier message: 29/07/2010, 13h56
  3. Récupérer la couleur d'un pixel a l'écran
    Par Ekinoks dans le forum GTK+ avec C & C++
    Réponses: 2
    Dernier message: 30/01/2008, 19h51
  4. Récupérer la couleur d'un pixel
    Par Jere15 dans le forum C++
    Réponses: 4
    Dernier message: 20/06/2007, 16h35
  5. Récupérer la couleur d'un pixel
    Par MadininaSTY dans le forum AWT/Swing
    Réponses: 2
    Dernier message: 05/06/2006, 18h55

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