2017-07-06 7 views
1

Donc j'essaye de texturer un objet dans OpenGL et j'ai deux textures que je veux mixer dans le fragment shader (rock.tga et grass.tga). Mon fragment shader:Comment charger plusieurs textures dans le fragment shader

out vec3 color; 

in vec2 uv; 

uniform sampler2D grasstexture; 
uniform sampler2D rocktexture; 

Pour charger une texture sampler2D est ici ce que je l'ai fait dans mon dossier d'en-tête en C++:

OpenGP::EigenImage<vec3> image; 
OpenGP::imread("grass.tga", image); 

glGenTextures(0, &_tex); 
glBindTexture(GL_TEXTURE_2D, _tex); 

check_error_gl(); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
glTexParameteri(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); 
check_error_gl(); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, 
      image.cols(), image.rows(), 0, 
      GL_RGB, GL_FLOAT, image.data()); 
check_error_gl(); 
tex_id = glGetUniformLocation(_pid, "grasstexture"); 
glUniform1i(tex_id, 0); 

qui charge la texture de l'herbe dans mon fragment shader. Maintenant, ce que je veux savoir, c'est comment charger plusieurs textures. Je ne peux pas copier le code ci-dessus deux fois car une texture est toujours écrasée par l'autre. Alors, comment puis-je charger plusieurs textures dans le fragment shader?

EDIT: Voici où mon _tex est déclaré:

class Mesh{ 
    protected: 
     GLuint _tex; 

     GLuint _vpoint; ///< memory buffer 
     GLuint _vnormal; ///< memory buffer 

    public: 
     GLuint getProgramID(){ return _pid; } 

     void init(){ 
//code for the textures goes in here 

Voici mon code mis à jour:

OpenGP::EigenImage<vec3> image; 
glActiveTexture(GL_TEXTURE0); 
OpenGP::imread("grass.tga", image); 

//glGenTextures(1, &_tex); 
glBindTexture(GL_TEXTURE_2D, _tex); 

check_error_gl(); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
glTexParameteri(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); 
check_error_gl(); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, 
      image.cols(), image.rows(), 0, 
      GL_RGB, GL_FLOAT, image.data()); 
check_error_gl(); 
tex_id = glGetUniformLocation(_pid, "grasstexture"); 
glUniform1i(tex_id, 0); 

glActiveTexture(GL_TEXTURE1); 
OpenGP::imread("rock.tga", image); 

//glGenTextures(0, &_tex); 

glBindTexture(GL_TEXTURE_2D, _tex); 

check_error_gl(); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
glTexParameteri(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); 
check_error_gl(); 
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB32F, 
      image.cols(), image.rows(), 0, 
      GL_RGB, GL_FLOAT, image.data()); 
check_error_gl(); 
tex_id = glGetUniformLocation(_pid, "rocktexture"); 
glUniform1i(tex_id, 1); 

Répondre

3

Opengl cache beaucoup de son contexte afin que vous devez garder à l'esprit. Vous avez trois parties de la texture:

  • Texture nom - juste un nombre entier, le passer autour.
  • unité de texture active - chose contexte, ensemble avec GL_TEXTURE0 ...
  • Texture cible - pour commencer GL_TEXTURE_2D est tout ce dont vous avez besoin.

Voici ce que vous devez faire pour obtenir un travail de texture 2d:

  1. Créer opengl texture nom avec glGenTextures
  2. Mettre en place la texture avec suivant ensemble d'actions:

    2.1 Set unité de texture actif avec glActiveTexture

    2,2 Spécifier le cible de l'unité de texture actif à laquelle la texture nommé est lié glBindTexture. Pour cela, les trois parties de texture doivent être "sous contrôle".

    2.3 Spécifier une image de texture en deux dimensions de l'unité de texture actif avec glTexImage2D

    2.4 Régler les paramètres de l'unité de texture actif avec glTexParameteri

  3. Pour utiliser simultanément plusieurs textures assurez-vous qu'ils ont uniques nom et unité de texture:

    3.1 Définir la texture actif unité à 0

    3,2 Bind un nommé texture à la texture actif unité

    3.3 unité texture Pass (0) pour shader

    3.4 Régler l'unité de texture active 1

    3,5 Bind un autre nommé texture à la texture actif unité

    3.6 Passe texture unité (1) à ombrer

    ...

  4. Et quand vous avez terminé ne pas oublier de supprimer toutes les textures nommées avec glDeleteTextures

L'ordre des commandes est pas le seul possible et l'ensemble des commandes est pas minimale - c'est juste typique.


réponse originale:

Vous devez définir la texture suivante actif comme ceci:

glActiveTexture(GL_TEXTURE1); 

avant de lier lier la texture suivante. Il travaillera également comme:

std::vector<std::string> textures = {"grass.tga", "rock.tga"}; 
for(int i = 0; i < textures.size(); i++) { 
    glActiveTexture(GL_TEXTURE0 + i); 
    // create the texture 
} 
+0

Il ne fonctionne pas. Je mettrai à jour ma question avec mon code le plus à jour. Fondamentalement, ce qui se passe est que ma texture de roche apparaît comme extrêmement blanche. Je ne suis même pas sûr que ce soit la texture de la roche ou une version vraiment brillante de ma texture d'herbe. Savez-vous ce que je fais mal? J'ai également commenté mes lignes glGenTextures parce que, pour une raison quelconque, mes textures n'apparaissent pas du tout. –

+0

@SarahMacleod J'ai mis à jour la réponse – teivaz