Tudo sobre objetos OpenGL
O modelo padrão para objetos OpenGL é o seguinte.
Objetos têm estado. Pense neles como um struct. Portanto, você pode ter um objeto definido assim:
struct Object
{
int count;
float opacity;
char *name;
};
O objeto possui certos valores armazenados e possui estado . Objetos OpenGL também têm estado.
Mudando de estado
No C / C ++, se você tiver uma instância do tipo Object, altere seu estado da seguinte maneira: obj.count = 5;Você faria referência direta a uma instância do objeto, obteria a parte específica do estado que deseja alterar e colocaria um valor nela.
No OpenGL, você não faz isso.
Por motivos legados, é melhor deixar inexplicável, para alterar o estado de um objeto OpenGL, você deve primeiro vinculá- lo ao contexto. Isso é feito com alguns de glBind*chamada.
O equivalente em C / C ++ a isso é o seguinte:
Object *g_objs[MAX_LOCATIONS] = {NULL};
void BindObject(int loc, Object *obj)
{
g_objs[loc] = obj;
}
Texturas são interessantes; eles representam um caso especial de ligação. Muitas glBind*chamadas têm um parâmetro "target". Isso representa diferentes locais no contexto do OpenGL em que objetos desse tipo podem ser vinculados. Por exemplo, você pode vincular um objeto buffer de moldura para leitura ( GL_READ_FRAMEBUFFER) ou para gravação ( GL_DRAW_FRAMEBUFFER). Isso afeta como o OpenGL usa o buffer. É isso que o locparâmetro acima representa.
Texturas são especiais porque quando você primeiro ligá-los a um alvo, que recebem informações especiais. Quando você liga uma textura pela primeira vez GL_TEXTURE_2D, você está realmente definindo um estado especial na textura. Você está dizendo que essa textura é uma textura 2D. E sempre será uma textura 2D; esse estado não pode ser alterado nunca . Se você tem uma textura que foi primeiro vinculada como a GL_TEXTURE_2D, sempre deve vinculá-la como a GL_TEXTURE_2D; tentar vinculá-lo, pois GL_TEXTURE_1Dcausará um erro (durante o tempo de execução).
Depois que o objeto é vinculado, seu estado pode ser alterado. Isso é feito através de funções genéricas específicas para esse objeto. Eles também usam um local que representa qual objeto modificar.
Em C / C ++, isso se parece com:
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;
}
}
Observe como esta função define o que quer que esteja no locvalor atualmente vinculado .
Para objetos de textura, as principais funções de alteração do estado da textura são glTexParameter. As únicas outras funções que alteram o estado da textura são as glTexImagefunções e suas variações ( glCompressedTexImage, glCopyTexImagerecentes glTexStorage). As várias SubImageversões alteram o conteúdo da textura, mas tecnicamente não alteram seu estado . As Imagefunções alocam armazenamento de textura e definem o formato da textura; as SubImagefunções apenas copiam pixels ao redor. Esse não é considerado o estado da textura.
Permita-me repetir: estas são as únicas funções que modificam o estado da textura. glTexEnvmodifica o estado do ambiente; isso não afeta nada armazenado em objetos de textura.
Textura ativa
A situação das texturas é mais complexa, mais uma vez por motivos legados, é melhor deixar de lado. É aqui que glActiveTextureentra.
Para texturas, não são alvos apenas ( GL_TEXTURE_1D, GL_TEXTURE_CUBE_MAP, etc.). Existem também unidades de textura . Em termos de nosso exemplo de C / C ++, o que temos é o seguinte:
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;
}
Observe que agora não temos apenas uma lista 2D de Objects, mas também temos o conceito de um objeto atual. Temos uma função para definir o objeto atual, temos o conceito de um número máximo de objetos atuais e todas as nossas funções de manipulação de objetos são ajustadas para selecionar o objeto atual.
Quando você altera o objeto ativo no momento, altera todo o conjunto de locais de destino. Portanto, você pode vincular algo que entra no objeto atual 0, alterna para o objeto atual 4 e modifica um objeto completamente diferente.
Essa analogia com objetos de textura é perfeita ... quase.
Veja, glActiveTexturenão leva um número inteiro; é preciso um enumerador . O que, em teoria, significa que pode levar qualquer coisa de GL_TEXTURE0para GL_TEXTURE31. Mas há uma coisa que você deve entender:
ISTO É FALSO!
O intervalo real que glActiveTexturepode ser adotado é controlado por GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS. Esse é o número máximo de multi-estruturas simultâneas que uma implementação permite. Cada um deles é dividido em diferentes agrupamentos para diferentes estágios do shader. Por exemplo, no hardware da classe GL 3.x, você obtém 16 texturas de shader de vértice, 16 de shader de fragmento e 16 de shaver de geometria. Portanto, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITSserá 48.
Mas não há 48 enumeradores. É por isso glActiveTextureque realmente não recebe enumeradores. A maneira correta de ligar glActiveTextureé a seguinte:
glActiveTexture(GL_TEXTURE0 + i);
onde ié um número entre 0 e GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS.
Renderização
Então, o que tudo isso tem a ver com renderização?
Ao usar shaders, você define os uniformes do amostrador para uma unidade de imagem de textura ( glUniform1i(samplerLoc, i), onde ié a unidade de imagem). Isso representa o número com o qual você usou glActiveTexture. O amostrador selecionará o alvo com base no tipo de amostrador. Então, um sampler2Dvai escolher a partir do GL_TEXTURE_2Dalvo. Essa é uma das razões pelas quais os amostradores têm tipos diferentes.
Agora, parece suspeito que você pode ter dois amostradores GLSL, com tipos diferentes que usam a mesma unidade de imagem de textura. Mas você não pode; O OpenGL proíbe isso e gera um erro quando você tenta renderizar.
GL_TEXTURE0 + i- eu pretendia inspecionar os valores da enumeração para ver se isso era válido ou não. E o último parágrafo - não sabia se isso era legal ou não. Excelente! Estou marcando todas as suas respostas para que eu possa consultá-las novamente.