Forum Programmation.autre [OpenGL] Antialiasing sur fond coloré

Posté par (page perso) .
Tags : aucun
0
10
sept.
2007
Ayant RT(F)M sur l'anti aliasing pour les lignes en opengl, je mets les

glEnable GL_LINE_SMOOTH;
glEnable GL_BLEND;
glBlendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA;
glHint GL_LINE_SMOOTH_HINT GL_NICEST;


qui vont bien. Sur fond noir, les lignes rendent nickel. Maintenant si je met un rectangle bleu derrière, l'anti aliasing continue à se faire vers du noir et non vers du bleu.
Est-ce normal (je suppose que oui) ?
Et comment fait-on pour avoir un bon rendu quel que soit le fond ?

Merci forum.

(Note: c'est écrit en Ocaml, c'est pour ça qu'il n'y a ni parenthèses ni virgules)
  • # de memoire

    Posté par . Évalué à 0.

    il y avait des methodes à appliquer pour calculer les faces visibles, les faces cachées

    il y en a surement des methodes à appliquer et quelques options pour preciser ou prendre le fond pour l'antialias.
    • [^] # Re: de memoire

      Posté par (page perso) . Évalué à 1.

      Je me doute, mais je ne trouve pas.
      J'ai bien trouvé GL_CULL_FACE pour ne pas dessiner les faces cachées, mais en fait ça ne m'intéresse pas (je fais de la 2D). Je continue à chercher alors ...
      • [^] # Re: de memoire

        Posté par (page perso) . Évalué à 1.

        OK, trouvé, il faut mettre le glDepthMask à false avant de dessiner les lignes.
        • [^] # Re: de memoire

          Posté par (page perso) . Évalué à 1.

          Perdu, désactiver le mask_depth fait un effet "écran", un trait noir par exemple ne se voit plus. grrr ...
  • # re:

    Posté par (page perso) . Évalué à 2.

    Salut,

    Tu as un exemple de couleur de ligne avec lequel tu as cet effet ? Ou éventuellement poster une capture d'écran.
    J'ai essayé une ligne blanche et une verte sur un triangle bleu (affiché sur un fond noir) et l'antialiasing est correct sur les deux surfaces.

    Aussi, quelle épaisseur de ligne utilises-tu ? (glLineWidth) Il est conseillé d'augmenter l'épaisseur de ligne lorsque l'antialising est activé, par exemple à au moins 1,5 lorsque l'épaisseur originelle de la ligne est à 1,0.
    • [^] # Re: re:

      Posté par (page perso) . Évalué à 1.

      Toutes les couleurs. Capture d'écran icitte :
      http://farm2.static.flickr.com/1320/1364676845_d55da56ae2_o.(...)

      L'init du code incriminé est là
      http://www.flickr.com/photos/15812694@N00/1364676845/

      J'ai un glLinewidth entre 2 et 4 suivant les lignes.
      J'ai découpé le rendering en 2 phases, d'abord les lignes, puis les remplissages. Dans ce cas, les lignes sensées être recouvertes par des fills ne le sont pas (ex sur la capture les L allongés figurant les ailes de l'avion ont un z plus proche que la ligne d'horizon, pourtant cette dernière passe devant la forme, mais bien derrière son contour.)

      Si j'inverse l'ordre de dessin, les lignes ne sont pas dessinées alors qu'elles ont un z plus proche (!). Toujours en ordre de dessin inversé, si je supprime les remplissages, je vois les lignes, mais si je rends les remplissages partiellement transparents, je ne vois pas les lignes derrière.

      J'ai inversé tous les z, je n'ai aucun changement dans ce qui est affiché.

      Si je mets tous les z à 0 et que je fais les appels dans le bon ordre (les lignes puis les remplissages) la géométrie passe bien (le choses qui doivent se cacher se cachent), mais j'ai toujours le même problème d'anti alias.


      Je pense que je n'ai pas tout compris au depth buffer ...
      • [^] # Re: re:

        Posté par (page perso) . Évalué à 2.

        Je n'ai pas trop le temps à l'instant là, mais j'essaierai de voir ce soir un peu plus loin sur ton problème en reproduisant des symboles comme tu le fais.

        Mais je me demandais pourquoi tu traces les contours avec des lignes puis effectues un remplissage ? pourquoi ne pas tracer directement tes symboles en tant que ligne uniquement, en jouant sur leur épaisseur ? (ça fait peut être partie de ton cahier des charges ?)
        • [^] # Re: re:

          Posté par (page perso) . Évalué à 1.

          En effet: mes données en entrée sont de la forme: un polygone passant par les points [p1;p2;p3;p4;p5] de couleur de remplissage cr avec un contour de couleur cc de largeur L. Dessiner un polygone à coups de lignes me semble légèrement sous-optimal, non ? Par exemple dans la spec que j'affiche dans la capture, il y a un triangle peint en noir avec un bord rosâtre, ou le losange gris plein centre. Je peux aussi avoir à afficher des disques ou des couronnes, avec les mêmes contraintes (remplissage + bordure). Sinon c'est peut-être dû à mes bindings, mais j'en doute ( http://glcaml.sourceforge.net/ ). Sinon je t'ajoute aussi le code qui fait effectivement le rendu (le point d'entrée est la dernière fonction: render) :
          module Gl = Glcaml 
          
          type line_cmd = | Lines | LineLoop |LineStrip 
          type color = float * float * float * float
          type width = float
          type depth = float
          type point = float * float
          type shape_cmd = | Quad | Polygon
          type matrix_cmd = | Translate of float * float |Scale of float*float | Rotate of float 
          type cmd = 
              |Line of line_cmd * point list * color * width * depth
              |Shape of shape_cmd * point list * color * depth
              |Matrix of matrix_cmd list * cmd list
          
          let color = function |(r,g,b,a)->Gl.glColor4f r g b a
          let set_alpha a = function |(r,g,b,_)->(r,g,b,a)
          let width w = Gl.glLineWidth w
          let line_prim = function | Lines -> Gl.GL_LINES | LineLoop -> Gl.GL_LINE_LOOP | LineStrip -> Gl.GL_LINE_STRIP
          let shape_prim = function | Quad -> Gl.GL_QUADS | Polygon -> Gl.GL_POLYGON 
          let vertex depth p2D = match p2D with | (x,y)-> Gl.glVertex3f x y depth
          let push_matrix transfos =
            let trans = function 
              | Translate(dx,dy) -> Gl.glTranslatef dx dy 0.
              | Scale (sx,sy) -> Gl.glScalef sx sy 0.
              | Rotate angle -> Gl.glRotatef angle 0. 0. 0.
            in
              begin 
                Gl.glPushMatrix ();
                List.iter trans transfos;
              end
          let pop_matrix () = Gl.glPopMatrix ()
          let rec render_line= function 
            |Line(prim,pts,c,w,d) -> 
               begin
                 color c ; 
                 width w ;
                 Gl.glBegin (line_prim prim);
                 List.iter (vertex d) pts;
                 Gl.glEnd ();
               end
            |Shape _ -> ()
            |Matrix(transfos, subshapes) -> begin 
                push_matrix transfos;
                List.iter render_line subshapes; 
                pop_matrix ()
              end
          
          let rec render_shape= function 
            |Line _ -> () 
            |Shape(prim,pts,c,d) -> 
               begin
                 color c ; 
                 Gl.glBegin (shape_prim prim);
                 List.iter (vertex (100.)) pts;
                 Gl.glEnd ();
               end
            |Matrix(transfos, subshapes) -> begin 
                push_matrix transfos;
                List.iter render_shape subshapes; 
                pop_matrix ()
              end
          
          let render cmd_list = 
            begin
              List.iter render_line cmd_list;
              List.iter render_shape cmd_list; 
            end
          
          • [^] # Re: re:

            Posté par (page perso) . Évalué à 2.

            Il y a un bug dans le code ci dessus où tous les z des shapes est forcé à 100.0. En sortant de l'axe pour voir ce qui se passe, j'ai pu corriger pas mal de problèmes de profondeur et de glfrustum mal ajusté, et ça donne ça:

            http://www.flickr.com/photos/15812694@N00/1367027345/

            Beaucoup mieux donc, mais les lignes ne sont pas de la bonne couleur (phénomène d'écran évoqué plus haut). Je continue à chercher ...
            • [^] # Re: re:

              Posté par (page perso) . Évalué à 1.

              J'ai vu dans ton initialisation :
              glBlendFunc GL_SRC_ALPHA GL_DST_ALPHA;

              Le second paramètre est incorrect, il doit être GL_ONE_MINUS_SRC_ALPHA comme indiqué dans ton message initial.
              • [^] # Re: re:

                Posté par (page perso) . Évalué à 1.

                En effet, j'aurais dû revenir voir ici plus souvent, j'ai trouvé mais une heure après ton post.
                Merci pour tout en tous cas ;)
            • [^] # Re: re:

              Posté par (page perso) . Évalué à 1.

              Au passage, tu n'utilises pas une projection orthogonale pour ton rendu 2D ? Tu risques de te retrouver avec des symboles de tailles variables suivant leur position dans la fenêtre.
              • [^] # Re: re:

                Posté par (page perso) . Évalué à 1.

                Je voudrais bien, on fait comment ?
                • [^] # Re: re:

                  Posté par (page perso) . Évalué à 1.

                  Regarde du côté de glOrtho ou gluOrtho2D. Par exemple :
                  gluOrtho2D (-10.0, 10.0, -5.0, 5.0);
                  te définit un repère orthogonal allant de -10 à +10 sur l'axe des X et de -5 à +5 sur l'axe des Y (donc dans ce cas, l'origine est situé au centre de l'image).
            • [^] # Re: re:

              Posté par (page perso) . Évalué à 1.

              Allez Luilla !!!
              Trouvé, mauvais paramètres en blend func, j'aurais du utiliser
              glBlendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA;
              pour faire l'anti aliasing comme il faut.
              Super ! je vais pouvoir m'attaquer aux stencils maintenant :o/

              Bonne nuit !
          • [^] # Re: re:

            Posté par (page perso) . Évalué à 1.

            Je n'arrive pas à reproduire ton problème. J'ai essayé de dessiner des surfaces et des contours dans un petit programme en C disponible à l'adresse http://tfc.duke.free.fr/tmp/aa.c (echap pour quitter, n'importe quelle autre touche pour antialiasing on/off). Ça donne ce résultat :
            http://tfc.duke.free.fr/tmp/aa.png
            Est-ce bien à peu près ce que tu cherche à obtenir ?

            Dans mon programme j'ai désactivé le test de profondeur. Pour de la 2D, ce n'est pas nécessaire, il suffit de dessiner dans le bon ordre (sauf peut être pour faire des masques -- cas particuliers).

            À la fin de ton bout de code, tu semble dessiner les contours d'abord puis ensuite les surfaces. Peut-être serait-il mieux d'inverser cet ordre ? (le résultat ne sera pas le même surtout si on désactive le test de profondeur)

            Bon par contre il semblerait qu'il y ait un bug avec le driver intel lorsqu'on utilise GL_LINE_LOOP...

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.