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' Object
s, 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);
où 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)
où 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.