Partage
  • Partager sur Facebook
  • Partager sur Twitter

OpenGL 2D, profondeur & transparence

OpenGL 3 / 4

Sujet résolu
    12 juin 2019 à 20:14:53

    Bonjour à tous, 

    Pour le contexte, j'utilise SFML (pour la fenêtre, le système, etc...) et OpenGL 3 pour essayer de faire un petit jeu 2D

    Mes textures sont chargées ainsi (je cherche à faire simple dans un premier temps)

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, mImage.getSize().x, mImage.getSize().y, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
    	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, mImage.getSize().x, mImage.getSize().y, GL_RGBA, GL_UNSIGNED_BYTE, mImage.getPixelsPtr());
    
    	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    	glGenerateMipmap(GL_TEXTURE_2D);

    J'ai voulu afficher des images avec un fond transparent du coup j'ai utilisé

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    Ce qui fait que le fond devient noir et quand une image est derrière elle est donc cachée, même derrière la partie qui est censée être transparente...

    Du coup, après avoir cherché, j'ai corrigé le tir dans le shader en faisant 

    if(out_color.a <= 0)
      discard;

    Cette fois j'ai bien le fond transparent. Est-ce qu'il n'y a pas un autre moyen sans passer par le shader pour faire la même chose ?

    Ensuite je voudrais que l'affichage de ces textures prenne en compte la pronfondeur : elles sont toutes affichées dans le plan XY & j'ai posé z = -y, comme ça plus la texture est haute, plus elle sera "derrière", et inversement. Si on imagine un arbre, en passant dessous (donc devant) notre personnage est visible mais pas en passant au dessus (donc derrière). Le problème en faisant ça c'est qu'à cause de la projection la texture est plus ou moins grande selon qu'elle est plus ou moins éloignée du bas de l'écran. En plus avec la distance minimale est maximale, ça peut poser problème mais je pense qu'en ajustant z=-a*y avec a, fonction de la hauteur de l'écran et du Min & Max de l'affichage, on peut arranger ça et rendre visible tout ce qui est à l'écran. Bien sûr il faut que cela soit compatible avec l'affichage de la transparence choisi.

    Merci de votre aide par avance.

    • Partager sur Facebook
    • Partager sur Twitter
      13 juin 2019 à 13:53:20

      Concernant le blending, si tu configures bien celui-ci juste avant les draw call de tes objets transparents :

      glEnable(GL_BLEND);
      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

      (Traduction: Chaque draw call qui suit "mélangera" les couleurs de chaque pixel entre src (résultat du fragment shader) et destination (ce qui était présent dans le framebuffer avant ce draw call):

      result_color = src_alpha x src_color + (1 - src_alpha) x destination_color)

      Et que tu le désactives bien avant le rendu de tes objets opaques (qui dans ce cas doit se faire en premier),

      alors l'alpha de la couleur d'output (le 4è élement du vec4) de ton fragment shader doit prendre une valeur correspondant à l'opacité désirée (l'alpha récupérée dans ta texture si j'ai bien compris). Tu n'as pas besoin de faire un discard. Lorsque c'est transparent, il suffit de mettre 0, si c'est opaque 1, si c'est semi transparent, 0.5 par exemple, etc

      Pour le problème suivant, quelle matrice de projection appliques tu dans ton vertex shader? Si c'est une projection ortho, ça devrait aller je suppose, mais c'est difficile à dire sans voir le code complet et les formules mathématiques que tu utilises...

      • Partager sur Facebook
      • Partager sur Twitter
        13 juin 2019 à 14:06:33

        Ah oui c'est ça je pense, je vais utiliser la projection ortho ce soir. Pour le reste je vais essayer et je te dis ce soir. Merci en tout cas.

        EDIT : 

        J'ai donc fait ta méthode, et les textures avec un fond transparent passent bien sur les textures opaques et inversement, par contre les textures transparentes se masquent entre elles : le fond est considéré comme noir sur les textures transparentes et transparent sur les textures opaques.

        Le Link de gauche est censé être devant celui de droite qui est censé, lui, être devant la brique. Ca marche bien mais le Link de gauche cache une partie de celui de droite car son fond n'est ici pas considéré comme transparent. 

        EDIT 2:

        La même chose mais avec la technique dans le shader & donc correcte (mais il faudrait faire la même chose autrement qu'en passant par le shader)

        -
        Edité par hertos 14 juin 2019 à 12:29:57

        • Partager sur Facebook
        • Partager sur Twitter
          14 juin 2019 à 20:58:12

          Du coup j'ai fait ça 
          glDisable(GL_ALPHA_TEST);
          glDisable(GL_BLEND);
          
          //Draw opaque
          
          glEnable(GL_BLEND);
          glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
          glAlphaFunc(GL_GEQUAL, 1.0);
          glEnable(GL_ALPHA_TEST);
          
          //Draw transparent 
          Et ça marche, je vais essayer d'en apprendre un peu plus sur ce fonctionnement. Merci beaucoup.
          • Partager sur Facebook
          • Partager sur Twitter
            15 juin 2019 à 11:16:57

            glAlphaFunc fonctionne comme le code que tu avais mis dans ton shader, le test puis le discard.

            glAlphaFunc(GL_GEQUAL, 1.0) équivaut donc à:

            if (alpha < 1.0)
            {
              discard;
            }


            Par contre, glAlphaFunc est deprecated, du coup je te conseille de garder la version GLSL.

            Pour le rendu des objets transparents (2D ou 3D), il faut laisser le depth test actif, mais désactiver le depth write, avec glDepthMask(GL_FALSE).
            Ensuite, il faut trier tes sprites/objets du plus "lointain" au plus "proche" (ça se fait aussi avec les sprites, même si ce ne sera pas éloigné/proche, mais plutôt par layer)

            -
            Edité par dragonjoker 15 juin 2019 à 11:23:02

            • Partager sur Facebook
            • Partager sur Twitter

            Si vous ne trouvez plus rien, cherchez autre chose.

              17 juin 2019 à 12:38:17

              Ok, je vais donc le remettre dans le shader, tant pis. Pour ce qui est du tri, je n'ai pas besoin de désactiver le depth write, ça marche bien comme c'est et justement j'en ai besoin  car "y fait aussi bouger z". Merci beaucoup pour votre aide !
              • Partager sur Facebook
              • Partager sur Twitter

              OpenGL 2D, profondeur & transparence

              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
              × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
              • Editeur
              • Markdown