Você está na página 1de 16

Universidade Federal de Santa Maria Departamento de Eletrnica e Computao Prof.

Cesar Tadeu Pozzer Disciplina: Computao Grfica Avanada pozzer@inf.ufsm.br 09/2009

OpenGL Conceitos Avanados


Neste mdulo sero vistos conceitos mais avanados da programao em OpenGL, que tratam: Otimizaes: Vertex Array, Display List e otimizaes de pipeline; Realismo: Iluminao, material e textura; Pipeline OpenGL

1. Arquitetura Cliente-Servidor
O OpenGL trabalha com a filosofia cliente-servidor. Isso significa que se pode trabalhar em um computador (cliente) e ver os resultados em outro (servidor). O cliente responsvel pela gerao dos comandos OpenGL enquanto que o servidor responsvel pelo processamento (render) destes dados e exibio na tela. Caso no existirem computadores em rede, o mesmo computador exerce o papel de cliente e servidor (maior parte dos casos). Esse conceito importante para melhor compreenso de conceitos avanados do OpenGL. Veja os comandos glFlush() e glFinish() para uso em uma aplicao distribuda que faa uso de cliente e servidor em mquinas diferentes conectadas por uma rede.
Client server

2. Vertex Array
Usado para: Reduzir o nmero de chamada de funes, que podem causar reduo de desempenho da aplicao o Desenhar um polgono com 20 lados requer 22 chamadas de funes: uma para cada vrtice + glBegin() + glEnd(). Passando-se as normais, pode-se duplicar o nmero de chamadas. Evitar a replicao de vrtices, resultando em economia de memria. o Para se especificar um cubo, gasta-se 24 vrtices, sendo cada vrtice replicado 3x. O mesmo cubo poderia ser desenhado com apenas 8 vrtices. Com o uso de vertex array (OpenGL 1.1), os 20 vrtices do polgono poderiam ser colocados em um vetor e passados em uma nica chamada para o OpenGL. O mesmo poderia ocorrer com os vetores normais. Em relao ao nmero de vrtices, pode-se facilmente definir vrtices compartilhados por vrias faces. Passos para se utilizar vertex array: Ativar o vetor de dados que se deseja utilizar. Os mais comuns so de vrtices, normais e textura; Colocar os dados nos arrays. Estes dados, no modelo cliente-servidor, so armazenados no cliente; Desenhar o objeto com os dados dos arrays. Neste momento, os dados so transferidos para o servidor. Para ativar os buffers de dados, deve-se utilizar o comando glEnableClientState(), que recebe como parmetro constantes associadas a cada vetor: GL_VERTEX_ARRAY,

GL_COLOR_ARRAY, GL_INDEX_ARRAY, GL_NORMAL_ARRAY, GL_TEXTURE_COORD_ARRAY, e GL_EDGE_FLAG_ARRAY


void glEnableClientState(GLenum array); void glDisableClientState(GLenum array);

glEnableClientState (GL_COLOR_ARRAY); glEnableClientState (GL_VERTEX_ARRAY); Para a definio dos dados, existem comandos especficos para cada um dos 6 tipos de dado. O comando glVertexPointer() usado para indicar o vetor de vrtices. O comando glNormalPointer() para especificao de normais.
void glVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); void glNormalPointer(GLenum type, GLsizei stride, const GLvoid *pointer); void glTextCoordPointer(GLenum type, GLsizei stride, const GLvoid *pointer); void glColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);

No comando glVertexPointer(): pointer especifica onde os dados das coordenadas podem ser acessados. type especifica o tipo de dados: GL_SHORT, GL_INT, GL_FLOAT, ou GL_DOUBLE de cada coordenada do array. size o nmero de coordenadas por vrtice (2, 3, ou 4). No necessria para especificao de normais (sempre 3). Para cor pode ser 3 ou 4. stride o offset em bytes entre vrtices consecutivos. Deve ser 0 se no existir espao vago entre dois vrtices. Para enviar os dados para o processamento (enviar para o servidor na arquitetura cliente-servidor do OpenGL), existem vrios comandos.
void glDrawElements(GLenum mode, GLsizei count, GLenum type, void *indices);

O comando glDrawElements() define uma seqncia de primitivas geomtricas onde os parmetros so: count: o mero de elementos do vetor indices: Vetor de ndices dos elementos type: Indica o tipo de dados do array indices. Deve ser GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT ou GL_UNSIGNED_INT. mode: indica o tipo de primitivas a serem geradas, como GL_POLYGON, GL_LINE_LOOP, GL_LINES, GL_POINTS, etc.

Exemplo de uso:
GLint allVertex[] = { 0,0,0, 0,0,1, 1,0,0, 1,0,1, 1,1,0, 1,1,1, 0,1,0, 0,1,1};

//GLint allNormals[8] = {Nesta configurao, define-se uma normal por vrtice}; GLfloat allColors[] = { 1,0,0, 0,0,1, GLubyte allIndices[] = {4, 1, 0, 0, 0, 2, 5, 2, 1, 3, 4, 3, 6, 6, 5, 2, 7, 7, 0,1,0, 1,1,1, 7, 5, 4, 1, 3, 6}; 1,1,1, 0,1,1, 1,0,1, 0,0,0};

3 7 0 6

2 1

glEnableClientState (GL_VERTEX_ARRAY); 4 5 glEnableClientState (GL_COLOR_ARRAY); glVertexPointer(3, GL_INT, 0, allVertex); glColorPointer( 3, GL_FLOAT, 0, allColors); //glNormalPointer(GL_FLOAT, 0, allNormals); glDrawElements(GL_QUADS, 6*4, GL_UNSIGNED_BYTE, allIndices); Face 0 Face 1 Face N

5 6

V0 V1 V2 V3 V4 V5 V6 V7

C 0 C1 C2 C3 C4

C5 C6 C7

Para a especificao de um nico vrtice por vez de um vertex array pode-se utilizar o comando glArrayElement(GLint). O seguinte trecho de cdigo tem o mesmo efeito que o comando glDrawElements() apresentado anteriormente.
glBegin (GL_QUADS); for (i = 0; i < 24; i++) glArrayElement(allIndices[i]); glEnd();

Observaes: Existe um mapeamento direto de 1 para 1 entre o vetor de vrtices com os vetores de normais, cores, etc. O vetor de ndices GLubyte pois como existem apenas 24 = 6*4 ndices, usar um tipo maior como GLuint seria um desperdcio de memria. Se um vrtice compartilhado tiver normais diferentes em cada face, deve-se replicar os vrtices e as normais (o mesmo vale para as cores). Neste caso, perde-se a otimizao de memria mas continuase ganhando com a reduo de chamadas em relao a definio do objeto utilizando-se os comandos convencionais como glVertex*() e glNormal*(). Para o caso do cubo, seriam necessrios 24 vrtices (4 por face x 6 faces), 24 normais e 24 cores. [http://www.songho.ca/opengl/gl_vertexarray.html] Este recurso do GL, quando usado com normais, melhor aplicado em superfcies planares, como terrenos. Para objetos volumtricos fechados como cubos, no faz sentido ter-se normais compartilhadas entre as 3 faces adjacentes, o que exige a replicao de vrtices. O mesmo se aplica para cilindros.

3. Display List
um grupo de comandos OpenGL que so armazenados para execuo futura. Quando um display list chamado, os comandos so executados na ordem que foram definidos. Nem todos os comandos OpenGL podem ser armazenados em um display list. No podem ser utilizados especialmente comandos relacionados com vertex array, comandos como glFlush(), glFinish(), glGenLists(), dentre outros. Deve ser utilizada sempre que for necessrio desenhar o mesmo objeto mais de uma vez. Neste caso, deve-se guardar os comandos que definem o objeto e ento exibir a display list toda vez que o objeto precisar ser desenhado. No caso de um carro que possui 4 rodas, pode-se gerar um display list com a geometria de uma roda e invocar a renderizao, uma vez para cada roda, lembrando de aplicar as devidas transformaes para posicionar cada roda no devido lugar. Os dados de um display list residem no servidor, reduzindo deste modo o trafego de informaes. Dependendo da arquitetura do servidor, o display list pode ser armazenado em memria especial para agilizar o processamento. Para criar um display list deve-se utilizar os seguintes comandos: glGenLists(), glNewList() e glEndList() como mostrado no seguinte exemplo:
GLuint id_objeto; void init() { id_objeto = glGenLists(1); glNewList(id_objeto, GL_COMPILE); //comandos de desenho do objeto //vrtices, transformaes, etc. glEndList(); } void display() { ... glRotated(10, 1, 0, 0); glCallList(id_objeto); glTranslated(10, 31, 0); glCallList(id_objeto); ... glSwapBuffers(); }

GLuint glGenLists(GLsizei range): Aloca um intervalo contnuo de ndices. Se o parmetro range for igual a 1, gera um nico ndice que o valor retornado pela funo. O ndice retornado usado pelas funes glNewList() e glCallList(). O retorno zero significa erro. void glNewList (GLuint list, GLenum mode): Especifica o incio do display list. Todos os comandos vlidos especificados antes do comando glEndList() so guardados no display list. o List: identificador do display list. o Mode: aceita dois argumentos: GL_COMPILE_AND_EXECUTE e GL_COMPILE (indica que os comandos no devem ser executados medida que so inseridos no display list). void glEndList (void): indica o fim do display list. void glCallList (GLuint list): Executa o display list referenciado por list. Os comandos so executados na ordem que foram especificados, do mesmo modo caso no fosse utilizado este recurso. Alm de reduzir o nmero de chamada de funes, bem como a transferncia de dados para o servidor, reduz-se tambm processamento para gerao dos objetos. Supondo que fosse necessrio gerar um crculo (ou uma esfera) por coordenadas polares, diversos clculos de ngulos podem ser realizados uma nica vez, visto que apenas comandos OpenGL so armazenados na display list para processamento futuro.

Entretanto, uma vez gerada o display list, os valores das coordenadas do crculo no podem mais ser alterados. Comandos GLUT tambm pode ser inseridos, uma vez que so desmembrados em comandos bsicos do OpenGL. Pode-se criar display list hierrquicos, onde um display list invoca outros.
... id_objeto = glGenLists(1); glNewList(id_objeto, GL_COMPILE); glBegin(GL_POLYGON); for(int i=0; i<1000; i++) { x = cos(ang)*radius; y = sin(ang)*radius; ang+=(360.0/1000); glVertex2f(x,y); } glEnd(); glEndList(); ...

Para maiores detalhes dos benefcios do uso de display list e recursos adicionais, consulte [1].

4. Iluminao
O OpenGL permite a definio de fontes luminosas, modelos de iluminao e caractersticas dos materiais (o que tem influncia direta na reflexo da luz). A iluminao fundamental para dar a noo de profundidade. Sem iluminao, uma esfera e um disco possuem a mesma representao. Para se visualizar uma cena 3D sem o uso de iluminao, pode-se utilizar texturas ou fazer a visualizao em wireframe.

[http://en.wikipedia.org/wiki/Phong_reflection_model] O OpenGL oferece clculo da iluminao Ambiente, Difusa e Especular (Gouraud). Cada componente tratada e configurada separadamente para cada componente RGB, o que permite fazer operaes que no ocorrem no mundo real. A cor deve ser especificada para as fontes como para os materiais. Na fonte, especifica-se a cor que a conte ir emitir. Se R=G=B=1, a fonte ir emitir cor branca, e tem a intensidade mxima. Se os valores forem 0.5, a fonte ainda emitir branco, porm com apenas 50% da intensidade. Se somente R=1, a fonte emitir cor vermelha. No material especifica-se a taxa de reflexo de cada componente. Se R=1 e G=0.5, o material reflete toda luz vermelha incidente e apenas 50% da cor verde e no reflete a cor azul. Considerando-se que a fonte emite (LR, LG, LB), que o material reflete (MR, MG, MB), desconsiderando-se todos outros efeitos de reflexo, a luz que chega ao observador dada por (LR*MR, LG*MG, LB*MB). Caso existir mais de uma fonte, caso a somatria de intensidades LR1+LR2+..LRn for maior que 1, este valor truncando em 1 (funo clamp).

Para ser aplicada a iluminao a uma cena necessita-se: 1. Definio dos vetores normais da superfcie 2. Ativao e definio da fonte de luz 3. Selecionar um modelo de iluminao 4. Definio de propriedades dos materiais dos objetos da cena. Para a ativao das fontes de luz (Passo 1), deve utilizar os seguintes comandos: glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_LIGHT7); O OpenGL permite a definio de at 8 fontes. Por default a fonte 0 tem cor branca e as demais a cor preto. Para mudar a cor, dentre outros parmetros da fonte (Passo 2), deve-se utilizar o comando glLightf*v().

void glLight{if}v(GLenum light, GLenum pname, TYPE *param); light: Especifica o ID da fonte que deve ser especificada. Pode assumir os seguintes valores: GL_LIGHT0, GL_LIGHT1, ... , ou GL_LIGHT7. pname: define a caracterstica a ser alterada da fonte light. Pode-se passar os seguintes argumentos: o GL_AMBIENT: intensidade RGBA ambiente da luz o GL_DIFFUSE: intensidade RGBA difusa da luz o GL_SPECULAR: intensidade RGBA especular da luz o GL_POSITION: posio (x, y, z, w) da luz. w deve ser 0. o GL_SPOT_DIRECTION: direo (x, y, z) do spotlight. o GL_SPOT_EXPONENT: expoente do spotlight. o GL_SPOT_CUTOFF: ngulo de corte (float). O default 180 (sem restrio) o GL_CONSTANT_ATTENUATION: fator de atenuao constante (float). o GL_LINEAR_ATTENUATION: fator de atenuao linear (float). o GL_QUADRATIC_ATTENUATION: fator de atenuao quadrtico (float). param: ponteiro para o conjunto de dados. Pode ter 1, 3 ou 4 componentes, dependendo do argumento pname.
GLfloat GLfloat GLfloat GLfloat light_0_position[] light_0_difuse[] light_0_specular[] light_0_ambient[] = = = = { { { { 1, 1, 1, 0 }; 0, 0, 1 }; //BLUE 1, 1, 1 }; //WHITE 0.2, 0.2, 0.2 }; light_0_position); light_0_difuse); light_0_specular); light_0_ambient);

glLightfv(GL_LIGHT0, glLightfv(GL_LIGHT0, glLightfv(GL_LIGHT0, glLightfv(GL_LIGHT0,

GL_POSITION, GL_DIFFUSE, GL_SPECULAR, GL_AMBIENT,

O OpenGL permite tambm a especificao de modelos de iluminao (Passo 3) com o comando glLightModel*(). O modelo usado para definir a posio do viewpoint, definir se a iluminao ser aplicada nos dois lados das faces (front- e back-facing) e para especificao da iluminao global ambiente. Para definir a iluminao global ambiente, que independe de fontes de iluminao, pode-se utilizar o seguinte comando:
GLfloat lmodel_ambient[] = { 0.2, 0.2, 0.2, 1.0 }; glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);

Neste caso, qualquer objeto da cena ter iluminao ambiente, independente da posio e configurao das fontes luminosas. Mesmo com nenhuma fonte habilitada, com este fator de iluminao ainda pode-se visualizar a cena.

O prximo passo consiste na especificao dos materiais dos objetos da cena (Passo 4). Para isso existe o comando glMaterialfv().
void glMaterial{if}v(GLenum face, GLenum pname, TYPE *param);

face: indica em qual lado da face a propriedade ser aplicada. Pode assumir GL_FRONT, GL_BACK, ou GL_FRONT_AND_BACK. pname: define a caracterstica a ser alterada no material. Pode-se passar os seguintes argumentos: o GL_AMBIENT: cor RGBA ambiente do material; o GL_DIFFUSE: cor RGBA difusa do material; o GL_AMBIENT_AND_DIFFUSE: cor ambiente e difusa do material; o GL_SPECULAR: cor RGBA especular do material o GL_SHININESS: expoente especular (float). o GL_EMISSION: cor RGBA emissiva do material. o GL_COLOR_INDEXES: ndice de cores. param: ponteiro para o conjunto de dados. Pode ter 1, 3 ou 4 componentes, dependendo do argumento pname.
GLfloat mat_specular[] = { 1, 1, 1, 1 }; GLfloat mat_shininess[] = { 10 }; glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);

A especificao de parmetros das fontes e materiais um trabalho que exige experimentos e prtica. No trivial encontrar uma combinao ideal de forma imediata. Deve-se observar que a iluminao do OpenGL no gera sombras. Algoritmos para sombra devem ser implementados separadamente. Se a iluminao realizada por vrtices, que estratgia pode ser utilizada para gerar um cubo, por exemplo, com uma reflexo mxima apenas no centro de uma face?

5. Exibio de FPS Frames Per Second


Passos: Calcular o FPS Guardar o estado de cada atributos ativo com o comando glPushAttrib(GLbitfield mask). Este comando aceita diversas constantes como argumentos. Os dois mais genricos so GL_ALL_ATTRIB_BITS e GL_ENABLE_BIT. Este comando tem o mesmo efeito do glPushMatrix(), s que este opera sobre pilha de atributos. Desabilitar todos os atributos com glDisable(), para no interferirem na impresso do valor do FPS, que tratado como uma string: o Cor material (GL_COLOR_MATERIAL) o Coordenadas de textura (GL_TEXTURE_2D) o Nevoeiro (GL_FOG); o Iluminao (GL_LIGHTING) o Z-buffer (GL_DEPTH_TEST) o Composio (GL_BLEND) Setar a matriz de projeo como ortogrfica Habilitar a matriz de Modelview, Desenhar os caracteres com glRasterPos2f(), glutBitmapCharacter() e glutBitmapWidth(); Restaurar os atributos com glPopAttrib(); Para mais detalhes, veja o demo FPS.

6. Textura
Para dar as superfcies caractersticas mais realistas, o OpenGL oferece alm de recursos de iluminao, recurso de texturizao. Faz-se uso da tcnica de texture mapping para aplicar a textura sobre a superfcie dos polgonos. A idia mapear cada face do modelo em coordenadas de textura, geralmente representada por uma imagem, como na seguinte figura. A definio de coordenadas de textura, para cada tringulo do modelo, que neste exemplo um modelo de personagem animado 3D (Formato MD2), feita pelo modelador (artista grfico). A textura faz parte do estgio de rasterizao do pipeline grfico do OpenGL. A rasterizao a converso de dados geomtricos (polgonos) e pixels (textura) em fragmentos. Cada fragmento corresponde a um pixel no framebuffer.

O mapeamento da textura para os fragmentos nem sempre preserva as propores. Dependendo da geometria do objeto, podem haver distores da textura ao ser aplicada. Tambm pode acontecer de um mesmo texel (texture element) ser aplicado a mais de um fragmento como um fragmento mapear vrios texels. Para isso operaes de filtragem so aplicadas. Uma textura um mapa retangular de dados (geralmente cores como em uma imagem). O OpenGL oferece algumas maneiras de se especificar textura: pela especificao de coordenadas para cada vrtice do modelo ou pela gerao automtica de coordenadas de textura. Como o assunto de textura muito amplo, nesta seo so apresentados alguns comandos com alguns parmetros possveis. Para maiores detalhes, consulte [1]. Restries da textura: A textura deve ter preferencialmente dimenses em potncia de 2, como por exemplo: 64x128, 512x512, 128x64, etc. A funo glTexImage2D(), como ser visto, no funciona se a textura no seguir esta restrio. Outra funo equivalente, a gluBuild2DMipmaps(), por sua vez, opera com textura de qualquer dimenso. Se a textura no for potncia de 2, deve-se garantir que a posio de memria do pixel que representa o incio de uma linha seja mltipla de 4 (mesmo formato adotado pelo padro de imagem BMP para imagens que no so potncia de 2). Por exemplo, uma imagem em RGB de 3x4 pixels, vai ocupar 12 bytes por linha, ao invs de 9, como esperado. Ver demo de textura. Para se aplicar textura deve-se inicialmente habilitar a textura, criar a textura, definir parmetros e aplicar a textura. Para habilitar o recurso de textura utilizam-se os comandos glEnable(GL_TEXTURE); glEnable(GL_TEXTURE_2D);

Cada textura esta associada a um ID que usado pelo OpenGL para definio da textura ativa. A cada momento existe uma nica textura ativa, que aplicada sobre todos os objetos que possuem coordenadas de textura. Para criar um ID utiliza-se o comando glGenTextures(1,&id) que indica que sero criados 1 ndice de textura, e que este ndice ser armazenado na varivel intera id. Par se criar, habilitar e desabilitar a textura, utiliza-se o comando void glBindTexture(GLenum target, GLuint textureName); O parmetro textureName corresponde ao ID da textura. O parmetro target pode assumir GL_TEXTURE_1D ou GL_TEXTURE_2D. Quando este comando for chamado com um ID de textura inteiro diferente de zero pela primeira vez, um novo objeto de textura criado com o nome passado. Se a textura j havia sido criada, ela ento habilitada. Se o parmetro textureName for zero, desabilita o uso de textura do OpenGL. Aps a criao da textura (nome), deve-se configurar parmetros de aplicao da textura sobre um fragmento. void glTexParameter{if}(GLenum target, GLenum pname, TYPE param); target: pode assumir GL_TEXTURE_1D ou GL_TEXTURE_2D. pname e param: formam uma dupla. Para cada valor de pname, existem possveis valores para param. Pname GL TEXTURE WRAP S GL_TEXTURE_WRAP_T GL TEXTURE MAG FILTER GL TEXTURE MIN FILTER param GL CLAMP, GL REPEAT GL_CLAMP, GL_REPEAT GL NEAREST, GL LINEAR GL NEAREST, GL LINEAR, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR

Os parmetros GL_TEXTURE_WRAP_S/T representam como a textura ser aplicada sobre objeto, caso o objeto for maior que a textura. GL_CLAMP usa a cor da borda e GL_REPEAT replica a textura. GL_NEAREST indica que deve ser usado o texel com coordenadas mais prximas do centro do pixel. GL_LINEAR faz uma mdia dos 2x2 texels vizinhos ao centro do pixel.

Os parmetros GL_TEXTURE_MAG/MIN_FILTER indicam como a textura ser filtrada. Isso ocorre porque aps a projeo, pode ocorrer de parte de um texel aplicado sobre um pixel (magnification) ou de vrios texels serem aplicados sobre um nico pixel (minification). O argumento passado vai indicar como ser realizada a mdia ou interpolao dos valores. A ltima etapa consiste na definio dos dados da textura. Para isso existem dois comandos: glTexImage2D() e gluBuild2DMipmaps().
void glTexImage2D(GLenum target,

GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);

level: comumente deve ser 0. Ver funo gluBuild2DMipmaps() para gerao automtica de textura em vrias resolues. internalFormat: indica como esto armazenados os dados no array pixels (imagem). Pode assumir vrios valores. O parmetro mais comum GL_RGB, para indicar que o array um vetor de coordenadas RGB. width: largura da imagem em pixels height: altura da imagem em pixels border: indica a largura da borda. Valor 0 significa sem borda. format: Formato dos dados. Use GL_RGB. type: Geralmente deve ser GL_UNSIGNED_BYTE para indicar que cada componente RGB utiliza 1 byte no sinalizado. pixels: contm os dados da imgem-textura. Ver restries de dimenso de textura.
int gluBuild2DMipmaps(GLenum target, GLint components, GLint width, GLint height, GLenum format, GLenum type, void *data);

Esta funo cria uma srie de mipmaps e chama a funo glTexImage*D() para carregar as imagens. Por isso uma funo glu. Vrios argumentos so os mesmos da funo glTexImage2D(). Para se especificar as coordenadas de textura para cada vrtice utiliza-se o comando glTexCoord*().
void glTexCoord{1234}{sifd}(TYPE coords); void glTexCoord{1234}{sifd}v(TYPE *coords);

Este comando seta as coordenadas de textura corrente (s, t, r, q). Vrtices definidos na seqncia com glVertex*() fazem uso do valor corrente de textura. Geralmente utiliza-se o comando glTexCoord2f() para definir as coordenadas s e t. Coordenadas de textura so multiplicadas pela matriz de textura antes que o mapeamento ocorra. Por default esta matriz a identidade. A matriz de textura pode conter vrios tipos de transformaes como rotaes, translaes, perspectivas, etc. Para aplicar transformaes nesta matriz deve-se setar a matriz de textura como corrente com o comando glMatrixMode(GL_TEXTURE). Com isso pode-se simular a rotao de uma textura sobre uma superfcie.

(0,1)

(1,1)

(0,0) Textura (0,3)

(1,0) (5,3)

(0,0)

(5,0)

Mapeamento da textura. Adaptada de [3]

10

Um programa que usa textura tem a seguinte estrutura. Para maiores detalhes, veja o demo de textura.
int tex_id; void init() { glGenTextures( 1, &tex_id ); glBindTexture( GL_TEXTURE_2D, tex_id ); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); ... glTexImage2D(GL_TEXTURE_2D,...); glEnable( GL_TEXTURE ); glEnable( GL_TEXTURE_2D ); } void render() { glBindTexture( GL_TEXTURE_2D, tex_id ); glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex3f(v[0].x, v[0].y, glTexCoord2f(3, 0); glVertex3f(v[1].x, v[1].y, glTexCoord2f(3, 3); glVertex3f(v[2].x, v[2].y, glTexCoord2f(0, 3); glVertex3f(v[3].x, v[3].y, glEnd(); }

v[0].z); v[1].z); v[2].z); v[3].z);

Exemplos de gerao de textura:


GLuint textureID[MAX_TEXTURES]; glGenTextures( 1, &textureID[0] ); glBindTexture( GL_TEXTURE_2D, textureID[0] ); 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_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, img1->getWidth(), img1->getHeight(), GL_RGB, GL_UNSIGNED_BYTE, data); glGenTextures( 1, &textureID[1] ); glBindTexture( GL_TEXTURE_2D, textureID[1] ); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img1->getWidth(), img1->getHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, data);

11

Gerao automtica de coordenadas de textura


O OpenGL permite que as coordenadas de textura sejam criadas automaticamente. Isso muito til em diversas aplicaes como por exemplo na gerao de terrenos onde os vrtices formam um reticulado. Considere o caso de um malha poligonal com dimenso 10x10, com origem em (0,0). Independente do nmero de faces que vai ter, deseja-se aplicar uma nica textura sobre toda a malha, sem replicao. Neste caso define-se uma escala 1/10 e especifica-se parmetros de projeo da textura nos eixos x e z, como no seguinte exemplo.

(10,10)

float escala = 1.0 / 10; float p1[4] = { escala, 0, 0, 0}; float p2[4] = { 0, 0, escala, 0}; glTexGenfv(GL_S, GL_OBJECT_PLANE, p1); glTexGenfv(GL_T, GL_OBJECT_PLANE, p2);

Como o quadrado tem dimenso de 10, com coordenada inicial em (0,0), se escala valesse 1/20, seria aplicada apenas da textura. Se escala = 1/5, seriam usadas 4 cpias da textura (com filtro GL_REPEAT) para preencher o quadrado.
glGenTextures( 1, &id ); glBindTexture( GL_TEXTURE_2D, id); float escala = 1.0 / 10; float p1[4] = { escala, 0, 0, 0 }; float p2[4] = { 0, escala, 0, 0 }; glTexGenfv(GL_S, GL_OBJECT_PLANE, p1); glTexGenfv(GL_T, GL_OBJECT_PLANE, p2); glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); 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_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, img1->getWidth(), img1->getHeight(), GL_RGB, GL_UNSIGNED_BYTE, data);

Deve-se habilitar a gerao automtica de textura e aps o uso desabilitar. Maiores detalhes podem ser vistos em [1].
glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T);

7. Pipeline de Renderizao
Uma corrente no mais forte que o seu elo mais fraco. Annimo O pipeline grfico de uma aplicao grfica que faz uso do OpenGL (tradicional sem shanding) composto por 3 etapas: aplicao, geometria e rasterizao, como mostrado na seguinte figura. Os processos do nvel de aplicao executam na CPU e os dois demais na GPU. Os 3 estgios executam simultaneamente. Antes do surgimento de placas aceleradoras, todo este trabalho era executado

12

exclusivamente pela CPU. Hoje em dia h uma separao das tarefas, o que permite aliviar o uso da CPU para outras tarefas como: processamento da IA (visto que ainda no existem placas destinadas a este propsito), interao com o usurio, simulao fsica (por pouco tempo, visto que esto surgindo placas dedicadas ou incorporadas placa de vdeo destinadas a este propsito), Algoritmos de remoo de objetos no visveis (culling), etc.

Aplicao
Entrada do usurio

Geometria
Transformaes do modelo e de cmera

Rasterizao
Converso vetorial matricial - rasterizao

Cinemtica dos objetos e teste de coliso

Iluminao

Operaes de fragmentos: textura, fog, blending, etc.

Processamento da IA

Projeo Frame buffer de cor e profundidade

Descarte de objetos fora do campo de viso

Recorte

Mapeamento para tela Extrao da geometria a ser visualizada

Etapas do processo de renderizao. Adaptada de [3].

Como mostrado na seguinte figura, o pipeline de geometria opera sobre vrtices, enquanto o pipeline de rasterizao opera sobre pixels (fragmentos).
Operaes por vrtice Transformao Modelagem e Visualizao Mapeamento de Tela

Aplicao

Iluminao

Projeo

Clipping

Rasterizao

Mapeamento de Textura

Combinao

Flog/Blend Teste , s, z

Frame Buffer

Operaes por pixel


Aplicao Geometria Rasterizao

Estgios funcionais do pipeline. Extrado de [3]

O Framebuffer composto por: Color buffers: guarda a cor dos pixels (fragmentos). Pode existir o left- e right-buffer (para viso estreo), e cada um destes pode ser single ou double (front- e back-buffer). Depth buffer: guarda a profundidade dos fragmentos em relao posio da cmera. Podem haver vrios fragmentos que projetam em um mesmo pixel. Somente o mais prximo ser o visvel (ver algoritmo z-buffer).

13

Accumulation Buffer: semelhante ao buffer de cor, com a diferena que este pode ser usado para acumular uma srie de imagens. Isso til em operaes de super-amostragem, antialiasing e motion blur. Stencil Buffer: buffer usado para restringir o desenho a certas partes da tela. Pode ser usado para desenhar o interior do carro (painel, direo, etc). Somente a rea na regio do pra-brisa que pode ser atualizada com informaes da cena. Para cada buffer, existem comandos de limpeza, como glClearColor(), glClearDepth(), glClearAccum() e glClearStencil(), ou glClear(GL_COLOR_BUFFER_BIT | ...). Para maiores detalhes de uso destes buffers, consulte [1]. O buffer de profundidade alterado pelo algoritmo z-buffer. Este buffer tem o mesmo tamanho e forma que o color buffer, onde cada pixel armazena a distncia da cmera at a primitiva corrente mais prxima. Quanto uma primitiva estiver sendo renderizada para um certo pixel (amostragem), compara-se a distncia deste pixel em relao cmera. Se a distncia for menor que a distncia j armazenada, significa que a primitiva corrente, para o dado pixel, est mais prxima que a ltima primitiva avaliada. Neste caso deve-se atualizar o buffer de profundidade, juntamente com o buffer de cor com informaes da nova primitiva. Se a distncia for maior, mantm-se os buffers inalterados. O custo computacional do z-buffer O(n), onde n nmero de primitivas sendo renderizadas.

7.1. Otimizao do Pipeline


Como os 3 estgios conceituais (aplicao, geometria e rasterizao) executam simultaneamente, o que for mais lento (gargalo) vai determinar a velocidade de renderizao (throughput). Observaes: Antes de tudo deve-se localizar o gargalo; Deve-se procurar otimizar o estgio mais lento para aumentar o desempenho do sistema; Se o estgio da aplicao for o mais lento, no se ter nenhum ganho otimizando o estgio de geometria, por exemplo; Ao se otimizar o estgio mais lento, pode ocorrer de outro estgio se tornar o novo gargalo; Caso o gargalo no puder ser otimizado, pode-se melhor aproveitar os demais estgios para se obter maior realismo. A estratgia mais simples para se detectar o gargalo realizar uma srie de testes, onde cada teste afeta somente um nico estgio. Se o tempo total for afetado, ou seja, reduzir o frame rate, ento o gargalo foi encontrado. Para isso pode-se aumentar ou reduzir o processamento de um estgio. Teste no estgio da Aplicao: A estratgia mais simples neste caso reduzir o processamento dos outros estgios, pela simples substituio dos comandos glVertex*() por glColor*(). Neste caso os estgios de geometria e rasterizao no vo ter o que processar. Se o desempenho no aumentar, o gargalo est na aplicao. Outra estratgia incluir um lao de repetio que realiza N clculos matemticos. Se o desempenho geral piorar, o gargalo era a aplicao. Teste no estgio de geometria: o estgio mais difcil de se testar pois se a carga de trabalho neste estgio for alterada, ser alterada tambm em outros estgios. Existem duas estratgias de teste: aumentar ou reduzir o nmero de fontes luminosas, o que no vai afetar os demais estgios, ou verificar se o gargalo est no estgio da aplicao ou rasterizao. Teste do estgio de Rasterizao: o estgio mais fcil de ser testado. Isso pode ser feito simplesmente aumentando-se ou reduzindo-se o tamanho da janela onde as imagens esto sendo renderizadas. Isso no interfere nem na aplicao e nem na geometria. Quanto maior for a janela, maior ser a quantidade de pixels a serem desenhados. Outro modo de testar desabilitando operaes de textura, fog, blending.

14

Existem vrias estratgias para se otimizar os estgios do pipeline. Algumas abordagens comprometem a qualidade em troca de desempenho e outras so apenas melhores estratgias de implementao: Otimizao do Estgio da Aplicao: otimizaes para tornar o cdigo e acesso memria mais rpidos. Isso pode ser obtido ativando-se flags de compilao e conhecendo detalhes das linguagens de programao. Algumas dicas gerais de cdigo/memria so listadas. Para maiores detalhes consulte [2]: o Evite divises; o Evite chamar funes com pouco cdigo. Use funes inline; o Reduzir uso de funes trigonomtricas; o Usar float ao invs de double; o Usar const sempre que possvel, para o compilador melhor otimizar o cdigo; o Evitar uso excessivo de funes malloc/free. Otimizao do Estgio de geometria: Pode-se aplicar otimizaes apenas sobre transformaes e iluminao. o Em relao a transformaes, se o objeto precisar ser movido para uma posio esttica, ao invs de aplicar a transformao a cada renderizao, pode-se aplicar as transformaes em um pr-processamento antes da renderizao iniciar; o Outra estratgia reduzir ao mximo o nmero de vrtices, com o uso de vertex array, ou primitivas do tipo STRIP ou FAN; o Outra estratgia muito eficiente aplicar culling, no estgio da aplicao; o Uso de LOD; o Reduzir o nmero de fontes luminosas; o Verificar quais partes da cena necessitam iluminao; o Iluminao flat mais rpida que Gourdaud; o Avaliar se necessrio iluminar os dois lados das superfcies; o Uso de Light maps. Otimizao do Estgio de Rasterizao: o Habilitar backface culling para objetos fechados. Isso reduz o nmero de tringulos para serem rasterizados em aproximadamente 50%; o Desenhar objetos mais prximos do observador primeiro. Isso evita gravaes sucessivas no z-buffer; o Desabilitar recursos como fog, blending ou uso de filtros de textura mais baratos, como o bilinear ao invs de mipmapping. Otimizaes gerais: o Reduzir a geometria da cena; o Reduza a preciso em vrtices, normais, cores e coordeandas de textura. Isso reduz uso de memria e uso de barramento; o Desabilitar recursos no utilizados; o Minimizar mudana de estados; o Evitar swap de texturas; o Use display lists para objetos estticos.

7.2. Avaliando o Desempenho do Pipeline


A velocidade de renderizao depende do estgio mais lento, e medida em FPS (frames por segundo). Para este clculo, deve-se desabilitar o recurso de double-buffer, visto que a troca de buffer neste caso ocorre em sincronismo com o refresh do monitor. Com o double buffer ativado, enquanto o front buffer est sendo exibido, o back buffer est sendo gerado. Somente ocorre a troca de buffers (glutSwapBuffers) quando o monitor acabar de desenhar o frame corrente.

15

Considerando-se o monitor com uma taxa de atualizao de 72 Hz, significa que a cada t = 13. 8 milisegundos a tela atualizada. Com o recurso de double-buffer ativado, a taxa de atualizao deve ser mltiplo deste valor. Se o tempo de renderizao consome 20 ms (50 Hz) em single-buffer, a taxa cair para 2*13. 8 = 36 Hz com o double-buffer ativo. Neste caso, o pipeline grfico fica inativo por 13. 8*2 20 = 7.78 ms para cada frame [2].

Monitor Pipeline

13.8 ms 20 ms

13.8 ms 7.78 ms

13.8 ms 20 ms

13.8 ms 7.78 ms

13.8 ms 20 ms

Uma forma de contornar os problemas do uso do double-buffer o uso de tiple-buffer. Neste caso existem dois back buffers e um front buffer. Neste caso, enquanto o monitor est exibindo o font buffer, podem estar sendo gerados 1 ou 2 back buffers. No caso do uso de double-buffer, o o refresh do monitor for de 60 Hz e o tempo de gerao das cenas for menor que 1/60 s, ento mantm-se uma taxa de 60 fps. Porem se o tempo de gerao for pouco maior que 1/60 s, a taxa de atualizao cai para 30 fps. Com o uso de triple-buffer, a taxa se mantm prxima de 60 fps. O inconveniente do uso de triple-buffer que o tempo de resposta para aes do usurio um pouco maior, especialmente se o fps for baixo.

8. Tpicos adicionais
Vrios tpicos suportados pelo OpenGL no foram tratados neste material. Para detalhes sobre assuntos como blending, fog, antialiasing, bitmaps, qudricas, NURBS, picking, e extenses OpenGL, consulte [1]. Para tcnicas de renderizao como sombras, efeitos especiais e tcnicas de otimizao, consulte [2].

9. Referncias Bibliogrficas
[1] Woo, M.; Neider, J.; Davis, T.; Shreiner, D. OpenGL: Programming Guide. 5. ed. Massachusetts : Addison-Wesley, 2005. [2] Moller, T.; Haines, E.; Akenine, T. Real-Time Rendering. 2 ed. AK Peters, 2002. [3] Celes, W. Notas de Aula. PUC-Rio, 2006.

16

Você também pode gostar