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

Caml Discussion :

Functional bindings for OpenGL


Sujet :

Caml

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 32
    Points : 32
    Points
    32
    Par défaut Functional bindings for OpenGL
    wiki.cocan.org/soc/google2008
    sur cette page est indiqué "Functional bindings for OpenGL"
    est-ce que quelqu'un pourrait donner plus d'indications ?
    qu'est ce qui doit être fonctionnel, juste la partie fenêtrage et interaction utilisateur,
    ou bien toutes les fonctions d'entrée sortie comme glVertex... ?

  2. #2
    Membre éprouvé
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    832
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 832
    Points : 1 104
    Points
    1 104
    Par défaut
    Merde, mon super message s'est fait descendre à coup de liquide de refroidissement.

    En résumé, le code habituel utilisant OpenGL (même avec l'approche de fgjdfgjdgj) est essentiellement impératif. Par exemple, les manipulations de la caméra ou de la couleur du tracé se font par effet de bord.

    Il est possible de faire différemment, par exemple avec des libs de "combinateurs", comme graphics-drawingcombinators. Par ailleurs, méfiez-vous des bindings monadiques (comme la plupart de ceux qu'on trouve en Haskell), ils sont encore impératifs en substance.


    EDIT gorgonite : le revoilà

    Citation Envoyé par bluestorm Voir le message
    Cela reste du code non fonctionnel à la base : par exemple, la fonction de changement de couleur est impérative, elle manipule un état global.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
          GlMat.push();
          let p = c.pos in
          GlMat.translate ~x:p.x ~y:p.y ~z:p.z ();
          GlDraw.color c.color;
          Glut.wireCube c.size;
          GlMat.pop();
    Un binding fonctionnel devrait présenter au programmeur une interface sans effets de bord. Par exemple, tu peux regarde la bibliothèque Haskell drawingcombinators :
    http://hackage.haskell.org/packages/...mbinators.html

    Cela donnerait sans doute quelque chose comme ça (pas testé)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    GlMat.with_mat
      (fun m -> (GlDraw.color c.color)
        (Glut.wireCube c.size (GlMat.translate ~pos:c.pos m))
    (Attention au fait qu'en Haskell, la plupart des bindings de libs externes ont une interface monadique, et on donc importé dans un cadre fonctionnel l'interface impérative (c'est normal, c'est le plus facile) : ce ne sont pas des bindings fonctionnels)

  3. #3
    Membre régulier Avatar de smatador
    Homme Profil pro
    Inscrit en
    Mars 2006
    Messages
    57
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 57
    Points : 78
    Points
    78
    Par défaut
    Je me demande même si cela est vraiment possible d'avoir un binding fonctionnel pour opengl étant donné la nature de ce dernier (une machine à état si mes souvenirs sont bons) ?

  4. #4
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 32
    Points : 32
    Points
    32
    Par défaut
    OK, j'ai lu avec beaucoup d'intérêt le code source de Graphics.DrawingCombinators,
    donc plus simplement il s'agit de wrapper chaque fonction pour qu'elles retournent en restaurant l'état qu'il y avait en entrant dans la fonction, c'est bien ça ?

    Donc dans mon exemple précédent je m'en tire, pour obtenir du code fonctionel, en ajoutant uniquement les 2 fonctions draw_color et draw_translate ?

    ... si c'est ça c'est pas bien compliqué à faire, juste un peu long car l'api gl contient beaucoup de fonctions ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    let draw_color color f =
      GlMisc.push_attrib [`current];
      GlDraw.color color;
      f ();
      GlMisc.pop_attrib()
     
    let draw_translate vec f =
      GlMat.push();
      GlMat.translate ~x:vec.x ~y:vec.y ~z:vec.z ();
      f ();
      GlMat.pop()
    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
     
    type pos = {x:float; y:float; z:float}
    type color = Gl.rgb
    type cube = {size:float; pos:pos; color:color}
    type obj = Cube of cube
    type app = {loc:pos; cnt:obj list}
     
    let rand_color() =
      (Random.float 1.0,
       Random.float 1.0,
       Random.float 1.0)
     
    let new_cube size ?(pos={x=0.; y=0.; z=0.}) color =
      Cube {size=size; pos=pos; color=color}
     
    let init_app() =
      let init_pos = {x=0.; y=0.; z=0.} in
      {loc=init_pos; cnt=[]}
     
    let draw_color color f =
      GlMisc.push_attrib [`current];
      GlDraw.color color;
      f ();
      GlMisc.pop_attrib()
     
    let draw_translate vec f =
      GlMat.push();
      GlMat.translate ~x:vec.x ~y:vec.y ~z:vec.z ();
      f ();
      GlMat.pop()
     
    let main_draw f =
      GlClear.clear [`color];
      GlMat.load_identity();
      f ();
      Glut.swapBuffers()
     
    let display app =
      main_draw (fun () ->
      draw_translate app.loc (fun () ->
        let display_item = function
        | Cube c ->
            draw_translate c.pos (fun () ->
            draw_color c.color (fun () ->
              Glut.wireCube c.size;
            ))
        in
        List.iter display_item app.cnt;
      ))
     
    let app_add_x app step = {app with loc={app.loc with x= app.loc.x +. step}}
    let app_add_y app step = {app with loc={app.loc with y= app.loc.y +. step}}
    let app_add_z app step = {app with loc={app.loc with z= app.loc.z +. step}}
     
    let app_sub_x app step = {app with loc={app.loc with x= app.loc.x -. step}}
    let app_sub_y app step = {app with loc={app.loc with y= app.loc.y -. step}}
    let app_sub_z app step = {app with loc={app.loc with z= app.loc.z -. step}}
     
    let push_content app cnt = {app with cnt = cnt :: app.cnt}
     
    let keyboard app ~key ~x ~y =
      match char_of_int key with
      | 'q' | '\027' -> exit 0;
      | '-' -> Glut.postRedisplay(); app_sub_z app 0.1
      | '+' -> Glut.postRedisplay(); app_add_z app 0.1
      | _ -> app
     
    let inv p = { x= -. p.x; y= -. p.y; z= -. p.z -. 3.0 }
     
    let push_cube app =
      let cube = new_cube 0.1 ~pos:(inv app.loc) (rand_color()) in
      push_content app cube
     
    let special app ~key ~x ~y =
      match key with
      | Glut.KEY_F1 | Glut.KEY_F2 | Glut.KEY_F3 | Glut.KEY_F4
      | Glut.KEY_F5 | Glut.KEY_F6 | Glut.KEY_F7 | Glut.KEY_F8
      | Glut.KEY_F9 | Glut.KEY_F10 | Glut.KEY_F11 | Glut.KEY_F12 -> app
      | Glut.KEY_HOME | Glut.KEY_PAGE_UP
      | Glut.KEY_END  | Glut.KEY_PAGE_DOWN -> app
      | Glut.KEY_UP    -> Glut.postRedisplay(); push_cube(app_sub_y app 0.1)
      | Glut.KEY_DOWN  -> Glut.postRedisplay(); push_cube(app_add_y app 0.1)
      | Glut.KEY_LEFT  -> Glut.postRedisplay(); push_cube(app_add_x app 0.1)
      | Glut.KEY_RIGHT -> Glut.postRedisplay(); push_cube(app_sub_x app 0.1)
      | Glut.KEY_INSERT -> app
     
    let () =
      Random.self_init();
      Fun_glut.fun_glut ~display ~keyboard ~special ~init:(init_app()) ()

  5. #5
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    Citation Envoyé par bluestorm Voir le message
    Il est possible de faire différemment, par exemple avec des libs de "combinateurs", comme graphics-drawingcombinators. Par ailleurs, méfiez-vous des bindings monadiques (comme la plupart de ceux qu'on trouve en Haskell), ils sont encore impératifs en substance.
    Pas forcément... On dirait que tu confonds "monadique" avec "impératif". Ce n'est pas du tout la même chose, et dans de nombreux cas, les monades impliqués dans un binding n'ont aucun élément impératif. Ce n'est pas le cas d'OpenGL en Haskell par exemple (au cas où tu n'aurais pas remarqué, OpenGL fait de l'IO donc est intrinsèquement impure), mais même ainsi, HOpenGL n'a rien d'une simple traduction de l'interface C d'OpenGL, c'est une librairie d'excellente qualité, l'un des meilleurs bindings OpenGL dans les langages non-C actuels. Elle propose un certain nombre d'améliorations et de raccourcis qui amène pas mal d'ex-utilisateurs d'OpenGL en C (et autres langages) à l'apprécier énormément.

    Un commentaire récent sur cette librairie venu de Haskell-café :
    I use Haskell and OpenGL for prototyping scientific visualization software, 3D models and such. Not that I think it couldn't be used for production software, its just that I just don't produce much

    The library really is fantastic. I don't think it gets enough fanfare. The only other GL API that rivals it is the C API itself. Most other languages provide a shoddy & incomplete interface to that, instead of an idiomatic interpretation of the OpenGL spec. I can't think of a single language, not even python, whose OpenGL bindings come close.

    I get the impression (from a inadequate sample of irc logs and list chatter) that many Haskellers see HOpenGL as 'just an OpenGL binding', like it was readline or curses or something. It just plugs a hole in the Haskell/OS interface, and its worth is merely a function of the size and importance of that hole. Instead I advocate, as Claus and others have done, that it's a shining example of how to write a Haskell interface to a well known API.

    If you never used C OpenGL and learned GL using Haskell, you might not notice anything special about it. But that's kind of my point, its just so damn good it blends into the background. The only people who notice this, I think, are experienced C OpenGL programmers, and the overlap between them and the Haskell community in general is small I bet. Their voice in that community smaller still.
    --
    Jedaï

  6. #6
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 32
    Points : 32
    Points
    32
    Par défaut
    ça a l'air intéressant tout ça, mais je ne connais pas du tout Haskell,
    comment traduirais-tu ça en termes concrêts pour OCaml ?

  7. #7
    Membre éprouvé
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    832
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 832
    Points : 1 104
    Points
    1 104
    Par défaut
    Jedai > désolé d'avoir fait une imprécision à ce sujet. Je voulais dire que dans la majorité, les bindings monadiques de bibliothèques impératives sont utilisées pour conserver le style de programmation original (impératif), et donc ne sont pas spécialement "fonctionnels".

    Le binding HOpenGL est certainement très bien (n'ayant jamais beaucoup utilisé OpenGL moi-même, encore moins HOpenGL, je n'en ai aucune idée), mais le style de programmation qu'il requiert n'est pas très "déclaratif" :

    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
    display angle = do
      clear [ColorBuffer]
      a <- get angle
      rotate a $ Vector3 0 0 (1::GLfloat)
      scale 0.7 0.7 (0.7::GLfloat)
      mapM_ (\(x,y,z) -> preservingMatrix $ do
        color $ Color3 ((x+1.0)/2.0) ((y+1.0)/2.0) ((z+1.0)/2.0)
        translate $ Vector3 x y z
        cube (0.1::GLfloat)
        ) $ points 7
      flush
    idle angle = do
      a <- get angle
      angle $= a + 0.1
      postRedisplay Nothing
    C'est intelligent au niveau de la syntaxe, cela propose des opérations pour simplifier la vie du programmeur (preservingMatrix), mais ça n'est pas spécialement un style fonctionnel : c'est un style de programmation impératif, reproduit en Haskell par l'intermédiaire des monades.

    Effectivement, comme OpenGL repose sur des principes _très_ impératifs, il semble difficile de faire des bindings déclaratifs. De plus, la plupart des utilisateurs des bindings souhaitent que le style de programmation soit comparable à celui de la bibliothèque initiale (ne serait-ce parce qu'il existe deux ou trois tutoriels HOpenGL, et des dizaines de tutos OpeNGL). Le choix de ce genre de bindings est donc très pertinent. (En OCaml, on ferait probablement cela sans couche monadique, parce que l'on peut faire directement des effets de bord, même si ce n'est pas toujours équivalent)

    Cependant, on peut toujours se demander s'il n'est pas possible de faire des bindings "plus fonctionnels". C'est comme ça que j'ai interprété le débat sur ce topic, et selon ce point de vue HOpenGL reste une "traduction de l'interface C", au niveau du style de programmation, et n'est donc pas satisfaisante. Je ne connais pas beaucoup d'approches déclaratives des bibliothèques graphiques : en GUI, j'ai vaguement entendu parler des "Fudgets", et des recherches plus récentes sur la "Functional Reactive Programmaing". Je ne connais rien pour la 3D. En 2D il y a quelques bibliothèques (comme drawingcombinators) et Functional MetaPost qui sont intéressants.

  8. #8
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    Citation Envoyé par bluestorm Voir le message
    C'est intelligent au niveau de la syntaxe, cela propose des opérations pour simplifier la vie du programmeur (preservingMatrix), mais ça n'est pas spécialement un style fonctionnel : c'est un style de programmation impératif, reproduit en Haskell par l'intermédiaire des monades.
    Certes, c'est d'ailleurs ce que j'ai dit, OpenGL dans son concept est impératif, et ça ne fait pas grand sens de vouloir faire un "binding fonctionnel" : dans ce cas ce n'est plus OpenGL, et pour avoir des performances correctes, il va falloir opérer à un niveau supérieur d'abstraction. Il serait beaucoup plus censé sans doute de parler d'un moteur 3D fonctionnel (utilisant éventuellement OpenGL en sous-main).

    Citation Envoyé par bluestorm
    Jedai > désolé d'avoir fait une imprécision à ce sujet. Je voulais dire que dans la majorité, les bindings monadiques de bibliothèques impératives sont utilisées pour conserver le style de programmation original (impératif), et donc ne sont pas spécialement "fonctionnels".
    Ce n'est pas toujours le cas, en général ce que tu dis s'applique surtout aux bibliothèques faisant de l'IO en premier plan (il est alors censé d'avoir un binding monadique "impératif"). Généralement, si on veut repenser dans un mode plus fonctionnel l'activité couverte par l'une de ces librairies, cela demande une réécriture complète, tant il est difficile de concilier le design originel et un nouveau modèle purement fonctionnel performant (qui peut très bien inclure une monade).

    Citation Envoyé par fgjdfgjdgj
    ça a l'air intéressant tout ça, mais je ne connais pas du tout Haskell,
    comment traduirais-tu ça en termes concrêts pour OCaml ?
    En bref, faire un binding fonctionnel pour OpenGL me semble une idée relativement ridicule : le modèle OpenGL est purement impératif, même s'il y a des endroits où une approche fonctionnelle permet d'exprimer plus clairement certaines abstractions. Faire une bibliothèque graphique pour la 3D avec un modèle fonctionnel est un autre problème, auquel je ne connais pas grand chose.

    --
    Jedaï

  9. #9
    Membre émérite
    Avatar de SpiceGuid
    Homme Profil pro
    Inscrit en
    Juin 2007
    Messages
    1 704
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2007
    Messages : 1 704
    Points : 2 990
    Points
    2 990
    Par défaut
    Pour celui qui chercherait un binding déclaratif pour OpenGL il y a la librairie FieldTrip, les Haskelleurs n'étant jamais à la traine sur ces sujets.

    Pour les objets fixes ça peut encore aller semble-t-il.
    Mais pour les animations, bluestorm a raison, ça tire du côté de FRP (Functional Reactive Programming) et là il y a un risque d'over-engineering.

    Je crois que Jedai a tout à fait raison: on ne peut pas recommander un binding sous le seul prétexte qu'il est déclaratif, il faut voir si c'est déjà bien testé, bien documenté, et si ça n'est pas trop expérimental ou trop ésotérique.

    Sinon autant s'en tenir à un binding au style plus traditionnel.
    Du même auteur: mon projet, le dernier article publié, le blog dvp et le jeu vidéo.
    Avant de poser une question je lis les règles du forum.

Discussions similaires

  1. Réponses: 1
    Dernier message: 02/06/2015, 13h59
  2. Babel 5.4.0 : test de la nouvelle syntaxe function bind
    Par vermine dans le forum Général JavaScript
    Réponses: 5
    Dernier message: 21/05/2015, 16h55
  3. Réponses: 0
    Dernier message: 21/01/2010, 16h09
  4. Limite de bind dans Opengl
    Par sivaller dans le forum OpenGL
    Réponses: 3
    Dernier message: 02/06/2008, 11h01
  5. Réponses: 2
    Dernier message: 12/02/2008, 09h23

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