Introdução à programação com OpenGL

Trabalho feito para disciplina Computação Gráfica, INPE, 2000.

Dmitry V. Fedorov.


O que ?


A biblioteca OpenGL é utilizada para programação gráfica em 3D. OpenGL em inglês é Open Graphics Library, Biblioteca Gráfica Aberta. Aberta significa independente do fabricante. OpenGL é um padrão bem documentado e a biblioteca em si pode ser produzida por qualquer um. O importante é que a biblioteca atenda as especificações OpenGL e certos testes. A biblioteca é produzida por vários fabricantes como Microsoft e Silicon Graphics e também por grupos de programadores como a bem conhecida Mesa. Mesa foi escrita por vários programadores, o autor principal é Brian Paul. A biblioteca é distribuída em código fonte em C e pode ser montada em varias sistemas operacionais.


Porque ?


As vantagens da biblioteca citados em www.opengl.org são : padrão de indústria, estável, seguro e portátil, em evolução, escalavel, fácil usar, bem-documentado. O padrão OpenGL começou a ser desenvolvido em 1992 por empresa Silicon Graphics, desde então ficou muito conhecida e virou o padrão de fato. Atualmente esta integrada em quantidade enorme de linguagens de programação como C, C++, Pascal, Object Pascal, Java, Ada, Fortran, etc. OpenGL é oferecida em todas estações de trabalho UNIX®, vem junto com todos os Windows NT® e Windows® 95. Nenhuma outra API suporta mais plataformas de hardware e software que OpenGL. Ela também roda em SOs como Mac® OS, OS/2®, UNIX, Windows 95, Windows NT, Linux, OPENStep, Python, e BeOS; e também é suportada por muitas sistemas de janelas como Presentation Manager, Win32, e X/Window System. Muitos jogos utilizam OpenGL, tais como: Quake I/II/III, Soldier of Fortune, Half-Life, MDK2, SiN, Heretic II, Hexen II, HomeWorld e muitos outros. As funções da OpenGL são oferecidos em hardware para PCs por fabricantes de chips de 3D como: Sgi, nVidia, 3dfx, ATI ...


Como ?


A biblioteca representa uma interface de programação em 3D. O elemento de informação é vértice dos quais outros objetos mais complexos são construídos. O programador cria vértices especifica o tipo de ligação, especifica coordenadas, câmeras e luzes e a biblioteca se encarrega da criação da imagem na tela. Esta biblioteca é a solução ideal para programadores que precisam criar uma cena pequena em 3D e não querem se envolver com aspectos de programação 3D. Para profissionais ela também oferece mecanismos básicos e certa automação. Utilizando OpenGL pode-se facilmente criar superfícies em 3D, aplicar texturas, iluminar, criar efeitos de neblina, transparência ou mistura de cores, também os objetos podem ser movidos criando animação. A biblioteca não suporta os equipamentos de entrada como teclado ou mouse, sendo completamente independente da plataforma. Estes recursos são programados dependendo da SO utilizada ou podem ser utilizadas bibliotecas adicionais como GLUT ou GLAUX. As diferenças de utilização (programação) da OpenGL para linguagens e SOs diferentes está em inicialização da biblioteca e em nomes (prefixos e sufixos) das funções. A programação em si é praticamente mesma.


Para windows a biblioteca é distribuída em forma dos DLLs, Windows 95osr2, 98, NT4, 2k vem com OpenGL v1.1 da Microsoft em arquivos opengl32.dll e glu32.dll. Também existe a distribuição da Silicon Graphics que 15-20% mais rápida que a da Microsoft, atualmente não mais suportada, opengl.dll e glu.dll. Os fabricantes de placas/chips 3D normalmente oferecem os drivers em forma de DLLs que executarão as chamadas em hardware. As bibliotecas da Microsoft e da Sgi por padrão procuram se existe hardware com drivers e se existir redirecionarão as chamadas para estes drivers em vez de executar tudo por software. A biblioteca da Microsoft fará chamadas para o primeiro dispositivo. Por isso o jeito mais fácil e universal seria fazer aplicativo que chama DLLs da Microsoft.

A versão utilizada aqui é 1.1 e 1.2 (última para 18/07/2000) por isso alguns exemplos podem não funcionar com versões anteriores.

Direto ao Assunto

Vamos desenhar uma esfera.

Para utilizar a biblioteca em C temos que adicionar os arquivos opengl32.lib, glu32.lib e glaux.lib se pretendemos usar AUX ao projeto.

O código pode ser colocado em Display (Visual C++) ou em respectivas funções de outras linguagens.


glColor3d(1,0,0);

auxSolidSphere(1);




Função glColor3d modifica a cor utilizada para desenhar figuras. A cor em OpenGL é especificada través de três parâmetros de cor: Vermelho, Azul, Verde e Transparência. O valor de Transparência por padrão é opaco. O quarto parâmetro não foi utilizado, por isso chamamos glColor com três parâmetros. Para isso o formato de chamadas é: FuncionName[n=numero de parâmetros][tipo de parâmetros]. Os tipos destes parâmetros são:


b - GLbyte byte

s - GLshort inteiro curto

i - GLint inteiro

f - GLfloat real (ponto flutuante)

d - GLdouble real com dupla precisão

ub - GLubyte byte sem sinal

us - GLushort inteiro curto sem sinal

ui - GLuint inteiro sem sinal

v - vetor de n parâmetros de um tipo especificado


Neste caso, glColor3d significa que a função recebe três parâmetros do tipo Gldouble. Assim podemos chamar glColor3i onde i especifica o tipo GLint.


A função glColor3dv significa que como parâmetro é dado um vetor de três elementos do tipo GLdouble.

Ex:

double array[] = {0.5, 0.75, 0.3, 0.7};

Exemplos:

glColor3dv(array);

glColor3ub(200, 100, 0);

glColor3d(0.25, 0.25, 0);

glColot3ub(0, 100, 0);

glColor3ub(0, 0, 255);


A função auxSolidSphere desenha esfera em ponto (0,0) - inicio das coordenadas e raio de 1. A iluminação e a câmara necessárias para visualização do objeto serão apresentadas mais tarde.


Figuras tridimensionais


Existem outras funções para desenhar figuras:


auxSolidCube(width)

auxSolidBox(width, height, depth)

auxSolidTorus(r, R)

auxSolidCylinder(r, height)

auxSolidCone(r, height)

auxSolidIcosahedron(width)

auxSolidOctahedron(width)

auxSolidTetrahedron(width)

auxSolidDodecahedron(width)

auxSolidTeapot(width) // desenha chaleira


Se os parâmetros forem muito grandes as bordas das figuras sairão para fora do monitor e não serão vistas. A parte Solid pode ser substituída por Wire assim a função desenhara a figura em linhas da estrutura.

Ex:

auxWireCube(1);

Mudança de coordenadas

Todas as figuras que desenhamos ate agora foram desenhadas no ponto (0, 0, 0) para modificar este ponto temos que mudar a posição do centro de coordenadas para um ponto novo. Esta operação é muito utilizada em computação gráfica, é muito útil transladar coordenadas e girar o sistema de coordenadas. Em OpenGL existem duas funções :


glTranslated( DX, DY, DZ )

glRotated( a, X0, Y0, Z0 )


A glTranslated desloca o centro de coordenadas para DX, DY, DZ. A função glRotated gira o centro de coordenadas para o ângulo a no sentido anti-horário ao redor do vetor (X0, Y0, Z0). As funções muito úteis para utilização com as duas anteriores são :


glPushMatrix()

glPopMatrix()


A primeira guarda a posição corrente do centro de coordenadas e a segunda restaura a posição guardada. As posições são guardadas em uma pilha interna do OpenGL. O tamanho da pilha pode ser identificado através de:

glGetIntegerv(GL_MAX_MODELVIEW_STACK_DEPTH, &n);


Ex glTranslated:


glPushMatrix(); // salvar as coordenadas correntes

glTranslated(1.4,0,0); // deslocação pelo eixo X a 1.4

glColor3d(0,1,0);

auxSolidSphere(0.5); // desenha esfera em (1.4,0,0)


glTranslated(1,0,0); // mais uma deslocação

glColor3d(0,0,1);

auxSolidSphere(0.3);

glPopMatrix(); // volta para o sistema de coordenadas


glColor3d(1,0,0);

auxSolidSphere(0.75); // desenha esfera em ponto (0,0,0)







Ex glRotated:


glColor3d(1,0,0);

auxSolidCone(1, 2); // desenha um cone


glPushMatrix();

glTranslated(1,0,0);

glRotated(75, 1,0,0); // girar sist. coord. P/ 75gr.

glColor3d(0,1,0);

auxSolidCone(1, 2);

glPopMatrix();


Para efetuar uma escala há o comando glScalef(ex, ey, ez) que altera a escala do objeto ao logo dos eixos coordenados.


Ex. glScalef:


DesenhaObjeto();// Desenha o objeto na posição

// corresp. às suas coordenadas originais


glScalef(0, 0.5, 0);

DesenhaObjeto(); // Diminui a altura do objeto à metade do origianl


glScalef(0, 2.0, 0);

DesenhaObjeto(); // Desenha outro objeto no seu tamanho original

Para permitir que a transformação atual seja reinicializada há o comando glLoadIdentity(), este comando substituirá a matriz corrente com a matriz de identidade.


Ex. glLoadIdentity:


DesenhaObjeto();// Desenha o objeto na posição

// corresp. às suas coordenadas originais


glScalef(0,0.5,0);

DesenhaObjeto(); // Diminui a altura do objeto à metade do original


glLoadIdentity(); // reinicializa as transformações


glScalef(0,2.0,0);

DesenhaObjeto(); // Desenha objeto com o dobro do tamanho


Animação simples


Para animar qualquer figura basta modificar as coordenadas do objeto com o tempo. No exemplo seguinte uma figura move-se em relação ao eixo X.


glPushMatrix();

glTranslated( ((double)time)/100.0 ,0,0);

// aqui código de desenho da figura

glPopMatrix();

Desenho de objetos simples

Todos os objetos são formados por objetos simples como pontos, linhas, triângulos ... Os objetos que desenhamos em anteriormente não estão em implementação básica de OpenGL e sim em uma biblioteca de utilitários (no caso windows glu32.dll) que utiliza as funções de OpenGL para desenhar os objetos mais complexos. Os primitivos são criados de seguinte modo:


glBegin(GLenum mode); // especificar o que é pra ser desenhado

glVertex[2 3 4][s i f d](...); // primeiro vértice

... // aqui os vértices seguintes

glVertex[2 3 4][s i f d](...); // ultimo vertice

glEnd(); // finalizar o desenho do objeto


As funções para desenhar vértices são :


glVertex2d(x,y); // 2 variaveis do tipo double

glVertex3d(x,y,z); // 3 variaveis do tipo double

glVertex2dv(array); // array de 2 variaveis do tipo double

glVertex3d(array); // array de 3 variaveis do tipo double

Os modos possíveis para criação de primitivos com glBegin :


GL_POINTS - cada chamada glVertex cria um ponto

GL_LINES - cada par de vértices cria linha

GL_LINE_STRIP - cria um linha quebrada em vertices

GL_LINE_LOOP - o mesmo do anterior e o ponto final é conectado com o primeiro

GL_TRIANGLES - 3 vertices criam triangulo

GL_TRIANGLE_STRIP - são desenhados triângulos com um lado em commum

GL_TRIANGLE_FAN - o mesmo, só os vértices são ligados do outro jeito

GL_QUADS - quatro vértices criam quadrante

GL_QUAD_STRIP - quadrantes com o mesmo lado

GL_POLYGON - poligono


Pontos


Os pontos podem ser desenhados dentro do glBegin/glEnd a função glColor3d pode ser chamada dentro. Para modificar o tamanho do ponto pode ser chamada glPointSize(GLfloat size).

Os pontos podem ser desenhados no modo de suavização habilitado com a função :

glEnable(GL_POINT_SMOOTH);

e desabilitado

glDisable(GL_POINT_SMOOTH);


Linhas


Para a criação de linhas também podem ser modificadas largura, cor, tamanho e suavização. Se definir cores diferentes para inicio e o final da linha OpenGL mostrará gradiente que é habilitado por padrão. A linha também pode ser desenhada com interrupções utilizando mascara :


void glLineStipple(GLint factor, GLushort pattern);


O segundo argumento define a mascara, o valor deve ser apresentado no formato binário, assim para o numero 255 (00FFh) a representação binária em 16 bits é 0000000011111111, nos 0 a linha não será desenhada. O primeiro argumento define a repetição de cada bit, por exemplo se for 2 a mascara resultante será: 00000000000000001111111111111111


Ex. linha 1:

glLineWidth(2); // largura de linha = 2

glBegin(GL_LINES);

glColor3d(1,0,0);

glVertex3d(-4.5,3,0); // primeira linha, inicio

glVertex3d(-3,3,0); // primeira linha, final


glColor3d(0,1,0); // define gradiente de verde

glVertex3d(-3,3.3,0); // segunda linha, inicio

glColor3d(0, 0, 1); // define gradiente para azul

glVertex3d(-4,3.4,0); // segunda linha, fim

glEnd();


Ex. linha 2:


glLineWidth(5);

glEnable(GL_LINE_SMOOTH);

glEnable(GL_LINE_STIPPLE); // abilitar o desenho de linha interrompida

glLineStipple(2, 58360); // define mascara


glBegin(GL_LINE_LOOP);

glColor3d(1,0,0);

glVertex3d(1,3,0);

glVertex3d(4,3,0);


glColor3d(0,1,0);

glVertex3d(3,2.7,0);

glColor3d(0,0,1);

glVertex3d(2.5,3.7,0);

glEnd();


glDisable(GL_LINE_SMOOTH);

glDisable(GL_LINE_STIPPLE);


Triangulos


Para desenho de triângulos podem ser usadas as mesmas funções. No modo GL_TRIANGLE_STRIP o primeiro triangulo será definido por vértices 1, 2 e 3 o segundo por 3, 4 e 5 e assim sucessivamente. Outras figuras são desenhadas do mesmo jeito.

Operações com cores

Interpolação de cores


glShadeModel(GL_SMOOTH) // habilita interpolação

glShadeModel(GL_FLAT) // desabilita


Transparência


Utilizando o quarto componente de cor podemos modificar a transparência de um objeto. Para habilitar o processamento deste quarto componente :

glEnable(GL_ALPHA_TEST)

Para visualizar o efeito a mistura de cores deve ser habilitada :

glEnable(GL_BLEND)

E ainda deve ser espicificado o algoritimo utilizado para mistura de cores:

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)


Pela definição de OpenGL os objetos mais distantes devem ser desenhados antes dos mais proximos porque OpenGL faz um teste de profundidade.


Ex. Transparencia :


glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );


glEnable(GL_ALPHA_TEST);

glEnable(GL_BLEND);

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);


glColor4d(1, 0, 0, 1);

auxSolidSphere( 1 );

glColor4d(0, 1, 0, 0.6);

auxSolidCylinder(2, 3);

glDisable(GL_BLEND);

glDisable(GL_ALPHA_TEST);

Planos de corte.

Existe 6 planos de corte, todos são disabilitados. Para habilitar:

glEnable(GL_CLIP_PLANE0)

onde o numero especifica o plano de corte. O plano em si é definido em glClipPlane, primeiro argumento é o plano e o segundo é um vetor com com as quatro coeficientes da equação do plano ( A*x + B*y + C*z + D = 0 ). Ex:


GLdouble equation[4] = {-1, -0.25, 0, 2};

glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );


glEnable(GL_CLIP_PLANE0);

glClipPlane(GL_CLIP_PLANE0, equation);

glColor3d(1,0,0);

auxSolidSphere( 3 );

glDisable(GL_CLIP_PLANE0);



Neblina


Para abilitar a neblina :

glFogf(GL_FOG_DENSITY, density);

Texturas e Imagens

A biblioteca OpenGL não suporta arquivos e formatos gráficos como BMP, GIF, JPEG mas consegue ler as imagens de uma matriz na memória. Assim as imagens devem ser carregadas na memória utilizando outras bibliotecas e depois utilizadas em OpenGL. Os pixels nestes vetores podem ser mantidos em vários formats: RGB, BGR, mantidos emvários formats: RGB, BGR, RGBA, etc. OpenGL possui funções para visualizar imagens (glDrawPixels), copiar (glCopyPixels), modificar escala (gluScaleImage). Antes de usar imagens devem ser definidos formato dos pixels e alinhamento dentro do array. O alinhamento é modificado:

glPixelStorei(GL_UNPACK_ALIGNMENT, align)

o segundo argumento é um numero inteiro que define o alinhamento.

Para visualizar a imagem, a posição inicial deve ser definida:

glRasterPos2d(x,y)

Tambem o tamanho do pixel pode ser definido atraves:

glPixelZoom(width, length)


ex. visualização de imagem:

glRasterPos2d(-4.5,-3); // ponto esquerdo mais baixo

glPixelZoom(1,1);

glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // alinhamento

glDrawPixels(image->sizeX, image->sizeY, // larg. e alt.

GL_RGB, GL_UNSIGNED_BYTE, // formato

image->data); // dados da imagem



Para aplicar uma imagem como textura em cima de um objeto:

1) Carregar a imagem na memoria

2) Criar Nome-Identificador da textura

3) Ativar a textura

4) Criar a textura em si na memória

5) Definir os parâmetros da textura

6) Definir como a textura será aplicada no objeto

7) Ligar as coordenadas da textura com o objeto


Pela definição do OpenGL as texturas devem ter tamanhos 2n x 2m, onde n e m são números inteiros. A função glGenTextures(num_text, array_text) cria identificadores de texturas, onde num_text é o numero de texturas a serem criadas e array_text é o vetor onde os identificadores serão guardados (o tamanho do array não pode ser menor que o numero de texturas).

unsigned int names[10];

glGenTetures(10, names);


Mas identificador pode ser guardado em uma variável separada:

unsigned int img_tex;

glGenTextures(1, &img_tex);


Agora podemos ativar a textura:

glBindTexture(GL_TEXTURE_2D, img_tex);

o primeiro parametro pode ser GL_TEXTURE_1D para texturas unidimencionais.

Agora podemos criar a textura, para isso existem duas funções glTexImage[1/2]D e gluBuild[1/2]DMipmaps


glTexImage2D(

GLenum target,

GLint level,

GLint components,

GLsizei width,

GLsizei height,

GLint border,

GLenum format,

GLenum type,

const GLvoid* pixels)


gluBuild2DMipmaps(

GLenum target,

GLint components,

GLsizei width,

GLsizei height,

GLenum format,

GLenum type,

const GLvoid* pixels)


A diferença é que a primeira função somente aceita as imagens com tamanho do expoente 2, i.e. 4, 16, 32 ... e também gera somente um nivel de detalização. O primeiro parâmetro dela deve ser GL_TEXTURE_2D, segundo é o nível de detalização, para ter imagem como é o nível deve ser 0. Terceiro parâmetro especifica o numero de componentes de cor (para RGB = 3). Quarto e quinto são largura e altura da imagem. Sexto é a largura da borda, para não ter igual à 0. Setemo é o formato de como os pixels são guardados : mais usualmente GL_RGB e tipo GL_UNSIGNED_BYTE (nas verções mais novas de OpenGL existe mais tipos e formatos do que na v1.0). Finalmente o oitavo parâmetro é o ponteiro para a matriz de dados.

Ex. Criação de textura:


glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

glTexImage2D(GL_TEXTURE_2D, 0, 3,

image->sizeX,

image->sizeY,

0, GL_RGB, GL_UNSIGNED_BYTE,

image->data);


Um resultado analógico pode ser conseguido utilizando a função gluBuild2Dmipmaps :


gluBuild2DMipmaps(GL_TEXTURE_2D, 3,

image->sizeX,

image->sizeY,

GL_RGB, GL_UNSIGNED_BYTE,

image->data);


Então temos que definir os parâmetros da textura :

glTexParameter[if](GLenum target, GLenum pname, GLenum param)


Primeiro parâmetro: GL_TEXTURE_1D ou GL_TEXTURE_2D.

Segundo : pname - é o parametro da textura a ser modificado.

Terceiro : é o valor a ser definido.

A função gluBuild2DMipmaps cria automaticamente todos niveis de detalização assim OpenGL consegue escolher níveis diferentes se a área do objeto não bateu com a área da textura. Ou estes níveis devem ser adicionados manualmente:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);


GL_NEAREST especifica que para modificação do tamanho da textura sera utilizado o algoritmo do vizinho mais proximo. Existe também GL_LINEAR.


Agora pode ser definido como a textura será colocada no objeto. Existem duas alternativas: quando a cor do objeto é avaliada ou não. Quando a cor do objeto é avaliada a cor resultante é calculada multiplicando a cor do objeto pela cor da textura (R_Obj*R_Tex, G_Obj*G_Tex, B_Obj*B_Tex). Se a cor for (0, 0, 0) a textura não será visível.

Multiplicação da cor do objeto pela cor da textura :


glTexEnv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE)


Somente textura :


glTexEnv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL)


Por definição o modo padrão é GL_MODULATE.


Ex. textura:

glEnable(GL_TEXTURE_2D);

glColor3d(1,1,1);

glBindTexture(GL_TEXTURE_2D, img_tex );

glBegin(GL_QUADS);

glTexCoord2d(0,0); glVertex3d(-5,-5, -0.1);

glTexCoord2d(0,1); glVertex3d(-5, 5, -0.1);

glTexCoord2d(1,1); glVertex3d( 5, 5, -0.1);

glTexCoord2d(1,0); glVertex3d( 5,-5, -0.1);

glEnd();

glBindTexture(GL_TEXTURE_2D, img_tex);

glBegin(GL_QUADS);

glTexCoord2d(0,0); glVertex2d(-4,-4);

glTexCoord2d(0,1); glVertex2d(-4, 4);

glTexCoord2d(1,1); glVertex2d( 4, 4);

glTexCoord2d(1,0); glVertex2d( 4,-4);

glEnd();

glDisable(GL_TEXTURE_2D);


A glTexCoord2d liga as coordenadas da textura com os vértices do quadrado. A textura possui as seguintes coordenadas : Esquerda em baixo (0, 0) e Direita em cima (1, 1).


Repetição das texturas


Para repetir a mesma textura na superfície do objeto deve ser definido o parâmetro GL_REPEAT para as coordenadas S e T da textura, ele esta habilitado por padrão. S é a coordenada horizontal e T vertical. Segundo parâmetro que pode ser definido é GL_CLAMP que garante que a textura não será multiplicada.

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);


A textura pode ser girada mudando a ligação com os vértices. O exemplo seguinte mostra como aplicar textura á um objeto esférico. A variável photo_image contém a imagem.


// definir textura

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

glTexImage2D(GL_TEXTURE_2D, 0, 3,

photo_image->sizeX,

photo_image->sizeY,

0, GL_RGB, GL_UNSIGNED_BYTE,

photo_image->data);


glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);


Para habilitar a aplicação da textura a um objeto tridimensional utilize :

guQuadricTexture(GL_TRUE) ou guQuadricTexture(GL_FALSE) para desabilitar, por padrão OpenGL desabilita esta opção.



GLUquadricObj *quadObj; // um objeto é criado


glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );


quadObj = gluNewQuadric();

gluQuadricTexture(quadObj, GL_TRUE);

gluQuadricDrawStyle(quadObj, GLU_FILL);

glColor3d(1,1,1);


glRotated(5, 0,1,0);


glPushMatrix();

glRotated(-90, 1,0,0);

gluSphere(quadObj, 3, 16, 16);

glPopMatrix();


gluDeleteQuadric(quadObj);

Iluminação

Na inicialização a iluminação esta desligada e é habilitada com o comando :

glEnable(GL_LIGHTING)

Agora podemos ligar luz do ambiente, no inicio ele é igual a (0.2, 0.2, 0.2, 1) podemos aumentar ate o maximo (1, 1, 1, 1) utilizando função glLightModel .


Ex. Luz Ambiental :


float ambient[4] = {0.5, 0.5, 0.5, 1};

...

glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);


Materiais diferentes refletem a luz de modos diferentes, para mudar o material :

glMaterialfv(GLenum face, GLenum pname, GLtype* params)


Primeiro parâmetro define a face a qual serão aplicadas as propriedades, pode possuir seguintes valores:

GL_BACK - face de traz

GL_FONT - face de frente

GL_FRONT_AND_BACK - as duas


Segundo parâmetro define a propriedade do material e possui as seguintes modificações:

GL_AMBIENT - luz do ambiente, dispercada

GL_DIFFUSE - tambem dispercada

GL_SPECULAR - luz refletida

GL_EMISSION - luz emitida

GL_SHININESS - quantidade da luz refletida

GL_AMBIENT_AND_DIFFUSE - ambos os luzes dispercados


O terceiro parâmetro define a cor da luz, que é definido por um vetor de 4 elementos: RGBA.


Ex. Luzes:

GLUquadricObj *quadObj;

GLfloat front_color[] = {0,1,0,1};

GLfloat back_color[] = {0,0,1,1};


quadObj = gluNewQuadric();


glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );


glMaterialfv(GL_FRONT, GL_DIFFUSE, front_color);

glMaterialfv(GL_BACK, GL_DIFFUSE, back_color);


glPushMatrix();

glRotated(110, -1,1,0);

gluCylinder(quadObj, 1, 0.5, 2, 10, 10);

glPopMatrix();


gluDeleteQuadric(quadObj);


Para o funcionamento o modo de iluminação das duas faces deve ser abilitado:

glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE)


Lampadas


As lampadas são definidas atraves da função glLight:

void glLight[if][v](GLenum light, GLenum pname, GLfloat param)


Primeiro argumento é o numero da lâmpada que é definido por GL_LIHGTi, onde i varia de 0 a 7, ou somando i a GL_LIHGT0, ex: GL_LIHGT0 + 2.


Segundo parâmetro pode ser :

GL_POSITION - posição de lâmpada

GL_SPOT_DIRECTION - é a direção

GL_DIFFUSE - define a cor da luz

GL_SPECULAR - define a luz refletida


Como terceiro parâmetro são dados vetores com os dados. Vetor de direção contem três coordenadas e a posição quatro, para o quarto parâmetro define valor maior de 0.

glLightfv(GL_LIGHT0, GL_POSITION, pos)

glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, dir)


Para ligar lâmpada use:

glEnable(GL_LIGHT0)


Ex. Lampadas :


float pos[4] = {3,3,3,1};

float color[4] = {1,1,1,1};

float sp[4] = {1,1,1,1};

float mat_specular[] = {1,1,1,1};


glEnable(GL_DEPTH_TEST);

glEnable(GL_COLOR_MATERIAL);

glEnable(GL_LIGHTING);

glEnable(GL_LIGHT3);

glEnable(GL_LIGHT5);

glEnable(GL_LIGHT6);

glLightfv(GL_LIGHT3, GL_SPECULAR, sp);

glLightfv(GL_LIGHT5, GL_SPECULAR, sp);

glLightfv(GL_LIGHT6, GL_SPECULAR, sp);


color[1]=color[2]=0;

glLightfv(GL_LIGHT3, GL_DIFFUSE, color);

color[0]=0;

color[1]=1;

glLightfv(GL_LIGHT5, GL_DIFFUSE, color);

color[1]=0;

color[2]=1;

glLightfv(GL_LIGHT6, GL_DIFFUSE, color);

glLightfv(GL_LIGHT3, GL_POSITION, pos);

pos[0] = -3;

glLightfv(GL_LIGHT5, GL_POSITION, pos);

pos[0]=0;pos[1]=-3;

glLightfv(GL_LIGHT6, GL_POSITION, pos);


glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);

glMaterialf(GL_FRONT, GL_SHININESS, 128.0);




Inicialização de OpenGL em diferentes linguagens de programação - Dicas rapidas.

C++ para Windows ou UNiX

Aqui tem bastante coisas para falar e mostrar, mas não seria exatamente o escopo do texto, so queria dar algumas dicas, os exemplos de códigos completos podem ser vistos em exemplos.

Passos necessários para programar:

1)

#include <GL/gl.h> // obrigatorio, a biblioteca

#include <GL/glu.h> // GL Utilities, bastante utilizada

#include <GL/glaux.h> // OpenGL Auxilary Library, facilita certas operacões

#include <GL/glut.h>

2)

Definir janela de contexto do windows (HWND)

3)

Inicializar OpenGL com luzes, ponto de vista, etc...

Delphi

As versões posteriores a 3 possuem uma unit opengl.pas que possui definições de constantes e funções das opengl32.dll e glu32.dll. Também existe um componete visual GLPanel com código aberto, que é muito simples e pequena mas muito útil, define uma janela de saída de OpenGL que pode ser visualmente colocada no projeto. Possui eventos como: OnGLDraw, OnGLInit e OnGLPrep onde o código OpenGL é escrito. Usando esta classe deverão ser adicionadas no uses as seguintes classes:

uses OpenGL, GLPanel;

Também o trabalho de definir a janela pode ser feito na mão usando somente opengl.pas.

C++ Builder

Para o C++Builder vale o mesmo do Delphi, pois é baseado na VCL da Delphi e também pode ser utilizada a mesma classe GLPanel.

JAVA

Para utilizar OpenGL com JAVA existem varias bibliotecas de classes e plugins para browsers que ligam as chamadas dos Applets com .dlls do opengl. Na verdade estes plugins não executarão OpenGL no nível da maquina de Java e sim no nível de .dlls de opengl por isso são um ponto possível de ataque da rede.

Uma das bibliotecas comercias Magician Library é bastante instável e possui um plugin de 2MB que liga com os dlls da Silicon Graphics.

Para utilizar esta biblioteca :

import com.hermetica.magician.*;

import com.hermetica.util3d.*;


Existe outra biblioteca free GL4Java, http://www.jausoft.com, com plugin pequeno de 200KB, esta biblioteca é muito mais estável do que a Magician Library.

Para utilizar esta biblioteca :

import gl4java.GLContext;

import gl4java.awt.GLCanvas;

import gl4java.awt.GLAnimCanvas;

Bibliografia

www.sgi.com

www.opengl.org

msdn.microsoft.com