129 votes

Les différences et les relations entre glActiveTexture et glBindTexture

De ce que je comprends, glActiveTexture jeux de l'actif "unité de texture". Chaque unité de texture peuvent avoir des textures multiples objectifs (généralement GL_TEXTURE_1D, 2D, 3D ou CUBE_MAP).

Si je comprends bien, vous appelez glActiveTexture pour définir l'unité de texture premier (initialisée à GL_TEXTURE0), et vous vous liez (un ou plusieurs) texture "cibles" pour que l'unité de texture?

Le nombre d'unités de texture disponible est dépendante du système. Je vois les énumérations pour jusqu'à 32 dans ma bibliothèque. Je suppose que cela signifie que je peux avoir le minimum de mon GPU est limite (je pense que c'est 16 8) et 32 de textures dans le GPU de la mémoire à un moment donné? Je pense qu'il y a une limite supplémentaire que je ne dépasse pas mon GPU mémoire maximale (soi-disant de 1 GO).

Suis-je la compréhension de la relation entre la texture des objectifs et de la texture des unités correctement? Disons que je suis autorisée à 16 unités et 4 cibles à chaque, cela signifie t il de la place pour 16*4=64 cibles, ou qu'il ne fonctionne pas comme ça?

Ensuite, vous souhaitez généralement de charger une texture. Vous pouvez le faire via glTexImage2D. Le premier argument de ce qui est une texture cible. Si cela fonctionne comme glBufferData, puis nous avons essentiellement lier la "poignée"/"nom de texture" de la texture de la cible, puis de charger les données de la texture dans la cible, et donc, indirectement, de l'associer avec cette poignée.

Qu'en glTexParameter? Nous avons pour lier une texture de la cible, puis de choisir la même cible que le premier argument? Ou la texture de la cible a pas besoin d'être liée aussi longtemps que nous avons la bonne active l'unité de texture?

glGenerateMipmap fonctionne sur une cible trop...que la cible doit toujours être lié à la texture nom pour qu'il réussisse?

Puis, quand nous voulons attirer notre objet avec une texture sur, ne nous ont à la fois choisir un actif de l'unité de texture, puis une texture cible? Ou devons-nous choisir une unité de texture, et alors nous pouvons saisir des données à partir de l'une des 4 objectifs associés à cette unité? C'est la partie qui est vraiment déroutant moi.

247voto

Nicol Bolas Points 133791

Tout À Propos De OpenGL Objets

Le modèle standard pour les objets OpenGL est comme suit.

Les objets de l'état. Pensez à eux comme une struct. Alors vous pourriez avoir un objet défini comme ceci:

struct Object
{
    int count;
    float opacity;
    char *name;
};

L'objet a un certain nombre de valeurs stockées dans celui-ci et il a de l'état. OpenGL objets de l'état est trop.

Changement D'État

En C/C++, si vous avez une instance de type Object, vous pouvez modifier son état comme suit: obj.count = 5; Vous directement référence à une instance de l'objet, obtenir le morceau particulier de l'état que vous souhaitez modifier, et de pousser une valeur en elle.

En OpenGL, vous n'avez pas à le faire.

Pour des raisons d'héritage mieux laisser planer le mystère, pour changer l'état d'un objet OpenGL, vous devez d'abord lier au contexte. C'est fait avec certains de de la glBind* appel.

Le C/C++ équivalent à ce qui est comme suit:

Object *g_objs[MAX_LOCATIONS] = {NULL};    
void BindObject(int loc, Object *obj)
{
  g_objs[loc] = obj;
}

Les Textures sont intéressantes; elles représentent un cas particulier de la liaison. Nombre glBind* des appels ont une "cible" de paramètre. Cela représente différents endroits dans le contexte OpenGL où les objets de ce type peut être lié. Par exemple, vous pouvez lier un objet framebuffer pour la lecture (GL_READ_FRAMEBUFFER) ou par écrit (GL_WRITE_FRAMEBUFFER). Cela affecte la façon dont OpenGL utilise le tampon. C'est ce que l' loc paramètre ci-dessus représente.

Les Textures sont spéciaux parce que quand vous d'abord se lier à une cible, ils obtiennent des informations spéciales. Lorsque vous liez une texture en GL_TEXTURE_2D, vous êtes réellement réglage spécial de l'etat dans la texture. Vous dites que cette texture est une texture 2D. Et il va toujours être une texture 2D; cet état ne peut pas être changé à jamais. Si vous avez une texture qui a d'abord été lié comme un GL_TEXTURE_2D, vous devez toujours le lier en tant que GL_TEXTURE_2D; en essayant de lier, comme GL_TEXTURE_1D donnera lieu à une erreur (alors qu'au moment de l'exécution).

Une fois que l'objet est lié, son état peut être modifié. Cela se fait via des fonctions génériques spécifiques à l'objet. Ils prennent un emplacement qui représente l'objet à modifier.

En C/C++, cela ressemble à:

void ObjectParameteri(int loc, ObjectParameters eParam, int value)
{
  if(g_objs[loc] == NULL)
    return;

  switch(eParam)
  {
    case OBJECT_COUNT:
      g_objs[loc]->count = value;
      break;
    case OBJECT_OPACITY:
      g_objs[loc]->opacity = (float)value;
      break;
    default:
      //INVALID_ENUM error
      break;
  }
}

Remarquez que cette fonction définit ce qui arrive à être lié, loc de la valeur.

Pour la texture des objets, le principal de la texture de l'état du changement des fonctions sont glTexParameter. Les seuls autres fonctions que le changement de la texture de l'état sont l' glTexImage fonctions et de leurs variations (glCompressedTexImage, glCopyTexImage, les récentes glTexStorage). Les différents SubImage versions de modifier le contenu de la texture, mais ils ne sont pas techniquement de changer son état. L' Image fonctions allouer de la texture de stockage et de définir la texture du format; l' SubImage fonctions de copie pixels qui l'entourent. Qui n'est pas considéré comme la texture de l'état.

Permettez-moi de répéter: ce sont les seules fonctions qui modifient la texture de l'état. glTexEnv modifie l'état de l'environnement; il n'affecte pas tout ce qui est stocké dans la texture des objets.

Active Texture

La situation pour les textures est plus complexe, encore une fois pour des raisons d'héritage laissé non divulgués. C'est là que glActiveTexture .

Pour les textures, il n'y a pas seulement des cibles (GL_TEXTURE_1D, GL_TEXTURE_CUBE_MAP, etc). Il y a aussi la texture des unités. En termes de notre C/C++ exemple, ce que nous avons, c'est ceci:

Object *g_objs[MAX_OBJECTS][MAX_LOCATIONS] = {NULL};
int g_currObject = 0;

void BindObject(int loc, Object *obj)
{
  g_objs[g_currObject][loc] = obj;
}

void ActiveObject(int currObject)
{
  g_currObject = currObject;
}

Remarquez que maintenant, nous avons non seulement une 2D liste d' Objects, mais nous avons également le concept d'un objet courant. Nous avons une fonction pour définir l'objet en cours, nous avons le concept d'un nombre maximum d'objets courants, et l'ensemble de notre objet les fonctions de manipulation sont ajustés pour sélectionner à partir de l'objet courant.

Lorsque vous modifiez l'objet actuellement actif, vous changer l'ensemble des emplacements cibles. De sorte que vous pouvez lier à quelque chose qui va dans le courant de l'objet 0, passez à l'objet courant 4, et sera la modification d'un de complètement différent de l'objet.

Cette analogie avec la texture des objets est parfait... ou presque.

Voir, glActiveTexture ne prend pas un entier, il faut un agent recenseur. Qui, en théorie, signifie qu'il peut prendre n'importe quoi GL_TEXTURE0 à GL_TEXTURE31. Mais il y a une chose que vous devez comprendre:

C'EST FAUX!

La portée réelle qu' glActiveTexture pouvez prendre est régie par GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS. Qui est le nombre maximum de simultanée multitextures qu'une mise en œuvre permet. Ce sont chacun divisés en différents groupes pour les différents shader étapes. Par exemple, sur GL 3.x matériel de classe, vous obtenez 16 vertex shader textures, 16 fragment shader textures, et 16 de la géométrie shader textures. Par conséquent, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS sera de 48.

Mais il n'y a pas 48 agents recenseurs. C'est pourquoi glActiveTexture n'a pas vraiment prendre des agents recenseurs. L' correct d'appeler glActiveTexture est comme suit:

glActiveTexture(GL_TEXTURE0 + i);

i est un nombre entre 0 et GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS.

Le rendu

Donc, est-ce que tout cela a à voir avec le rendu?

Lors de l'utilisation de shaders, vous définissez votre échantillonneur uniformes à une image de texture de l'unité (glUniform1i(samplerLoc, i)i est l'image de l'unité). Que représente le nombre que vous avez utilisé avec de l' glActiveTexture. L'échantillonneur de sélection de la cible en fonction de l'échantillonneur de type. Ainsi, un sampler2D va chercher de l' GL_TEXTURE_2D de la cible. C'est une des raisons pourquoi les échantillonneurs ont des types différents.

Maintenant, cela ressemble étrangement vous pouvez avoir deux GLSL échantillonneurs, avec différents types qui utilisent la même image de texture à l'unité. Mais vous ne pouvez pas; OpenGL interdit cela et vous donnera une erreur lorsque vous tentez de vous rendre.

18voto

rotoglup Points 3662

Je vais faire un essai ! Tout cela n'est pas très compliqué, juste une question de termes, j'espère me faire comprendre.


Vous pouvez créer à peu près autant de la Texture des Objets car il est disponible de la mémoire de votre système. Ces objets contiennent des données réelles (texels) de vos textures, avec les paramètres fournis par glTexParameter (voir FAQ).

Lorsqu'en cours de création, vous devez assigner une Texture Cible à une texture de l'objet, qui représente le type de la texture (GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE, ...).

Ces deux éléments, la texture de l'objet et de la texture de la cible de représenter les données de la texture. Nous y reviendrons plus tard.

La Texture unités

Maintenant, OpenGL fournit un tableau de texture unités, qui peuvent être utilisés simultanément pendant le dessin. La taille de la matrice dépend de l'OpenGL système, la vôtre en a 8.

Vous pouvez lier un objet texture à une unité de texture à utiliser la texture donnée pendant le dessin.

Dans un simple et facile du monde, de dessiner avec une texture donnée, vous souhaitez lier un objet texture de l'unité de texture, et que vous souhaitez faire (pseudo-code):

glTextureUnit[0] = textureObject

En tant que GL est un état de la machine, elle, hélas, ne fonctionne pas de cette façon. En supposant que notre textureObject a données pour l' GL_TEXTURE_2D de la texture de la cible, nous allons exprimer la précédente affectation :

glActiveTexture(GL_TEXTURE_0);                   // select slot 0 of the texture units array
glBindTexture(GL_TEXTURE_2D, textureObject);     // do the binding

Notez que GL_TEXTURE_2D dépend vraiment du type de la texture que vous voulez lier.

La Texture des objets

En pseudo-code, pour définir la texture de données ou les paramètres de la texture, vous feriez par exemple :

setTexData(textureObject, ...)
setTexParameter(textureObject, TEXTURE_MIN_FILTER, LINEAR)

OpenGL ne peut pas manipuler directement la texture des objets, de mettre à jour/ensemble de leur contenu, ou de modifier leurs paramètres, vous devez d'abord lier à l'actif de l'unité de texture (quel qu'il soit). L'équivalent de code devient :

glBindTexture(GL_TEXTURE_2D, textureObject)       // this 'installs' textureObject in texture unit
glTexImage2D(GL_TEXTURE_2D, ...)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)

Les Shaders

Les Shaders ont accès à toutes les unités de texture, ils ne se soucient pas de l'actif de la texture.

Sampler des uniformes int des valeurs représentant l'index de l'unité de texture à utiliser pour l'échantillonneur (et pas la texture de l'objet à utiliser).

Donc, vous devez lier votre texture des objets pour les unités que vous souhaitez utiliser.

Le type de l'échantillonneur faire la correspondance avec la texture de la cible qui est utilisé dans l'unité de texture : Sampler2D pour GL_TEXTURE_2D, et ainsi de suite...

12voto

datenwolf Points 85093

Imaginez le GPU comme la peinture de l'usine de traitement.

Il y a un certain nombre de chars, qui offre un colorant à la peinture de la machine. Dans la peinture de la machine, le colorant est ensuite appliqué à l'objet. Ces réservoirs sont les unités de texture

Ces réservoirs peuvent être équipés de différents types de colorant. Chaque type de colorant nécessite un autre type de solvant. Le "solvant" est la texture de la cible. Pour des raisons de commodité chaque réservoir est connecté à certains solvants d'approvisionnement, et les mais un seul type de solvant peut être utilisé à la fois dans chaque réservoir. Donc, il y a une valve/commutateur "TEXTURE_CUBE_MAP", "TEXTURE_3D", "TEXTURE_2D", "TEXTURE_1D". Vous pouvez remplir tous les types de colorant dans le réservoir en même temps, mais depuis, un seul type de solvant va en, elle va "diluer" que le type de colorant de correspondance. Ainsi, vous pouvez avoir chaque type de texture être lié, mais la liaison avec le "plus important" solvant seront effectivement aller dans le réservoir et mélanger avec le type de colorant à laquelle il appartient.

Et puis il y a le colorant lui-même, qui vient d'un entrepôt et est remplie dans le réservoir par "liaison". C'est la texture de vos cheveux.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X