Forum de la communauté SFML

Général => Suggestions de nouvelles fonctionnalités => Discussion démarrée par: Lolilolight le Juillet 04, 2013, 11:02:52 am

Titre: Définir un ordre d'affichage par vertex.
Posté par: Lolilolight le Juillet 04, 2013, 11:02:52 am
Voila je voudrais savoir si il serait possible (vu que tu utilises opengl) de faire comme le fait opengl c'est à dire définir un ordre d'affichage par vertex pour que certaines tiles d'une tilemap soient affiché avant ou après certaines tiles d'une autre tilemap.

Merci de votre réponse.
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Nexus le Juillet 04, 2013, 11:22:13 am
Ce n'est pas directement possible, tu devrais dessiner les vertexes dans l'ordre que tu veux. Donc il faut utiliser plusieurs vertex arrays.
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Laurent le Juillet 04, 2013, 11:33:25 am
C'est techniquement possible (il suffit d'ajouter une coordonnée Z à sf::Vertex et d'activer le depth buffer), et ça a déjà été longuement débattu sur le forum anglais.

Pour l'instant ce n'est pas prévu, mais disons que je ne suis pas non plus spécialement contre.
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Lolilolight le Juillet 04, 2013, 11:42:56 am
Ok bah alors je vais essayer de faire comme tu dis, ajouter une coordonnée Z à mes sf::vertex et activer le depth buffer.

Merci.  :)
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Nexus le Juillet 04, 2013, 11:49:29 am
En fait ce n'est pas si facile, par exemple il y a des problèmes avec la composante alpha. Cherche les fils de discussion anglais ;)
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Lolilolight le Juillet 04, 2013, 12:00:16 pm
Arf ok.  :-\
Je vais aller faire un tour sur le forum anglais, je n'y avais jamais été mais ça pourrait être intéressant d'y aller jeter un coup d’œil. 
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Lolilolight le Juillet 04, 2013, 12:13:44 pm
Voilà j'ai trouvé, tu parles bien de ce fils de discutions là ?

http://en.sfml-dev.org/forums/index.php?topic=6817.msg44921#msg44921

Je n'utilise pas de sprites semi-transparent donc ça ne devrait pas poser de problèmes mais bon je verrai bien ça quand j'implémenterai ça.
Au pire, je repasserai à mon ancien système qui dessine les sprite un par un, c'est plus lent car plus d'appel à draw mais bon..., pas vraiment le choix dans mon cas.

PS : et hum quel problème ça cause exactement avec les sprites semi-transparents ?



Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Laurent le Juillet 04, 2013, 12:39:20 pm
Non c'était une autre discussion, bien plus fournie.

Citer
et hum quel problème ça cause exactement avec les sprites semi-transparents ?
Si tu affiches un sprite semi-transparent avant ce qui se trouve derrière, tu ne verras pas ce qui se trouve derrière. Le Z-buffer n'a pas la notion de semi-transparence.
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Lolilolight le Juillet 04, 2013, 01:03:59 pm
Citer
Si tu affiches un sprite semi-transparent avant ce qui se trouve derrière, tu ne verras pas ce qui se trouve derrière. Le Z-buffer n'a pas la notion de semi-transparence.

Ha, ok, c'est donc pour ça que parfois j'avais des sprites qui ne s'affichaient pas avec opengl et ou j'avais mal gommé le gris autour de mes sprites pour rendre le tour de mes sprites transparent au format png.
Car les fonds d'image de rendu blender sont gris, je ne sais pas si il y a moyen de changer ça pour que blender rendent mes objets en 3D sur fond transparent, bref...

Mais pour tout ce qui est transparent a 100% ça marche quand même non ?

Bref je n'utilise la semi-transparence que pour tout ce qui est lumière/ombre ou là je n'utilise pas de tilemap mais une rendertexture plutôt, pour la semi-transparence, c'est mieux.  :)

PS : ha oui je vois ce que tu veux dire, tu veux dire que si un objet est devant un autre, même si l'objet de devant est transparent, le Depthbuffer va faire comme si l'objet de derrière était caché et donc ne va pas l'afficher. (Vu que ça ne fait q'un bête test que sur la profondeur des pixels et non la transparence.)

PS 2 : dommage, un zBuffer qui ferai aussi un test sur l'opacité des pixels serait intéresant, mais à part faire ça avec un shader il n'y a surement pas d'autres options. (Ou je me trompe ?)
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Lolilolight le Juillet 04, 2013, 01:15:43 pm
Ok bah alors je vais plutôt revenir à mon ancien système avec un seul draw par sprite parceque en effet sans sahders ça ne marchera pas et je veux que mon appli marche aussi sur des pc ne supportant pas le langage GLSL.
Je pensais que le depthtest faisait aussi un test sur l'opacité des pixels mais ce n'est pas le cas.  :-\
Bref, oublie ma proposition, avec des sprites transparents ou semi-transparent ça ne marchera pas.
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Lolilolight le Juillet 04, 2013, 01:45:50 pm
Sinon, j'ai trouvé un article en Anglais qui traite sur le sujet : http://www.sjbaker.org/steve/omniv/alpha_sorting.html

Je pense que je vais essayer avec un glAlphaTest pour ne pas écrire les pixels totalement transparent dans le zBuffer, vu que je n'utilise pas de MipMap ou bien de linear mode, d'après cet article, ça ne devrait pas poser de problèmes.
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Nexus le Juillet 04, 2013, 01:55:08 pm
Est-ce que trier les objets dans une liste avant dessiner n'est pas une option? Ca serait beaucoup plus simple, et tu n'aurais pas besoin de modifier SFML.

A propos, les ordinateurs qui n'offrent pas GLSL sont très anciens (une décennie et plus).
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Lolilolight le Juillet 04, 2013, 02:35:28 pm
Citer
st-ce que trier les objets dans une liste avant dessiner n'est pas une option? Ca serait beaucoup plus simple, et tu n'aurais pas besoin de modifier SFML.
Si mais l'inconvénient est que c'est plus lent à dessiner qu'une tilemap car plus d'appels à draw.

Au sinon j'ai besoin de modifier SFML pour faire ça ?

En rajoutant juste ces quelques lignes de code dans mon code ça ne marcherait pas ?

glEnable(GL_DEPTH_TEST);
glAlphaFunc ( GL_GREATER, 0.1 ) ;
glEnable ( GL_ALPHA_TEST ) ;
 

Ainsi je dessine toutes les tilemap (donc je limite mes appels à draw vu que tout mes sprites qui pointeront vers la même texture seront envoyé d'un seul coup à opengl) et je mets une coordonnée z à tous les vertex de mes tilemap pour que les vertex ne soient plus affiché dans l'ordre ou je dessine mes tilemap mais bien dans l'ordre avec lequel j'ai insérer mes sprites dans ma liste.
Et pour virer le problème avec la transparence, j'active un alpha_test ainsi, tout les pixels qui sont transparent au bord de mes sprite ne seront pas écris dans le zbuffer et donc ne viendront pas cacher ce qui sera derrière.)

En fait ce que je cherche à faire c'est une combinaison des 2 techniques suivantes. (tilemapping et zBeuffering.)

La technique ou je trie tout dans la liste est plus simple mais plus lente. (D'ailleurs toutes les techniques (ou presque.) qui sont plus simple à mettre en œuvre en informatique sont souvent plus lente à l'exécution.))

Les techniques plus optimisées et plus avancées demandent souvent un peu plus de réflexion et de pratique.

Bref je trouve que se serait bien de pouvoir combiner ces 2 techniques avec la SFML, il y a bien sûr une complication supplémentaire pour les sprites semi-transparent mais il y a les rendertexture pour régler ce genre de problème non ?

Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Laurent le Juillet 04, 2013, 02:58:07 pm
Citer
En rajoutant juste ces quelques lignes de code dans mon code ça ne marcherait pas ?
Non, il faut modifier SFML à plusieurs endroits pour faire fonctionner le depth buffer correctement. En plus si tu fais ça dans ton code, ça ne sera pas pris en compte par SFML.
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Lolilolight le Juillet 04, 2013, 03:04:55 pm
Citer
Non, il faut modifier SFML à plusieurs endroits pour faire fonctionner le depth buffer correctement. En plus si tu fais ça dans ton code, ça ne sera pas pris en compte par SFML.

Erf.  :'(
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Lolilolight le Juillet 04, 2013, 03:34:49 pm
Bon bah pas le choix alors je vais revenir à mon ancienne technique avec un seul draw par sprite, la seule technique qui marche avec SFML dans mon cas pour l'instant.
Je changerai plus tard si une version futur de la SFML permet d'utiliser le depthtest et l'alphatest correctement.
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Laurent le Juillet 04, 2013, 03:41:59 pm
Les modifs ne sont pas forcément compliquées à faire, si ça ne t'embête pas d'utiliser une version custom de SFML je peux te dire ce qu'il y a à changer.
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Lolilolight le Juillet 04, 2013, 03:58:33 pm
Salut,
ha bah c'est une bonne nouvelle ça.
Oui peux tu me dire ce qu'il y a a changé stp ?
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Laurent le Juillet 04, 2013, 04:10:54 pm
1. Vertex::position doit être un Vector3f

2. Dans RenderTarget::resetGLStates mets/change tous les glEnable et autre dont tu as besoin.

3. Dans RenderTarget::draw(const Vertex*, unsigned int, PrimitiveType, const RenderStates&), remplace ça :

glCheck(glVertexPointer(2, GL_FLOAT, sizeof(Vertex), data + 0));
glCheck(glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), data + 8));
glCheck(glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), data + 12));

Par ça :

glCheck(glVertexPointer(3, GL_FLOAT, sizeof(Vertex), data + 0));
glCheck(glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), data + 12));
glCheck(glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), data + 16));

4. A un moment donné il faut que tu forces ContextSettings::depthBits à 24 ou 32, je ne sais pas trop quel endroit serait le meilleur.

Je ne sais pas si ça va marcher du premier coup, donc n'hésite pas à donner du feedback ;D
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Lolilolight le Juillet 04, 2013, 04:32:37 pm
Ok, je vais test ça et je te dis quoi après.
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Lolilolight le Juillet 04, 2013, 06:38:37 pm
Mmm, pas si simple que ça a changé, j'ai modifier le vector2f en vector3f dans la classe sf::Vertex pour la position mais, le cmpilateur me sort cette erreur :

no know conversion from argument 2 from const Vector3f to const sf::transform, dans le fichier transform.hpp ligne 376.

Donc bon je dois aussi modifier la classe Transform pour que ça marche aussi avec des vector3.
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Laurent le Juillet 04, 2013, 07:42:59 pm
Il faut juste ajouter un opérateur * entre sf::Transform et sf::Vector3f. Reprends le même que pour Vector2f (laisse la composante Z inchangée, sf::Transform ne transforme que X et Y).
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Lolilolight le Juillet 04, 2013, 09:36:54 pm
Bon j'ai fait plus simple, dans le draw de rendertarget j'ai carément créer un vector2f et je l'ai utilisé pour faire la transfo et puis j'ai récupérer le vector3f et je l'ai mis dans le vecteur2f vu que je m'en tape du z pour la transformation c'est juste pour le depthtest.

J'ai du modifier toutes les classes qui utilisent la classe Vertex, c'est à dire les Shapes, la classe sf::Text et la classe sf::Sprite et VertexArray aussi pour récupérer le "bound." sans me soucier du z.

Je pense même que je vais rajouter une méthode pour définir un "z-order" dans les classes Shape, text et sprite.

Bref je vais test ça demain avec mon code on verra ce que ça donne, la je viens de finir de recompiler ma version personnelle de SFML.
Je savias pas trop ou coller le paramètre pour définir la valeur pour l'alpha test par contre du coup je l'ai mis dans le resetglstates même si il aurait peut être mieux valu le mettre dans contextsetting mais bon la flemme de changer le fichier wglimpl ou je ne comprend pas grand chose. :/
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Laurent le Juillet 04, 2013, 10:16:17 pm
Citer
je vais test ça demain
Pourquoi est-ce que tu ne dis jamais "tester" ? ;D

Citer
Je savias pas trop ou coller le paramètre pour définir la valeur pour l'alpha test
Je suis pas sûr qu'il faille utiliser autre chose que 0. Avec des valeurs plus grandes tu vas virer des pixels qui ne sont pas totalement transparents et donc avoir un rendu tronqué par rapport à l'image source.
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Lolilolight le Juillet 05, 2013, 07:43:47 am
Citer
Pourquoi est-ce que tu ne dis jamais "tester" ? ;D
Je sais pas.  :o
Citer
Je suis pas sûr qu'il faille utiliser autre chose que 0. Avec des valeurs plus grandes tu vas virer des pixels qui ne sont pas totalement transparents et donc avoir un rendu tronqué par rapport à l'image source.
Ok, super alors je vais la mettre d'office a 0.

Bon me reste encore une chose à améliorer maintenant que j'ai activé le depthtest, c'est rendre le paramètre z facultatif et si je ne spécifie rien alors ça s'affichera dans l'ordre avec lequel je dessine les entités.
Et normalement ça devrait être bon.  :)
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Lolilolight le Juillet 05, 2013, 11:13:50 am
Bon après un 1er essai et en ayant bien fait ce que tu m'as dis (un vector3f pour la position, activer le depthtest dans resetGlStates ainsi que l'alphatest, changer ce que tu m'as dis de changer dans draw, etc...)

Ca ne marche pas avec le depthtest activé ça ne m'affiche rien du tout. (Ecran tout noir.)

La position en z de la caméra à de l'importance dans ce cas la ?

Car tout ce qui se trouve en z = 0 ça s'affiche bien, mais pas les vertex qui ont une coordonnée supérieur à 0.

Et une autre question, peut on jouer avec l'activation du depthtest si je veux faire par exemple un depthtest pour certains vertex mais pas pour d'autre.

En fait je voudrais faire ceci, si la valeur de z est négative, pas de depthtest, ça s'affiche l'un sur l'autre, sinon, depthtest.

Y'a moyen de changer la position de la view en Z ???

Sinon au pire, je mettrai des coordonnées z qui seront uniquement <=0 et je désative le depthtest si le z est positif. (l'inverse donc.)
Ou alors non j'ai mieux :
Tourner la vue pour qu'elle regarde vers des z positif et non des z négatif, comment je peux faire ça ?
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Laurent le Juillet 05, 2013, 11:40:01 am
Citer
La position en z de la caméra à de l'importance dans ce cas la ?
Ah oui, puisque la vue (sf::View) utilise un sf::Transform, elle ne modifie pas l'intervalle de validité pour la coordonnée Z. C'est donc par défaut [-1, 1] si je ne me trompe pas. Il faut donc utiliser des valeurs Z dans cet intervalle.

Citer
Et une autre question, peut on jouer avec l'activation du depthtest si je veux faire par exemple un depthtest pour certains vertex mais pas pour d'autre.
Pas si les vertex en question se trouvent tous dans le même vertex array, puisqu'il faut insérer un appel à glEnable(GL_DEPTH_TEST).

Citer
En fait je voudrais faire ceci, si la valeur de z est négative, pas de depthtest, ça s'affiche l'un sur l'autre, sinon, depthtest.
Ca me paraît difficile à faire sans shader.

Citer
Sinon au pire, je mettrai des coordonnées z qui seront uniquement <=0 et je désative le depthtest si le z est positif. (l'inverse donc.)
Ou alors non j'ai mieux :
Tourner la vue pour qu'elle regarde vers des z positif et non des z négatif
Et ça changerait quoi de faire ça ?
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Lolilolight le Juillet 05, 2013, 11:45:09 am
Citer
Ah oui, puisque la vue (sf::View) utilise un sf::Transform, elle ne modifie pas l'intervalle de validité pour la coordonnée Z. C'est donc par défaut [-1, 1] si je ne me trompe pas. Il faut donc utiliser des valeurs Z dans cet intervalle.

Ok j'ai essayer d'utiliser des valeurs dans cet interval mais malgré ça ça ne marche pas avec le depthtest même si je met toutes les coordonnées de Z à 0 ça ne m'affiche rien.

Citer
Pas si les vertex en question se trouvent tous dans le même vertex array, puisqu'il faut insérer un appel à glEnable(GL_DEPTH_TEST).

Ok donc seulement pour les vertex qui ne se trouvent pas dans le même vertex array, justement c'est mon cas donc ça va.



Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Lolilolight le Juillet 05, 2013, 12:10:19 pm
Bon, bizarre, ça m'affiche quelque chose au 1er affichage et puis ça disparait.

C'est pas grâve si je mets les glDisable et Enable pour le depthtest dans le draw ??? (Si la composante z est négative (c'est le cas par défaut.) alors pas de depthtest, sinon, j'active le depthtest.)

J'ai restreint la position de z dans un intervale entre 0 et 1 quand j'active le depth test mais toujours le même problème. :/

PS : les méthode draw et resetGlStates :

////////////////////////////////////////////////////////////
void RenderTarget::draw(const Vertex* vertices, unsigned int vertexCount,
                        PrimitiveType type, const RenderStates& states)
{
    // Nothing to draw?
    if (!vertices || (vertexCount == 0))
        return;

    if (activate(true))
    {
        // First set the persistent OpenGL states if it's the very first call
        if (!m_cache.glStatesSet)
            resetGLStates();

        // Check if the vertex count is low enough so that we can pre-transform them
        bool useVertexCache = (vertexCount <= StatesCache::VertexCacheSize);
        if (useVertexCache)
        {
            // Pre-transform the vertices and store them into the vertex cache
            for (unsigned int i = 0; i < vertexCount; ++i)
            {
                Vertex& vertex = m_cache.vertexCache[i];
                Vector2f v2Pos = states.transform * Vector2f(vertices[i].position.x, vertices[i].position.y);
                (vertices[i].position.z < 0) ? glCheck(glDisable(GL_DEPTH_TEST)) : glCheck(glEnable(GL_DEPTH_TEST));
                (vertices[i].position.z > 1) ? vertex.position = Vector3f(v2Pos.x, v2Pos.y, 1) :  vertex.position = Vector3f(v2Pos.x, v2Pos.y, vertices[i].position.z);
                vertex.color = vertices[i].color;
                vertex.texCoords = vertices[i].texCoords;
            }

            // Since vertices are transformed, we must use an identity transform to render them
            if (!m_cache.useVertexCache)
                applyTransform(Transform::Identity);
        }
        else
        {
            applyTransform(states.transform);
        }

        // Apply the view
        if (m_cache.viewChanged)
            applyCurrentView();

        // Apply the blend mode
        if (states.blendMode != m_cache.lastBlendMode)
            applyBlendMode(states.blendMode);

        // Apply the texture
        Uint64 textureId = states.texture ? states.texture->m_cacheId : 0;
        if (textureId != m_cache.lastTextureId)
            applyTexture(states.texture);

        // Apply the shader
        if (states.shader)
            applyShader(states.shader);

        // If we pre-transform the vertices, we must use our internal vertex cache
        if (useVertexCache)
        {
            // ... and if we already used it previously, we don't need to set the pointers again
            if (!m_cache.useVertexCache)
                vertices = m_cache.vertexCache;
            else
                vertices = NULL;
        }

        // Setup the pointers to the vertices' components
        if (vertices)
        {
            const char* data = reinterpret_cast<const char*>(vertices);
            glCheck(glVertexPointer(3, GL_FLOAT, sizeof(Vertex), data + 0));
            glCheck(glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), data + 12));
            glCheck(glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), data + 16));
        }

        // Find the OpenGL primitive type
        static const GLenum modes[] = {GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_TRIANGLES,
                                       GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_QUADS};
        GLenum mode = modes[type];

        // Draw the primitives
        glCheck(glDrawArrays(mode, 0, vertexCount));

        // Unbind the shader, if any
        if (states.shader)
            applyShader(NULL);

        // Update the cache
        m_cache.useVertexCache = useVertexCache;
    }
}
 

////////////////////////////////////////////////////////////
void RenderTarget::resetGLStates()
{
    if (activate(true))
    {
        // Make sure that GLEW is initialized
        priv::ensureGlewInit();

        // Define the default OpenGL states
        glCheck(glDisable(GL_CULL_FACE));
        glCheck(glDisable(GL_LIGHTING));
        glCheck(glDisable(GL_DEPTH_TEST));
        glCheck(glDisable(GL_ALPHA_TEST));
        glCheck(glEnable(GL_TEXTURE_2D));
        glCheck(glEnable(GL_BLEND));
        glCheck(glMatrixMode(GL_MODELVIEW));
        glCheck(glEnableClientState(GL_VERTEX_ARRAY));
        glCheck(glEnableClientState(GL_COLOR_ARRAY));
        glCheck(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
        glCheck(glEnable(GL_ALPHA_TEST));
        glCheck(glAlphaFunc(GL_GREATER, 0));
        m_cache.glStatesSet = true;

        // Apply the default SFML states
        applyBlendMode(BlendAlpha);
        applyTransform(Transform::Identity);
        applyTexture(NULL);
        if (Shader::isAvailable())
            applyShader(NULL);
        m_cache.useVertexCache = false;

        // Set the default view
        setView(getView());
    }
}
 
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Laurent le Juillet 05, 2013, 12:12:00 pm
Dans RenderTarget::clear il faut ajouter GL_DEPTH_BIT à glClear, et dans RenderTarget::resetGLStates il faut ajouter glClearDepth(0).
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Lolilolight le Juillet 05, 2013, 12:21:35 pm
C'est GL_DEPTH_BUFFER_BIT. ^^
Ok je vais tester ça.
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Lolilolight le Juillet 05, 2013, 12:30:40 pm
Ca ne marche toujours pas, même problème ça s'affiche une fois puis ça disparait.  :o
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Lolilolight le Juillet 05, 2013, 12:42:13 pm
Faut pas faire glClearDepth(1) plutôt ?
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Lolilolight le Juillet 05, 2013, 01:04:48 pm
Bon peu importe dans tout les cas ça ne résoud pas le problème.
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Laurent le Juillet 05, 2013, 01:14:30 pm
Citer
Faut pas faire glClearDepth(1) plutôt ?
Si ;)

Tu as bien pensé à appeler glDepthMask(GL_TRUE) aussi ?
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Lolilolight le Juillet 05, 2013, 01:27:41 pm
J'ai rajouté le glDepthMask a true, mais toujours le même problème, tout ce que j'affiche après avoir activé le depthtest s'affiche puis disparait.

Voici mes fonction :
////////////////////////////////////////////////////////////
void RenderTarget::resetGLStates()
{
    if (activate(true))
    {
        // Make sure that GLEW is initialized
        priv::ensureGlewInit();

        // Define the default OpenGL states
        glCheck(glDisable(GL_CULL_FACE));
        glCheck(glDisable(GL_LIGHTING));
        glCheck(glDisable(GL_DEPTH_TEST));
        glCheck(glDisable(GL_ALPHA_TEST));
        glCheck(glEnable(GL_TEXTURE_2D));
        glCheck(glEnable(GL_BLEND));
        glCheck(glMatrixMode(GL_MODELVIEW));
        glCheck(glEnableClientState(GL_VERTEX_ARRAY));
        glCheck(glEnableClientState(GL_COLOR_ARRAY));
        glCheck(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
        glCheck(glEnable(GL_ALPHA_TEST));
        glCheck(glAlphaFunc(GL_GREATER, 0));
        glCheck(glClearDepth(1));
        glCheck(glDepthMask(GL_TRUE));

        m_cache.glStatesSet = true;

        // Apply the default SFML states
        applyBlendMode(BlendAlpha);
        applyTransform(Transform::Identity);
        applyTexture(NULL);
        if (Shader::isAvailable())
            applyShader(NULL);
        m_cache.useVertexCache = false;

        // Set the default view
        setView(getView());
    }
}
 

////////////////////////////////////////////////////////////
void RenderTarget::draw(const Vertex* vertices, unsigned int vertexCount,
                        PrimitiveType type, const RenderStates& states)
{
    // Nothing to draw?
    if (!vertices || (vertexCount == 0))
        return;

    if (activate(true))
    {
        // First set the persistent OpenGL states if it's the very first call
        if (!m_cache.glStatesSet)
            resetGLStates();

        // Check if the vertex count is low enough so that we can pre-transform them
        bool useVertexCache = (vertexCount <= StatesCache::VertexCacheSize);
        if (useVertexCache)
        {
            // Pre-transform the vertices and store them into the vertex cache
            for (unsigned int i = 0; i < vertexCount; ++i)
            {
                Vertex& vertex = m_cache.vertexCache[i];
                Vector2f v2Pos = states.transform * Vector2f(vertices[i].position.x, vertices[i].position.y);
                (vertices[i].position.z < 0) ? glCheck(glDisable(GL_DEPTH_TEST)) : glCheck(glEnable(GL_DEPTH_TEST));
                (vertices[i].position.z > 1) ? vertex.position = Vector3f(v2Pos.x, v2Pos.y, 1) :  vertex.position = Vector3f(v2Pos.x, v2Pos.y, vertices[i].position.z);
                vertex.color = vertices[i].color;
                vertex.texCoords = vertices[i].texCoords;
            }

            // Since vertices are transformed, we must use an identity transform to render them
            if (!m_cache.useVertexCache)
                applyTransform(Transform::Identity);
        }
        else
        {
            applyTransform(states.transform);
        }

        // Apply the view
        if (m_cache.viewChanged)
            applyCurrentView();

        // Apply the blend mode
        if (states.blendMode != m_cache.lastBlendMode)
            applyBlendMode(states.blendMode);

        // Apply the texture
        Uint64 textureId = states.texture ? states.texture->m_cacheId : 0;
        if (textureId != m_cache.lastTextureId)
            applyTexture(states.texture);

        // Apply the shader
        if (states.shader)
            applyShader(states.shader);

        // If we pre-transform the vertices, we must use our internal vertex cache
        if (useVertexCache)
        {
            // ... and if we already used it previously, we don't need to set the pointers again
            if (!m_cache.useVertexCache)
                vertices = m_cache.vertexCache;
            else
                vertices = NULL;
        }

        // Setup the pointers to the vertices' components
        if (vertices)
        {
            const char* data = reinterpret_cast<const char*>(vertices);
            glCheck(glVertexPointer(3, GL_FLOAT, sizeof(Vertex), data + 0));
            glCheck(glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), data + 12));
            glCheck(glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), data + 16));
        }

        // Find the OpenGL primitive type
        static const GLenum modes[] = {GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_TRIANGLES,
                                       GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_QUADS};
        GLenum mode = modes[type];

        // Draw the primitives
        glCheck(glDrawArrays(mode, 0, vertexCount));

        // Unbind the shader, if any
        if (states.shader)
            applyShader(NULL);

        // Update the cache
        m_cache.useVertexCache = useVertexCache;
    }
}
 

////////////////////////////////////////////////////////////
void RenderTarget::clear(const Color& color)
{
    if (activate(true))
    {
        glCheck(glClearColor(color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f));
        glCheck(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
    }
}
 

Ai je encore oublié quelque chose ? X_X
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Laurent le Juillet 05, 2013, 01:31:46 pm
Tu pars avec GL_ALPHA_TEST désactivé, et tu ne l'actives pas au bon endroit. Déjà, ce morceau de code est exécuté uniquement lorsque le nombre de vertex est très petit (de mémoire ça doit être 4). Ensuite, admettons que tu sois dans ce cas de figure, tu fais potentiellement plein de glEnable/glDisable à la suite sans rien dessiner entre chaque appel, ça n'aura aucun effet. En plus l'état final ne va dépendre que de la coordonnée Z du dernier vertex, ton algorithme est mauvais.
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Lolilolight le Juillet 05, 2013, 01:44:44 pm
Citer
Tu pars avec GL_ALPHA_TEST désactivé, et tu ne l'actives pas au bon endroit. Déjà, ce morceau de code est exécuté uniquement lorsque le nombre de vertex est très petit (de mémoire ça doit être 4).

Je dois l'activer quand le GL_ALPHA_TEST ?
Et hum, ça ne dessine pas tout les vertex d'un vertexarray cette méthode draw ?
Pourquoi tu me dis que ça ne va marche que lorsque le nombre de vertex est très petits ?

Citer
Ensuite, admettons que tu sois dans ce cas de figure, tu fais potentiellement plein de glEnable/glDisable à la suite sans rien dessiner entre chaque appel, ça n'aura aucun effet.
Ha ok il faut obligatoirement dessiner entre chaque appel à Enable et disable. ^^
En fait je veux activer et désactiver le depthtest au dessin de chaque vertexarray vu que je vois que toutes tes classes utilisent des vertexarray mais c'est ou que tu dessines ses vertexarray ???

Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Laurent le Juillet 05, 2013, 01:54:21 pm
Citer
Je dois l'activer quand le GL_ALPHA_TEST ?
Avant de dessiner le truc pour lequel tu veux que ce soit actif. Les états OpenGL ne font rien quand tu les changes, c'est uniquement lors du prochain dessin qu'ils sont pris en compte.

Citer
Et hum, ça ne dessine pas tout les vertex d'un vertexarray cette méthode draw ?
Ca dessine ce qu'on lui passe en paramètre, donc si tu as appelé window.draw(vertexArray), oui ça va tout dessiner.

Citer
Pourquoi tu me dis que ça ne va marche que lorsque le nombre de vertex est très petits ?
Tu vois bien que ce morceau de code est conditionné par un "if (vertexCount < xxx)". Et puis lis bien les commentaires, je pense qu'ils sont assez explicites quant à ce que fait chaque morceau de code ;)

Citer
En fait je veux activer et désactiver le depthtest au dessin de chaque vertexarray vu que je vois que toutes tes classes utilisent des vertexarray mais c'est ou que tu dessines ses vertexarray
C'est bien à cet endroit.

Ton problème c'est que tu veux activer ou désactiver le depth test par vertex, alors que tu ne peux le faire que par entité (tu peux le changer entre deux draw).
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Lolilolight le Juillet 05, 2013, 03:49:58 pm
Ha, ok, donc il y a deux fonction draw, une pour dessiner en utilisant les classe sfml de plus haut niveau et une pour dessiner en utilisant les entités d'opengl de plus bas niveau.
Mais je suppose que le draw qui dessine les entités de plus haut niveau utilise la fonction draw qui dessine les entités de plus bas niveau.

Ok bah ça va je pense que j'ai compris ou je dois faire les glDisable et les glEnable alors.  :)

Juste avant d'appeler la fonction draw qui dessine les entités de plus haut niveau dans RenderTarget c'est ça ?

Bref je vais tester ça une fois que mon PC sera réparé mais je dois rajouter une méthode virtuelle dans la classe drawable pour savoir si je dois activer le depthtest et l'alphatest.
Et si j'active le depthtest je pourrai redéfinir la fonction draw en envoyant au 2ème draw des vertex avec un z différent (ce que j'ai déjà fais d'ailleurs.) et ça va peut être enfin marcher. (Youhou!)

Au départ je pensais faire les glDisable et Enable dans la fonction draw de plus bas niveau mais en effet ce n'est pas le bonne endroit. (Vu que tu dessines surement toute l'entité d'un coup et pas vertex par vertex.)
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Laurent le Juillet 05, 2013, 04:13:06 pm
Citer
Mais je suppose que le draw qui dessine les entités de plus haut niveau utilise la fonction draw qui dessine les entités de plus bas niveau.
Oui, tout finit par arriver dans le draw(const Vertex*, etc.).

Citer
Juste avant d'appeler la fonction draw qui dessine les entités de plus haut niveau dans RenderTarget c'est ça ?
Non, tu peux le faire dans le draw bas niveau, mais simplement il faut le faire une seule fois, et non pas une fois pour chaque vertex comme tu le faisais, et qui plus est pas dans un morceau de code qui n'est exécuté que sous certaines conditions.
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Lolilolight le Juillet 05, 2013, 04:18:34 pm
Ok ça va j'ai compris merci.  :)
C'est l'un des rares codes source ou je ne me perd pas de trop :D
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Lolilolight le Juillet 06, 2013, 11:34:22 am
Il faut dire que j'avais mal lu le code, je pensais que tu mettais tout dans le cache et que tu appliquais les pré-transformation puis que tu dessinais tout.

Mais en relisant mieux le code ça ne rentre dans le if que si il n'y a que 4 vertex dans le tableau.
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Lolilolight le Juillet 19, 2013, 10:25:48 pm
Bon bah j'ai récupéré mon PC et ça marche sauf que j'ai un bord noir qui s'affiche sur le bord de mes tiles.
(http://zupimages.net/up/3/1561956604.jpg)
Franchement ça m'inquiète parce que toutes mes tiles du sol son sur la même couche donc même si y'a de la semi-transparence sur les bords, elles devraient s'emboîter correctement les unes dans les autres comme avant.
J'ai utiliser les masque de calques avec GIMP pour les bords des tiles.
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Laurent le Juillet 19, 2013, 10:38:48 pm
Et bien c'est très exactement le problème de la semi-transparence non ? Les tiles sont devant à cause de leur valeur Z, mais elles sont dessinées en premier donc elles se mélangent avec la couleur de fond plutôt qu'avec les tiles du dessous (qui ne sont pas encore dessinées).
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Lolilolight le Juillet 20, 2013, 10:09:04 pm
Ouiais c'était ça, j'avais oublié que j'avais de la semi-transparence pour les tiles au sol.
Bref, c'est pas grâve, j'ai retiré le z pour les tiles au sol, je n'en ai de toute façon pas besoin, là je peux m'arranger facilement pour avoir un type de tile pour le sol par tileset et les ordres d'affichage ne changent pas pour le sol. (L'herbe s'affiche toujours au dessus de la pière pour bien faire la transition entre les tiles.)

Par contre pour toutes les autres tiles (bâtiments, murs, personnage, arbres, etc...), j'ai besoin du depthtest absolument si j'utilise des tilemaps car le personnage peut être devant ou derrière les murs, bâtiments, etc..., les murs peuvent eux aussi être devant ou derrière les bâtiments, etc...)
Mais bon ça ne me pose pas de problème car il n'y a que les tiles du sol qui contiennent de la semi-tranparence. (Dont les bords qui ont des pixels avec une valeur de alpha très petites du coups bah ça se mélangeais avec la couleur de fond et non pas avec la tile du dessous.)

Bref j'ai trouvé la solution en retirant le z pour les couches du sol donc mon problème est résolu et ça tourne plus vite, il faudra juste que je ne fasse pas de semi-transparence pour les autres tiles que celles au sol.
Sinon je suis reparti pour faire de l'affichage sprite par sprite. (Sauf peut être si j'utilise une render texture..., mais je ne sais pas exactement comment ça marche ça, mais il me semble que ça fait aussi appel à plusieurs draw pour dessiner tout sur la rendertexture donc..., je n'y gagnerai pas au niveau des perfs.)


Performances qui ont besoin d'être très bonne surtout dans mon cas.
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Lolilolight le Juillet 22, 2013, 11:31:10 am
Bon finalement j'en suis revenu à un système de draw sprite par sprite pour les raisons suivantes :

-Le framerate n'augmente pas. (Même si je fais qu'un seul appel à draw plutôt que plusieurs.)
-Les tiles ne s'affichent pas toujours dans l'ordre dans lequel elles devraient (erreur dans mon algorithme qui modifier le z de mes entités surement.), donc, je préfère les insérer au bonne endroit dans mon std::vector. (C'est plus simple.)
Mais bon je laisse quand même ma version personalisée de la SFML, ça pourra être utile dans certains cas.

Voici mon algorithme qui modifie le z de mes tiles, je l'ai mis en commentaire car il ne fonctionne pas mais quand j'insère simpelement les tiles au bonne endroit dans le vecteur et que je les dessines dans l'ordre sans passer par une tile map, pas de soucis.

void MyCanvas::addDynamicTile (Tile *tile, vector<Tile*> &visibleTiles) {
     //On insère la tile au bonne endroit dans le vecteur.
     vector<Tile*> oldVector = visibleTiles;
     vector<Tile*> behind, before;
     visibleTiles.clear();
     //On va rechercher toutes les tiles qui sont devant et derrière la tile.
     for (int i = 0; i < oldVector.size(); i++) {
         if (oldVector[i]->getZOrder() < Tile::MIN_ENTITY_Z_ORDER) {
            visibleTiles.push_back(oldVector[i]);
         } else {
             Vec2f centerDT = tile->getCenter();

             if (visibleTiles[i]->getType() == Entity::E_WALL) {

                 vector<Segment*> segments = lm->getTileSegWall(visibleTiles[i]);
                 int dist = segments[0]->getOrig().computeDist(centerDT);
                 Segment &seg = *segments[0];
                 for (unsigned int j = 1; j < segments.size(); j++) {
                     int tmpDist = segments[j]->getOrig().computeDist(centerDT);
                     if (tmpDist < dist) {
                         dist = tmpDist;
                         seg = *segments[j];
                     }
                 }

                 Segment seg2 (seg.getOrig(), centerDT);
                 int det = seg.getDir().x * seg2.getDir().y - seg.getDir().y * seg2.getDir().x;
                 (det >= 0) ? behind.push_back(oldVector[i]) : before.push_back(oldVector[i]);
             } else {
                 Vec2f center = oldVector[i]->getCenter();
                 Vec2f size = oldVector[i]->getSize();
                 Vec2f orig (center.x - size.x * 0.5f, center.y);
                 Vec2f ext (orig.x + size.x * 0.5f, center.y);
                 Segment seg (orig, ext);
                 Segment seg2 (orig, centerDT);
                 int det = seg.getDir().x * seg2.getDir().y - seg.getDir().y * seg2.getDir().x;
                 (det >= 0) ? behind.push_back(oldVector[i]) : before.push_back(oldVector[i]);
             }
         }
     }
     /*On ajoute toutes les tiles qui sont derrière, puis on ajoute la tile à insérer
      et enfin on ajoute toutes les tiles qui sont devant.*/

    for (unsigned int i = 0; i < behind.size(); i++) {
        visibleTiles.push_back(behind[i]);
    }

    //(behind.size() > 0) ? tile->setZOrder(behind[behind.size() - 1]->getZOrder() + 1) : tile->setZOrder(Tile::MIN_ENTITY_Z_ORDER);

    visibleTiles.push_back(tile);
    for (unsigned int i = 0; i < before.size(); i++) {
        /*if (!before[i]->isZOrderSaved())
            before[i]->saveZOrder();
        before[i]->setZOrder(tile->getZOrder() + 1);*/

        visibleTiles.push_back(before[i]);
    }
}
 

Au cas ou quelqu'un trouverait l'erreur.
Titre: Re : Définir un ordre d'affichage par vertex.
Posté par: Lolilolight le Juillet 28, 2013, 12:36:12 pm
Bon j'ai fais comme ça, par défaut si on ne le spécifie pas, le z du vertex vaut -1 et on désactive l'alpha testing et le depthtest, sinon, si le z est entre 0 et 1, on active l'alpha testing et le depthtest, et ça marche. :)

Je peux donc choisir ce que je veux faire, personnellement je trouve ça plus cool. ^^