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

Développement 2D, 3D et Jeux Discussion :

3D : comment gérer la semi-transparence avec le depthtest ?


Sujet :

Développement 2D, 3D et Jeux

  1. #1
    Invité
    Invité(e)
    Par défaut 3D : comment gérer la semi-transparence avec le depthtest ?
    Salut, je suis entrain de coder un moteur de jeux.
    Mais contrairement aux moteurs de jeu existant, je voudrais que celui-ci :

    -Puisse choisir comment effectuer un rendu en fonction des fonctionnalités opengl supportée par le PC.
    -Permette de créer n'importe quel type de jeux ou bien d'application de manière sécurisée sans devoir passé par trop de bibliothèques ou de gros framework qui prennent parfois du temps à installer, pire encore si on doit les recompiler. (Le framework n'utilisera donc que sfml et openssl comme dépendance, qui sont des dépendances légères)
    -Offre de la flexibilité en permettant au développeur de choisir si il veut utiliser tel fonctionnalité ou bien de coupler le framework avec une autre bibliothèque.
    -Puisse offrir (si la carte graphique le permet) des fonctionnalités plus avancée avec un depth test qui gère la semi-transparence.

    Si le PC ne supporte pas le langage GLSL, les objects sont dessiné dans l'ordre de leur position en Z. (ne fonctionne que pour la 2D ou les textures sont toujours plate en z)

    Car si les textures semi-transparente se croisent en z, il faut faire un test par pixel pour savoir quel sont les texels les plus transparents qui sont devant la caméra, et faire en sortent que ces texels ne cachent pas les texels de l'autre texture.

    Alors, j'ai essayer de faire deux fragment shader :

    Le 1er écrit les valeurs de z des fragments dans la composante b d'une "depthtexture", si et seulement si le z du texel de l'entité qu'on veut dessiner est plus grand que le z du pixel couramment affiché à l'écran et que sa composante alpha est plus grande ou égale à celle du texel déjà présent dans la depthtexture ce qui donne le shader suivant : (Donc un depthtest basique mais avec un alpha test plus évolué que celui offert par opengl car je ne compare pas l'alpha des texels par rapport à une valeur bien précise mais par rapport à ce qui a déjà été dessiné)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    "uniform sampler2D depthBuffer;"
                "uniform sampler2D texture;"
                "uniform vec3 resolution;"
                "void main () {"
                      "vec2 position = ( gl_FragCoord.xy / resolution.xy );"
                      "vec4 color = texture2D(depthBuffer, position);"
                      "vec4 pixel = texture2D(texture, gl_TexCoord[0].xy);"
                      "if (abs(gl_FragCoord.z) > color.z && pixel.a >= color.a) {"
                         "gl_FragColor = vec4(0, 0, abs(gl_FragCoord.z), pixel.a);"
                      "} else {"
                         "gl_FragColor = color;"
                      "}"
                "}";on
    On dirait que la composante z du fragment doit toujours être comprise entre 0 et -1 sinon opengl ne dessine rien.

    J'ai donc passé la matrice de projection suivante à opengl : (afin d'essayer d'avoir un z qui soit toujours négatif dans le vertex shader, 0 = le fragment est sur le plan éloigné, -1 = le fragment est sur le plan le plus près.)
    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
     
    matrix4f.m11 = (2 * scale.x) / (r - l);
        matrix4f.m12 = 0;
        matrix4f.m13 = 0;
        matrix4f.m14 = -((r + l) / (r - l));
        matrix4f.m21 = 0;
        matrix4f.m22 = (2 * scale.y) / (t - b);
        matrix4f.m23 = 0;
        matrix4f.m24 = -((t + b) / (t - b));
        matrix4f.m31 = 0;
        matrix4f.m32 = 0;
        matrix4f.m33 = (2 * scale.z) / (f - n);
        matrix4f.m34 = -((f + n) / (f - n));
        matrix4f.m41 = 0;
        matrix4f.m42 = 0;
        matrix4f.m43 = 0;
        matrix4f.m44 = 1;
    Mais déjà là je ne vois pas très bien comment faire.

    Bref ce shader est sensé régler une partie du problème c'est à dire lorsque les fragments les plus transparent de la 2ème texture semi-transparente sont devant ceux de la 1ère texture semi-transparente.

    Par contre il faut encore régler le problème lorsque les fragments les plus semi-transparents de la 2ème texture sont derrière, afin de quand même les envoyé à opengl pour qu'il fasse le blending, j'ai donc écris se shader qui contient les valeurs rgba des texels de ce qui est dessiné à l'écran : (je refais donc un second depthtext et ensuite un second alpha test pour le cas inverse)

    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
     
    "uniform sampler2D depthBuffer;"
                "uniform sampler2D frameBuffer;"
                "uniform sampler2D texture;"
                "uniform vec3 resolution;"
                "void main () {    "
                    "vec2 position = ( gl_FragCoord.xy / resolution.xy );"
                    "vec4 depth = texture2D(depthBuffer, position);"
                    "vec4 color = texture2D(frameBuffer, position);"
                    "vec4 pixel = texture2D(texture, gl_TexCoord[0].xy);"
                    "if (abs(gl_FragCoord.z) >= depth.z) {"
                        "gl_FragColor = pixel;"
                    "} else if (color.a < pixel.a) {"
                        "gl_FragColor = pixel;"
                    "} else {"
                        "gl_FragColor = color;"
                    "}"
                "}";
    Mais, cela ne marche pas et ça me donne un résultat bizarre :

    Nom : problemeShaders.jpg
Affichages : 119
Taille : 81,2 Ko

    Ici je suis en 2D et donc la position en z de mes objets est la même que la position en y.

    Sinon j'utilise SFML pour tout dessiner sur des textures de rendu et faire abstraction des fonctions opengl :

    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
     
    #include "../../../include/odfaeg/Graphics/fastRenderComponentManager.h"
    #include "../../../include/odfaeg/Graphics/2D/fastRenderComponent.h"
    using namespace odfaeg::g2d;
    namespace odfaeg {
    FastRenderComponentManager::FastRenderComponentManager(RenderWindow& window) : window (window) {
            sf::Vector3i resolution ((int) window.getSize().x, (int) window.getSize().y, window.getView().getSize().z);
            depthBuffer = new RenderTexture();
            frameBuffer = new RenderTexture();
            depthBuffer->create(resolution.x, resolution.y);
            frameBuffer->create(resolution.x, resolution.y);
            frameBuffer->setView(window.getView());
            depthBuffer->setView(window.getView());
     
            if (Shader::isAvailable()) {
                frameBufferGenerator = new Shader();
                depthBufferGenerator = new Shader();
                const std::string vertexShader =
                "void main () {"
                    "gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;"
                    "gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;"
                    "gl_FrontColor = gl_Color;"
                "}";
                const std::string  depthGenFragShader =
                "uniform sampler2D depthBuffer;"
                "uniform sampler2D texture;"
                "uniform vec3 resolution;"
                "void main () {"
                      "vec2 position = ( gl_FragCoord.xy / resolution.xy );"
                      "vec4 color = texture2D(depthBuffer, position);"
                      "vec4 pixel = texture2D(texture, gl_TexCoord[0].xy);"
                      "if (abs(gl_FragCoord.z) > color.z && pixel.a >= color.a) {"
                         "gl_FragColor = vec4(0, 0, abs(gl_FragCoord.z), pixel.a);"
                      "} else {"
                         "gl_FragColor = color;"
                      "}"
                "}";
                const std::string frameBufferGenFragShader =
                "uniform sampler2D depthBuffer;"
                "uniform sampler2D frameBuffer;"
                "uniform sampler2D texture;"
                "uniform vec3 resolution;"
                "void main () {    "
                    "vec2 position = ( gl_FragCoord.xy / resolution.xy );"
                    "vec4 depth = texture2D(depthBuffer, position);"
                    "vec4 color = texture2D(frameBuffer, position);"
                    "vec4 pixel = texture2D(texture, gl_TexCoord[0].xy);"
                    "if (abs(gl_FragCoord.z) >= depth.z) {"
                        "gl_FragColor = pixel;"
                    "} else if (color.a < pixel.a) {"
                        "gl_FragColor = pixel;"
                    "} else {"
                        "gl_FragColor = color;"
                    "}"
                "}";
                if (!depthBufferGenerator->loadFromMemory(vertexShader, depthGenFragShader))
                    throw Erreur(50, "Failed to load depth buffer generator shader", 0);
                if (!frameBufferGenerator->loadFromMemory(vertexShader, frameBufferGenFragShader))
                    throw Erreur(51, "Failed to load frame buffer generator shader", 0);
                 depthBufferGenerator->setParameter("resolution",resolution.x, resolution.y, resolution.z);
                 frameBufferGenerator->setParameter("resolution",resolution.x, resolution.y, resolution.z);
            }
        }
        void FastRenderComponentManager::addRenderComponent(FastRenderComponent* component) {
            components.push_back(component);
        }
        RenderWindow& FastRenderComponentManager::getWindow() {
            return window;
        }
        /*void FastRenderComponentManager::initComponents() {
            for (unsigned int i = 0; i < components.size(); i++) {
                components[i]->init();
            }
        }*/
        void FastRenderComponentManager::clearBufferBits(sf::Color color) {
            clrColor = color;
            frameBuffer->clear(color);
        }
        void FastRenderComponentManager::clearDepthBits() {
            depthBuffer->clear(sf::Color(0, 0, 0, 0));
        }
        g2d::Tile FastRenderComponentManager::getFrameBufferTile () const {
            sf::IntRect subRect(0, 0, frameBuffer->getView().getSize().x, frameBuffer->getView().getSize().y);
            g2d::Tile tile (&frameBuffer->getTexture(), Vec2f(0, 0), Vec2f(frameBuffer->getView().getSize().x, frameBuffer->getView().getSize().y), subRect);
            return tile;
        }
        g2d::Tile FastRenderComponentManager::getDepthBufferTile() {
            sf::IntRect subRect(0, 0, depthBuffer->getView().getSize().x, depthBuffer->getView().getSize().y);
            g2d::Tile tile (&depthBuffer->getTexture(), Vec2f(0, 0), Vec2f(depthBuffer->getView().getSize().x, depthBuffer->getView().getSize().y), subRect);
            return tile;
        }
        void FastRenderComponentManager::draw(Drawable& drawable, RenderStates states) const {
            states.shader = frameBufferGenerator;
            frameBufferGenerator->setParameter("depthBuffer", depthBuffer->getTexture());
            frameBufferGenerator->setParameter("frameBuffer", frameBuffer->getTexture());
            frameBufferGenerator->setParameter("texture", Shader::CurrentTexture);
            frameBuffer->setView(window.getView());
            frameBuffer->draw(drawable, states);
            frameBuffer->display();
            depthBuffer->setView(window.getView());
            depthBufferGenerator->setParameter("depthBuffer", depthBuffer->getTexture());
            depthBufferGenerator->setParameter("texture", Shader::CurrentTexture);
            states.shader = depthBufferGenerator;
            depthBuffer->draw(drawable, states);
            depthBuffer->display();
            states.shader = nullptr;
            g2d::Tile tile = getFrameBufferTile();
            tile.setCenter(frameBuffer->getView().getPosition());
            window.draw(tile);
        }
        sf::Color FastRenderComponentManager::getClrColor() {
            return clrColor;
        }
        FastRenderComponentManager::~FastRenderComponentManager() {
            delete frameBuffer;
            delete depthBuffer;
            delete depthBufferGenerator;
            delete frameBufferGenerator;
            for (unsigned int i = 0; i < components.size(); i++) {
                delete components[i];
            }
        }
    }
    L'idée est de dessiner toutes mes entités sur des composants de rendu (en leur passant un shader, une caméra, etc...), puis de dessiner tout ses composants à l'aide d'une classe qui choisira la meilleure option de rendu pour rendre tout les composants. (en fonction des fonctionnalité opengl supportées par mon PC)
    Et donc de faire ainsi du multi-pass rendering d'objets 3D ou 2D à l'aide d'un design à base de composants.
    Dernière modification par Neckara ; 16/04/2014 à 06h27. Motif: librairie -> bibliothèque

  2. #2
    Invité
    Invité(e)
    Par défaut
    Désolé, je crois que j'ai trouvé le problème, c'est que les tiles du sol qui sont plus basse que le centre de mes autres objets ont un z plus grand hors que ça ne devrait pas être le cas, je devrais donc définir une position en z pour chaque tile...

    Mais ça me parait assez lourd à faire surtout pour les entités qui sont animées (comme par exemple le personnage) et ou je ne connais pas leur z à l'avance.

    Ou alors je dois juste définir une position z pour les tiles du sol et pour le reste définir le z en fonction du centre de la tile..., bref, je sèche un peu pour trouver une bonne solution.

    PS : mais je crois que mon shader merde quand même un petit peu. :/

    Si quelqu'un à une solution qui n'utilise pas de shader je suis preneur également. (Genre écrire et lire des pixels dans une texture avec un PBO mais je suis pas sûr que ça soit très optimal et si ont peut faire ça comme ça avec une PBO)

  3. #3
    Membre expérimenté

    Profil pro
    Programmeur
    Inscrit en
    Août 2002
    Messages
    1 091
    Détails du profil
    Informations personnelles :
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Programmeur

    Informations forums :
    Inscription : Août 2002
    Messages : 1 091
    Points : 1 679
    Points
    1 679
    Par défaut
    Si tu fais de la 2D isométrique avec des tiles qui ne s'entrecroisent pas (si tes tiles sont des simples surfaces 2D), alors c'est le cas le plus simple.
    Tu n'as pas besoin du test de profondeur par pixel (ZBuffer), le test de profondeur est là pour les cas complexes de visibilité (polygones non ordonnés, entrecroisements).
    En gros tu détermines à l'avance quels sont les objets les plus lointains et les objets les plus proches et tu les traces dans cet ordre (du plus lointain au plus proche). Le fait de tracer les plus proches en dernier va faire qu'ils vont "naturellement" cacher les objets plus lointains sans avoir besoin de faire un test de profondeur. C'est ce qu'on appelle l'algorithme du peintre (le peintre qui peint par couche successives qui cachent partiellement les couches précédentes). Pour la semi transparence, tu actives l'effet que tu veux et là, pareil, l'algo du peintre va tirer partie de l'ordre de rendu pour que la semi transparence "marche".

    LeGreg

    Mon site web | Mon blog | Mes photos | Groupe USA
    > BONJOUR, JE SUIS NOUVEAU SUR CE FORUM
    > presse la touche caps lock, stp
    > OH.. MERCI C EST BEAUCOUP PLUS FACILE COMME CA

  4. #4
    Invité
    Invité(e)
    Par défaut
    Oui pour les textures qui ne se croisent pas je fais comme ça mais le problème c'est que moi je voudrais faire des meilleurs rendus avec des textures qui se croisent, bref...

    J'ai essayer de passer une variable en plus à mon shader qui est, la position en z du composant sur lequel je trace mes entités ce qui fait que j'ai deux position en z (la position en z de la tile (qui est égale à sa position en y) et la position en z du composant.

    Je dessine donc le sol sur un composant qui a un z de 0, et le reste sur un autre composant qui a un z de 1.

    Et j'ai essayer de faire ceci dans mes 2 shaders :

    Si la position en z du composant sur lequel je dessine est plus grande que la position en z du composant du pixel courant, alors, je dessine le pixel sans effectuer de depth test et d'alpha test. (Car je sais que son z est plus grand)

    Si la position en z du composant sur lequel je dessine est égale à celle du composant du pixel courant, alors j'effectue un depth test et un alpha test.

    Sinon, si la position en z du composant sur lequel je dessine est plus petite que celle du composant du pixel courant, alors, je ne dessine pas le pixel.

    Voilà ce que ça donne au niveau de mes shaders :

    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
     
    const std::string vertexShader =
                "void main () {"
                    "gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;"
                    "gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;"
                    "gl_FrontColor = gl_Color;"
                "}";
                const std::string  depthGenFragShader =
                "uniform sampler2D depthBuffer;"
                "uniform sampler2D texture;"
                "uniform vec3 resolution;"
                "uniform int l;"
                "void main () {"
                      "vec2 position = ( gl_FragCoord.xy / resolution.xy );"
                      "vec4 color = texture2D(depthBuffer, position);"
                      "vec4 pixel = texture2D(texture, gl_TexCoord[0].xy);"
                      "if (l > color.y) {"
                           "gl_FragColor = vec4(0, l, abs(gl_FragCoord.z), pixel.a);"
                      "} else if (l == color.y && abs(gl_FragCoord.z) > color.z && pixel.a >= color.a) {"
                           "gl_FragColor = vec4(0, l, abs(gl_FragCoord.z), pixel.a);"
                      "} else {"
                           "gl_FragColor = color;"
                      "}"
                "}";
                const std::string frameBufferGenFragShader =
                "uniform sampler2D depthBuffer;"
                "uniform sampler2D frameBuffer;"
                "uniform sampler2D texture;"
                "uniform vec3 resolution;"
                "uniform int l;"
                "void main () {	"
                    "vec2 position = ( gl_FragCoord.xy / resolution.xy );"
                    "vec4 depth = texture2D(depthBuffer, position);"
                    "vec4 color = texture2D(frameBuffer, position);"
                    "vec4 pixel = texture2D(texture, gl_TexCoord[0].xy);"
                    "if (l > depth.y) {"
                        "gl_FragColor = pixel;"
                    "} else if (l == depth.y && abs(gl_FragCoord.z) >= depth.z) {"
                        "gl_FragColor = pixel;"
                    "} else if (l == depth.y && color.a < pixel.a) {"
                        "gl_FragColor = pixel;"
                    "} else {"
                        "gl_FragColor = color;"
                    "}"
                "}";
    Dans ma classe RenderComponent, je ne fais que de passer la position z du composant à mon shader :

    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
     
     void FastRenderComponent::draw(RenderTarget& target, RenderStates states) const {
            for (unsigned int i = 0; i < shaders.size(); i++) {
                shaders[i]->setParameter("l", (int) const_cast<FastRenderComponent*>(this)->getPosition().z);
            }
            if (Shader::isAvailable()) {
                for (unsigned int i = 0; i < m_vertices.size(); i++) {
                    states.texture = const_cast<FastRenderComponent*>(this)->m_vertices[i].first.getMaterial().getTexture();
                    states.transform = getTransform();
                    for (unsigned int j = 0; j < m_vertices[i].second.size(); j++) {
                        for (unsigned int k = 0; k < m_vertices[i].second[j]->getVertexCount(); k++)
                            target.draw(*m_vertices[i].second[j], states);
                    }
                }
            } else {
                for (unsigned int i = 0; i < visibleEntities.size(); i++) {
                    for (unsigned int j = 0; j < visibleEntities[i]->getFaces().size(); j++) {
                        states.texture = visibleEntities[i]->getFaces()[0]->getMaterial().getTexture();
                        states.transform = visibleEntities[i]->getTransform();
                        target.draw(visibleEntities[i]->getFaces()[0]->getVertexArray(), states);
                    }
                }
            }
     
        }
    Si les shaders ne sont pas supporté j'utilise l'algorithme du peintre (mes entités sont triées par un gestionnaire d'entités avant d'être chargée sur mes composants) sinon, je passe mes shaders à mes composants et je regroupe tout mes tableaux de sommets par type de primitive et matériel et je dessine le tout avec mes 2 shaders)

    Cependant mon système de layer ne semble pas fonctionner, le depthtest et l'alpha test sont quand même effectués, même si la position en z du composant est plus grande que celle du pixel du composant qui est dessiné à l'écran.

    Et les pixels opaque du sol viennent toujours cacher ceux des autres entités si leur position y est plus grande.


    Peut être devrais je faire une framebuffertexture et une depthbuffertexture par composant et non pas une pour tout les composants ?

    Mais si il y'a une autre solution je suis preneur.

  5. #5
    Invité
    Invité(e)
    Par défaut
    Bon bah j'ai fait une depth texture et une frametexture par composant mais là, mon shader ne marche plus. (il me dessine toujours le personnage par dessus la maison quelque soit sa position en z sur le composant)

  6. #6
    Invité
    Invité(e)
    Par défaut
    J'ai trouvé!
    Maintenant je vais pouvoir faire des textures qui se croisent en Z. (Des vagues, etc...)
    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
    152
    153
    154
    155
    156
     
    #include "../../../../include/odfaeg/Graphics/2D/fastRenderComponent.h"
    namespace odfaeg {
    namespace g2d {
    FastRenderComponent::FastRenderComponent (RenderWindow& window, int layer) :
        Transformable(Vec3f(window.getView().getPosition().x, window.getView().getPosition().y, layer),
                      Vec3f(window.getView().getSize().x, window.getView().getSize().y, 0),
                      Vec3f(window.getView().getSize().x + window.getView().getSize().x * 0.5f, window.getView().getPosition().y + window.getView().getSize().y * 0.5f, layer)),
        view(window.getView()) {
        sf::Vector3i resolution ((int) window.getSize().x, (int) window.getSize().y, window.getView().getSize().z);
        depthBuffer = new RenderTexture();
        frameBuffer = new RenderTexture();
        depthBuffer->create(resolution.x, resolution.y);
        frameBuffer->create(resolution.x, resolution.y);
        frameBuffer->setView(window.getView());
        depthBuffer->setView(window.getView());
     
        if (Shader::isAvailable()) {
            frameBufferGenerator = new Shader();
            depthBufferGenerator = new Shader();
            const std::string vertexShader =
            "void main () {"
                "gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;"
                "gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;"
                "gl_FrontColor = gl_Color;"
            "}";
            const std::string  depthGenFragShader =
            "uniform sampler2D depthBuffer;"
            "uniform sampler2D texture;"
            "uniform vec3 resolution;"
            "void main () {"
                  "vec2 position = ( gl_FragCoord.xy / resolution.xy );"
                  "vec4 color = texture2D(depthBuffer, position);"
                  "vec4 pixel = texture2D(texture, gl_TexCoord[0].xy);"
                  "if (gl_FragCoord.z >= color.z && pixel.a >= color.a) {"
                     "gl_FragColor = vec4(0, 0,gl_FragCoord.z, pixel.a);"
                  "} else {"
                     "gl_FragColor = color;"
                  "}"
            "}";
            const std::string frameBufferGenFragShader =
            "uniform sampler2D depthBuffer;"
            "uniform sampler2D frameBuffer;"
            "uniform sampler2D texture;"
            "uniform vec3 resolution;"
            "void main () {	"
                "vec2 position = ( gl_FragCoord.xy / resolution.xy );"
                "vec4 depth = texture2D(depthBuffer, position);"
                "vec4 color = texture2D(frameBuffer, position);"
                "vec4 pixel = texture2D(texture, gl_TexCoord[0].xy);"
                "if (gl_FragCoord.z >= depth.z) {"
                    "gl_FragColor = pixel;"
                "} else if (color.a < pixel.a) {"
                    "gl_FragColor = pixel;"
                "} else {"
                    "gl_FragColor = color;"
                "}"
            "}";
            if (!depthBufferGenerator->loadFromMemory(vertexShader, depthGenFragShader))
                throw Erreur(50, "Failed to load depth buffer generator shader", 0);
            if (!frameBufferGenerator->loadFromMemory(vertexShader, frameBufferGenFragShader))
                throw Erreur(51, "Failed to load frame buffer generator shader", 0);
             depthBufferGenerator->setParameter("resolution",resolution.x, resolution.y, resolution.z);
             frameBufferGenerator->setParameter("resolution",resolution.x, resolution.y, resolution.z);
             backgroundColor = sf::Color::Transparent;
        }
    }
    void FastRenderComponent::setBackgroundColor(sf::Color color) {
        this->backgroundColor = color;
    }
    void FastRenderComponent::clearBufferBits() {
        frameBuffer->clear(backgroundColor);
    }
    void FastRenderComponent::clearDepthBits() {
        depthBuffer->clear(sf::Color::Transparent);
    }
    g2d::Tile FastRenderComponent::getFrameBufferTile () const {
        sf::IntRect subRect(0, 0, frameBuffer->getView().getSize().x, frameBuffer->getView().getSize().y);
        g2d::Tile tile (&frameBuffer->getTexture(), Vec2f(0, 0), Vec2f(frameBuffer->getView().getSize().x, frameBuffer->getView().getSize().y), subRect);
        return tile;
    }
    g2d::Tile FastRenderComponent::getDepthBufferTile() const {
        sf::IntRect subRect(0, 0, depthBuffer->getView().getSize().x, depthBuffer->getView().getSize().y);
        g2d::Tile tile (&depthBuffer->getTexture(), Vec2f(0, 0), Vec2f(depthBuffer->getView().getSize().x, depthBuffer->getView().getSize().y), subRect);
        return tile;
    }
    bool FastRenderComponent::load(std::vector<Entity*> visibleEntities)
    {
     
        if (Shader::isAvailable()) {
            fg.clear();
            for (unsigned int i = 0; i < visibleEntities.size(); i++) {
     
                if (visibleEntities[i]->isLeaf()) {
                    for (unsigned int j = 0; j < visibleEntities[i]->getFaces().size(); j++) {
     
                        visibleEntities[i]->getFaces()[j]->transform(visibleEntities[i]->getTransform());
     
                        fg.addFace(visibleEntities[i]->getFaces()[j]);
                    }
                }
            }
            m_vertices = fg.getFaces();
        }
        this->visibleEntities = visibleEntities;
    }
     
    void FastRenderComponent::draw(RenderTarget& target, RenderStates states) const {
        const Shader* devShader = states.shader;
        states.transform = getTransform();
        if (Shader::isAvailable()) {
            frameBuffer->setView(target.getView());
            depthBuffer->setView(target.getView());
            for (unsigned int i = 0; i < m_vertices.size(); i++) {
                states.texture = const_cast<FastRenderComponent*>(this)->m_vertices[i].first.getMaterial().getTexture();
                for (unsigned int j = 0; j < m_vertices[i].second.size(); j++) {
                    states.shader = frameBufferGenerator;
                    frameBufferGenerator->setParameter("depthBuffer", depthBuffer->getTexture());
                    frameBufferGenerator->setParameter("frameBuffer", frameBuffer->getTexture());
                    frameBufferGenerator->setParameter("texture", Shader::CurrentTexture);
                    frameBuffer->draw(*m_vertices[i].second[j], states);
                    frameBuffer->display();
                    depthBufferGenerator->setParameter("depthBuffer", depthBuffer->getTexture());
                    depthBufferGenerator->setParameter("texture", Shader::CurrentTexture);
                    states.shader = depthBufferGenerator;
                    depthBuffer->draw(*m_vertices[i].second[j], states);
                    depthBuffer->display();
                }
            }
            g2d::Tile tile = getFrameBufferTile();
            tile.setCenter(frameBuffer->getView().getPosition());
            states.shader = devShader;
            target.draw(tile, states);
        } else {
            for (unsigned int i = 0; i < visibleEntities.size(); i++) {
                for (unsigned int j = 0; j < visibleEntities[i]->getFaces().size(); j++) {
                    states.texture = visibleEntities[i]->getFaces()[j]->getMaterial().getTexture();
                    states.transform = visibleEntities[i]->getTransform();
                    target.draw(visibleEntities[i]->getFaces()[j]->getVertexArray(), states);
                }
            }
        }
    }
    void FastRenderComponent::init() {
    }
    FastRenderComponent::~FastRenderComponent() {
     
    }
    View& FastRenderComponent::getView() {
        return view;
    }
    int FastRenderComponent::getLayer() {
        return getPosition().z;
    }
    }
    }

    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
     
    #include "../../../include/odfaeg/Graphics/fastRenderComponentManager.h"
    #include "../../../include/odfaeg/Graphics/2D/fastRenderComponent.h"
    using namespace odfaeg::g2d;
    namespace odfaeg {
    FastRenderComponentManager::FastRenderComponentManager(RenderWindow& window, int nbComponents) : window (window) {
     
        components = std::vector<std::vector<g2d::FastRenderComponent*>>(nbComponents);
    }
    void FastRenderComponentManager::addRenderComponent(FastRenderComponent* component) {
        components[component->getPosition().z].push_back(component);
    }
    RenderWindow& FastRenderComponentManager::getWindow() {
        return window;
    }
    /*void FastRenderComponentManager::initComponents() {
        for (unsigned int i = 0; i < components.size(); i++) {
            components[i]->init();
        }
    }*/
     
    void FastRenderComponentManager::drawComponents() const {
        for (unsigned int l = 0; l < components.size(); l++) {
            for (unsigned int i = 0; i < components[l].size(); i++) {
                window.draw(*components[l][i]);
            }
        }
    }
    bool FastRenderComponentManager::isComponentCreated(int layer) {
       if (components[layer].size() == 0)
           return false;
       return true;
    }
    FastRenderComponent* FastRenderComponentManager::getRenderComponent(int layer) {
        return components[layer][0];
    }
    void FastRenderComponentManager::clearComponents() {
        for (unsigned int l = 0; l < components.size(); l++) {
            for (unsigned int i = 0; i < components[l].size(); i++) {
                components[l][i]->clearBufferBits();
                components[l][i]->clearDepthBits();
            }
        }
    }
    FastRenderComponentManager::~FastRenderComponentManager() {
        for (unsigned int l = 0; l < components.size(); l++) {
            for (unsigned int i = 0; i < components[l].size(); i++) {
                delete components[l][i];
            }
        }
    }
    }
    Par contre le rendu est assez long et ça saccade un peu, il va falloir que j'essaye d'optimiser tout ça.

Discussions similaires

  1. Comment gérer une scrollBar vertical, avec un bouton?
    Par wolverine1987 dans le forum MFC
    Réponses: 6
    Dernier message: 06/05/2009, 11h43
  2. Réponses: 8
    Dernier message: 27/02/2009, 01h37
  3. Rectangle semi-transparent avec DrawAlphaBlend
    Par Bouillou dans le forum Visual C++
    Réponses: 2
    Dernier message: 07/04/2008, 17h19
  4. Comment gérer des sous ensembles avec des "enum" ?
    Par ogattaz dans le forum Langage
    Réponses: 2
    Dernier message: 30/05/2007, 10h29
  5. Réponses: 3
    Dernier message: 16/12/2006, 12h59

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