Précédent   Forum des professionnels en informatique > Applications > Développement 2D, 3D et Jeux > API graphiques > OpenGL
OpenGL Forum d'entraide sur le développement en OpenGL. Avant de poster -> FAQ OpenGL
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 30/12/2011, 23h40   #1
Invité régulier
 
Inscription : juin 2004
Messages : 53
Détails du profil
Informations personnelles :
Âge : 25

Informations forums :
Inscription : juin 2004
Messages : 53
Points : 5
Points : 5
Envoyer un message via MSN à orochimaru
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 :
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 :
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.
orochimaru est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/12/2011, 14h26   #2
Membre habitué
 
Homme
Étudiant
Inscription : juin 2009
Messages : 155
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 21

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : juin 2009
Messages : 155
Points : 102
Points : 102
Bonjours

Citation:
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 :
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 :
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 :
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 :
texture(tex_id, texCoord - floor(texCoord))
ou un :
Code :
texture(tex_id,clamp(vec2(0.0), vec2(1.0), texCoord))
Citation:
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 :
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 :
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.
LastSpear est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 04/01/2012, 20h36   #3
Invité régulier
 
Inscription : juin 2004
Messages : 53
Détails du profil
Informations personnelles :
Âge : 25

Informations forums :
Inscription : juin 2004
Messages : 53
Points : 5
Points : 5
Envoyer un message via MSN à orochimaru
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 :
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 :
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
orochimaru est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/01/2012, 20h53   #4
Responsable 2D/3D/Jeux

 
Avatar de LittleWhite
 
Homme Alexandre Laurent
Étudiant
Inscription : mai 2008
Messages : 6 560
Détails du profil
Informations personnelles :
Nom : Homme Alexandre Laurent
Localisation : France

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : mai 2008
Messages : 6 560
Points : 14 054
Points : 14 054
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.
__________________
Vous souhaitez participer à la section Jeux ? Contactez-moi
La rubrique a aussi un blog !

Ma page sur DVP
Mon Portfolio

Qui connaît l'erreur, connaît la solution.
LittleWhite est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/01/2012, 21h45   #5
Invité régulier
 
Inscription : juin 2004
Messages : 53
Détails du profil
Informations personnelles :
Âge : 25

Informations forums :
Inscription : juin 2004
Messages : 53
Points : 5
Points : 5
Envoyer un message via MSN à orochimaru
En effet, pas de pipeline fixe, que du shader.
D'ailleurs, le voici :
Code :
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 :
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 :
1
2
3
4
m_id_tex[1] = 1
m_id_tex[2] = 2
m_id_tex[3] = 3
m_id_tex[4] = 4
orochimaru est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/01/2012, 22h11   #6
Membre habitué
 
Homme
Étudiant
Inscription : juin 2009
Messages : 155
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 21

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : juin 2009
Messages : 155
Points : 102
Points : 102
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 :
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 :
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.
LastSpear est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 05/01/2012, 00h44   #7
Invité régulier
 
Inscription : juin 2004
Messages : 53
Détails du profil
Informations personnelles :
Âge : 25

Informations forums :
Inscription : juin 2004
Messages : 53
Points : 5
Points : 5
Envoyer un message via MSN à orochimaru
Citation:
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 :
Citation:
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 :
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 .
orochimaru est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/01/2012, 18h22   #8
Membre habitué
 
Homme
Étudiant
Inscription : juin 2009
Messages : 155
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 21

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : juin 2009
Messages : 155
Points : 102
Points : 102
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 :
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é.
LastSpear est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 08h41.


 
 
 
 
Partenaires

Hébergement Web