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

OpenGL Discussion :

Texture via shaders


Sujet :

OpenGL

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2004
    Messages
    66
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2004
    Messages : 66
    Points : 37
    Points
    37
    Par défaut Texture via shaders
    Bonjour,

    je suis en train d'apprendre à utiliser openGL 3 et je bloque sur l'utilisation de textures.
    J'ai chargé ma texture en mémoire de la carte graphique (je sais qu'elle est bien chargée car je peux la voir avec gDEBugger), ensuite j'envoie l'identifiant de cette texture à mon shader que voici (juste le fragment, le vertex n'est je pense, pas utile) :
    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
    #version 140
     
    // float en haute précision
    precision highp float;
     
    // Uniform
    uniform sampler2D tex;
     
    // Entrées
    smooth in vec3 InterpolatedColor;
    smooth in vec2 texCoord;
     
    // Sortie du fragment shader, ira dans le framebuffer principal
    out vec4 Color;
     
    void main()
    {
        Color = texture(tex, texCoord) + 0.5*vec4(InterpolatedColor, 1.0);
    }
    Seulement il n'y a que la partie "0.5*vec4(InterpolatedColor, 1.0)" qui fonctionne.

    j'ai testé énormément de choses mais voici le code actuel permettant d'envoyer la texture :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    glUseProgram(m_shaderProgram);
    ...
    /* Envoi de la texture au fragment shader */
    glBindTexture(GL_TEXTURE_2D, m_id_tex);
    glUniform1i(m_uniform_texture, 0);
     
    glDrawElements(...);
    Voila si vous avec des pistes, ou un lien, je suis preneur.

    Sinon deux petites questions dans le même sujet:
    1) Les coordonnées pour la fonction texture() dans le shader doivent etre entre 0 et 1 ou entre 0 et width/height ?
    2) D’après gDEBugger, glBindTexture semble déprécié, hors je ne trouve rien à ce sujet, est-ce vraiment le cas et si oui que faut il utiliser à le place ?

    Merci d'avance.

  2. #2
    Membre actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2009
    Messages
    219
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 219
    Points : 239
    Points
    239
    Par défaut
    Bonjours

    1) Les coordonnées pour la fonction texture() dans le shader doivent etre entre 0 et 1 ou entre 0 et width/height ?
    Cela ne dépend que de toi en vérité. les caractéristique de la fonction texture est que lorsque la composante en x (respectivement en y) de la coordonné de texture parcoure l'intervalle [0,1], çà va en faite parcourir l'ensemble de ta texture selon l'horizontale (respectivement la vertical). Donc si tu a une texture de taille (width, height), lorsque tu va faire un :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    texture(tex, vec2(0.2,0.5))
    tu va aller chercher le pixel en coordonné (0.2*width, O.5*height) de ta texture
    Ainsi çà à le bon gou d'être indépendant de la résolution de ta texture et donc très pratique pour faire du LOD (Level Of Detail). Mais note qu'il existe aussi des fonctions glsl pour accédé directement au pixel que tu désire. (très utile pour des shaders de post-production) Ensuite, en fonction de tes besoin, tu peut configuré le sampler associé de manière différente, Genre si tu souhaite que ta composante doit subir un clamp :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    vec4 texture(sampler2D tex_id, vec2 uv)
    {
    uv = clamp(vec2(0.0), vec2(1.0), uv) ;
     
    [.....]
    }
     
    //Ainsi, texture(tex_id, vec2(1.2,2.3)) renverra la même couleur que texture(tex_id, vec2(1.0,1.0))
    ou un module 1
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    vec4 texture (sampler2D tex_id, vec2 uv)
    {
    uv -= floor (uv);
    // donc ta texture va être appliqué comme une mosaïque ....
    [.....]
    }
     
    //Ainsi, texture(tex_id, vec2(1.2,2.3)) renverra la même couleur que texture(tex_id, vec2(0.2,0.3))
    Mais ce choix se fait de coté API, ainsi tu peu configuré le comportement de ton sampler sans a être obligé de recompilé un nouveau shader. Il est donc inutile de faire un :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    texture(tex_id, texCoord - floor(texCoord))
    ou un :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    texture(tex_id,clamp(vec2(0.0), vec2(1.0), texCoord))
    2) D’après gDEBugger, glBindTexture semble déprécié, hors je ne trouve rien à ce sujet, est-ce vraiment le cas et si oui que faut il utiliser à le place ?
    Attention, il y a des différences notables sur la façon d'initialisé les textures. Si tu à crée un context OpenGL en mode core, tu doit respecté l'initialisation d'une texture (mais aussi de certain autres éléments) au mot près. Mais aussi, en compatibility mode, il faut éviter de faire des codes de version trop hétérogène. En d'autre thermes lorsque tu veux évolué ton code vers un OpenGL plus moderne, il faut assez souvent tout relire pour apporté certaine modification nécessaire au bon fonctionnement. Dans ce genre de cas, il est même préférable de réécrire les codes OpenGL avec la documentation à coté.

    Pour se qui est de ton shader, à tu vérifié dans un premier temps le rendu avec un shader du type :
    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
     
    #version 140
     
    // float en haute précision
    precision highp float;
     
    // Uniform
    uniform sampler2D tex;
     
    // Entrées
    smooth in vec3 InterpolatedColor;
    smooth in vec2 texCoord;
     
    // Sortie du fragment shader, ira dans le framebuffer principal
    out vec4 Color;
     
    void main()
    {
        Color = vec4 (texCoord, 0.0, 1.0); // dabord pour vérifié si les coordonné de texture fonctionnent
        Color = texture(tex, texCoord); // puis voir si le sampler est correctement configuré et ta texture prète à l'emploi
    }
    Aussi, à tu pensé à faire un entre l'étape de "link" de ton m_shaderProgram et son utilisation pour le rendu ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    glBindFragDataLocation (m_shaderProgram, 0, "Color");
    Cette ligne est très importantes sinon ton shaker n'écrira pas la couleur dans ton frambuffer.

    Quelque lien utiles :
    Official OpenGL SDK 3.2
    OpenGL 3.2 Quick Reference Card

    Bonne fêtes.

  3. #3
    Nouveau membre du Club
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2004
    Messages
    66
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2004
    Messages : 66
    Points : 37
    Points
    37
    Par défaut
    Merci pour ces éclaircissements, j'ai réussi à afficher ma texture

    Néanmoins, je veux maintenant passer au multitexturing et encore une fois, je ne comprend pas pourquoi cela ne fonctionne pas. J'ai chargé toutes mes textures sur le GPU (4 au total) seulement c'est uniquement la première qui est toujours active, peut importe laquelle j'essaye d'afficher.
    Voici mon code :
    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
    void Terrain::loadTextures()
    {
        sf::Image textures[4];
        std::string srcTextures[4] =
        {
            m_srcHeightmap,
            "textures/sand.jpg",
            "textures/grass.jpg",
            "textures/rock.jpg"
        };
     
        glGenTextures(4, m_id_tex);
        for(uint i=0; i<4; i++)
        {
            if( textures[i].LoadFromFile(srcTextures[i]) == false )
            {
                std::cout << "Terrain : Erreur lors du chargement de la texture " << srcTextures[i] << "." << std::endl;
                std::exit(1);
            }
     
            glBindTexture(GL_TEXTURE_2D, m_id_tex[i]);
                /* Génération de la mipmap */
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
                gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, textures[i].GetWidth(), textures[i].GetHeight(), GL_RGBA, GL_UNSIGNED_BYTE, textures[i].GetPixelsPtr());
        }
    }
    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
     
            glUseProgram(m_shaderProgram);
     
            glActiveTexture(GL_TEXTURE0);
                glBindTexture(GL_TEXTURE_2D, m_id_tex[0]);
                glUniform1i(m_uniform_heightmap, 0);
     
            glActiveTexture(GL_TEXTURE1);
                glBindTexture(GL_TEXTURE_2D, m_id_tex[1]);
                glUniform1i(m_uniform_sand, 1);
     
            glActiveTexture(GL_TEXTURE2);
                glBindTexture(GL_TEXTURE_2D, m_id_tex[2]);
                glUniform1i(m_uniform_grass, 2);
     
            glActiveTexture(GL_TEXTURE3);
                glBindTexture(GL_TEXTURE_2D, m_id_tex[3]);
                glUniform1i(m_uniform_rock, 3);
     
            /* Envoi des données au shader + affichage de la géométrie */
    C'est à devenir fou :o

  4. #4
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 966
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 966
    Points : 221 450
    Points
    221 450
    Billets dans le blog
    130
    Par défaut
    Je ne vois pas le problème dans le code. Serait-ce à cause du shader ?
    Sinon, si vous utilisez le pipeline fixe (je doute, vu la conversation), il manque des glEnable(GL_TEXTURE_2D); lors de l'activation de chaque texture.

    Un autre problème peut venir du faire que vous fassiez un unbind de la texture ?
    Finalement, pour être sur que tout le code est bon, j'afficherai bien les IDs des textures et des uniforms, pour voir si on moins, ils sont bien tous différents.

  5. #5
    Nouveau membre du Club
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2004
    Messages
    66
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2004
    Messages : 66
    Points : 37
    Points
    37
    Par défaut
    En effet, pas de pipeline fixe, que du shader.
    D'ailleurs, le voici :
    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
    #version 140
     
    // Attributs
    in vec3 VertexPosition;
    in vec2 VertexTexCoord;
     
    // Uniform
    uniform mat4 projection;
    uniform mat4 modelview;
     
    // gl_Position déclaré invariant
    invariant gl_Position;
     
    smooth out vec2 texCoord;
     
    void main ()
    {
        texCoord = VertexTexCoord;
     
        gl_Position = projection * modelview * vec4(VertexPosition, 1.0);
    }
    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
    #version 140
     
    // float en haute précision
    precision highp float;
     
    uniform sampler2D heightmap; // HeightMap
    uniform sampler2D sand;      // ground0
    uniform sampler2D grass;     // ground1
    uniform sampler2D rock;     // ground1
     
    smooth in vec2 texCoord;
     
    // Sortie du fragment shader, ira dans le framebuffer principal
    out vec4 Color;
     
    void main()
    {
        Color = texture(sand, texCoord);
    }
    et voici les id des textures :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    m_id_tex[1] = 1
    m_id_tex[2] = 2
    m_id_tex[3] = 3
    m_id_tex[4] = 4

  6. #6
    Membre actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2009
    Messages
    219
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 219
    Points : 239
    Points
    239
    Par défaut
    C'est tout a fait curieux ... Il doit y avoir un problème avec des lignes non affichées ici. Vérifie bien si les valeur m_uniform_heightmap ainsi que ses congénères m_uniform ont une valeur cohérente.

    Aussi je te conseille de placer des lignes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    if ( glGetError() != GL_NO_ERROR )
    printf ("[%s:%i] opengl survenu", __FILE__, __LINE__);
    entre tes lignes de rendu pour tester s'il n'y a pas eu d'erreur. En théorie il doit en y avoir 0 dans un moteur 3D, sinon il se passe des "undefine behavior" (je site la documentation OpenGL) soit des comportements inattendus ... comme ici. A mon avis il y a des erreurs OpenGL. donc places-en, et si tu en trouves, tu résous chacune de tes erreurs. glGetError() te permet de savoir si il y a des erreurs OpenGL qui sont survenues depuis son dernier appel (ou création du contexte si tu l'as jamais appelé)

    A mon avis, les erreurs viennent des lignes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    glUniform1i(m_uniform_heightmap, 0);
    glUniform1i(m_uniform_grass, 2);
    glUniform1i(m_uniform_rock, 3);
    car les sampler heightmap, grass et rock n'existe pas étant donné qu'il sont pas utilisé dans le shader (le compilo GLSL détecte les variables inutilisées et les virent automatiquement) donc les glGetUniformLocation de ses sampler doivent surement retourner -1 pour m_uniform_heightmap, m_uniform_grass et m_uniform_rock, et donc glUniform1i fait une erreur étant donner que l'uniform -1 n'existe pas.

  7. #7
    Nouveau membre du Club
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2004
    Messages
    66
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2004
    Messages : 66
    Points : 37
    Points
    37
    Par défaut
    A mon avis, les erreurs viennent des lignes :
    Dans le mil !

    Du coup j'ai fait un nouveau shader qui utilise tous les samplers et du coup mes glGetUniformLocation ne retournent plus -1.

    Mais, ca ne fonctionne toujours pas, déjà j'ai testé de recupérer les erreures d'openGL comme tu me l'a conséillé, et justement la première erreur apparait au glUniform1i(m_uniform_heightmap, 0);
    je ne vois pas ce que cette ligne à de mal, m_uniform_heightmap est bien défini et vaut 1 (le sampler est bien utilisé dans le shader).


    [edit] Trouvé !
    il est indiqué ici :
    Notice how glUniform1i doesn't take ProgramObject as a parameter, unlike glGetUniformLocation. This means, you must bind the shader before calling glUniform1i. Binding is done with glUseProgram.
    The other thing to keep in mind is that the uniforms belong to the shader. This means that if you bind another shader, then bind this shader, you don't need to call glUniform1i to set things up again. The values are remembered.
    J'ai donc mis dans le constructeur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        glUseProgram(m_shaderProgram);
            glUniform1i(m_uniform_heightmap, 0);
            glUniform1i(m_uniform_sand, 1);
            glUniform1i(m_uniform_grass, 2);
            glUniform1i(m_uniform_rock, 3);
    et ai retiré les glUniform1i de ma methode de dessin, et ça fonctionne nickel avec en prime un petit gain de performances du fait qu'il n'y a plus de glUniform1i dans ma boucle de rendu

    Merci a vous .

  8. #8
    Membre actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2009
    Messages
    219
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 219
    Points : 239
    Points
    239
    Par défaut
    Oui c'est sur que ça fonctionne pas sans le glUseProgram(m_shaderProgram), mais comme tu l'avais mis bien comme il faut tend ton code de rendu ... (c'est pour ma défense )
    Le fait que tu bind à chaque foi les samplers dans ta boucle de rendu m'étonnait déjà, mais çà ne change pas fondamentalement les choses (sauf si ta config est vraiment vielle)

    Note que si t'as pas envi de faire du "bind to modify", il est mis à ta disposition l'extension GL_EXT_direct_state_access (qui est souvent présent sur les cartes graphiques), qui te permet, entre autres, de modifier un uniform d'un program sans le bind par la fonction glProgramUniform. Elle sont également disponible dans le core profil depuis OpenGL 4.1 ou 4.2 (j'ai un doute entre les deux )

    Exemple :

    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
     
    glUseProgram (m_shaderProgram);
    glUniform1i (m_uniform_heightmap, 0);
     
    // DEVIEN SIMPLEMENT
    glProgramUniform1iEXT (m_shaderProgram, m_uniform_heightmap, 0);
     
     
    // DONC
    glUseProgram (m_shaderProgram);
    glUniform1i (m_uniform_heightmap, 0);
    glUniform1i (m_uniform_sand, 1);
     
    // DEVIEN
    glProgramUniform1iEXT (m_shaderProgram, m_uniform_heightmap, 0);
    glProgramUniform1iEXT (m_shaderProgram, m_uniform_sand, 1);
    lien pour les specs de cette extension.

    Aussi un petit conseil, une foit que ton shader est prêt, ou tout initialisé correctement, il n'est pas nécessaire de gardé les variables m_uniform_heightmap et ses collègues en global si tu ne les modifiera plus jamais. Donc declare les juste dans ta fonction qui initialise le shader. Parce qu'avec OpenGL 3 et supérieur, t'a vite tout plein de shaders de partout, alors faut commencé vite à faire le tris. Hésite pas aussi à te faire des structures ou des class pour contenir tes location d'uniform.

    Ravis de t'avoir aidé.

Discussions similaires

  1. Problème de texture avec shaders
    Par killerjeff dans le forum OpenGL
    Réponses: 1
    Dernier message: 07/06/2010, 16h23
  2. Matrice orthogonale pour OpenGL 3.2 via shader
    Par iliak dans le forum OpenGL
    Réponses: 3
    Dernier message: 31/03/2010, 21h12
  3. Réponses: 1
    Dernier message: 11/03/2009, 19h22
  4. Passer plusieurs textures à un shader : PROBLEME
    Par Bakura dans le forum OpenGL
    Réponses: 6
    Dernier message: 06/05/2008, 22h54
  5. Texture float / shaders
    Par Codeur masqué dans le forum OpenGL
    Réponses: 0
    Dernier message: 14/09/2007, 13h04

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