Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

Apostila OPENGL PDF

Fazer download em pdf ou txt
Fazer download em pdf ou txt
Você está na página 1de 40

Introduo OpenGL

Professora Isabel Harb Manssour


01. Introduo
OpenGL definida como "um programa de interface para hardware grfico". Na
verdade, OpenGL uma biblioteca de rotinas grficas e de modelagem, bi (2D) e
tridimensional (3D), extremamente portvel e rpida. Usando OpenGL possvel criar
grficos 3D com uma qualidade visual prxima de um ray tracer. Entretanto, a maior
vantagem na sua utilizao a rapidez, uma vez que usa algoritmos cuidadosamente
desenvolvidos e otimizados pela Silicon Graphics, Inc., lder mundial em Computao
Grfica e Animao.
OpenGL no uma linguagem de programao, uma poderosa e sofisticada API
(Application Programming Interface) para criao de aplicaes grficas 2D e 3D. Seu
funcionamento semelhante ao de uma biblioteca C, uma vez que fornece uma srie de
funcionalidades. Normalmente se diz que um programa baseado em OpenGL ou
uma aplicao OpenGL, o que significa que ele escrito em alguma linguagem de
programao que faz chamadas a uma ou mais bibliotecas OpenGL.
As aplicaes OpenGL variam de ferramentas CAD a programas de modelagem usados
para criar personagens para o cinema, tal como um dinossauro. Alm do desenho de
primitivas grficas, tais como linhas e polgonos, OpenGL d suporte a iluminao,
colorizao, mapeamento de textura, transparncia, animao, entre muitos outros
efeitos especiais. Atualmente, OpenGL reconhecida e aceita como um padro API
para desenvolvimento de aplicaes grficas 3D em tempo real.
Ao invs de descrever a cena e como ela deve parecer, quando se est utilizando
OpenGL preciso apenas determinar os passos necessrios para alcanar a aparncia ou
efeito desejado. Estes passos envolvem chamadas a esta API portvel que inclui
aproximadamente 250 comandos e funes (200 comandos do core OpenGL e 50 da
GLU - OpenGL Utility Library). Por ser portvel, OpenGL no possui funes para
gerenciamento de janelas, interao com o usurio ou arquivos de entrada/sada. Cada
ambiente, como por exemplo o Microsoft Windows, possui suas prprias funes para
estes propsitos. No existe um formato de arquivo OpenGL para modelos ou
ambientes virtuais. OpenGL fornece um pequeno conjunto de primitivas grficas para
construo de modelos, tais como pontos, linhas e polgonos. A biblioteca GLU (que
faz parte da implementao OpenGL) que fornece vrias funes para modelagem,
tais como superfcies qudricas, e curvas e superfcies NURBS (Non Uniform Rational
B-Splines) [Woo 1999, Wright 2000].
A palavra pipeline usada para descrever um processo que pode ter dois ou mais passos
distintos. A figura 2.1 mostra uma verso simplificada do pipeline OpenGL. Como uma
aplicao faz chamadas s funes API OpenGL, os comandos so colocados em um
buffer de comandos. Este buffer preenchido com comandos, vrtices, dados de textura,
etc. Quando este buffer "esvaziado", os comandos e dados so passados para o
prximo estgio.

Figura 1.1 - Verso simplificada do pipeline OpenGL
Aps a etapa de aplicao das transformaes geomtricas e da iluminao, feita a
rasterizao, isto , gerada a imagem a partir dos dados geomtricos, de cor e textura.
A imagem final, ento, colocada no frame buffer, que a memria do dispositivo
grfico. Isto significa que a imagem exibida no monitor [Wright 2000].
02. Utilizao
Como uma API, OpenGL segue a conveno de chamada da linguagem C. Isto significa
que programas escritos em C podem facilmente chamar funes desta API, tanto porque
estas foram escritas em C, como porque fornecido um conjunto de funes C
intermedirias que chamam funes escritas em assembler ou outra linguagem [Wright
2000].
Apesar de OpenGL ser uma biblioteca de programao "padro", existem muitas
implementaes desta biblioteca, por exemplo, para Windows e para Linux. A
implementao utilizada no ambiente Linux a biblioteca Mesa. Tambm existem
implementaes para os compiladores Visual C++, Borland C++, Dev-C++, Delphi e
Visual Basic. Para obter as bibliotecas e a documentao de cada implementao acesse
http://www.opengl.org/.
No caso da implementao da Microsoft, o sistema operacional fornece os arquivos
opengl32.dll e glu32.dll, necessrios para execuo de programas OpenGL. Alm disso,
so fornecidas com suas ferramentas de programao, como por exemplo com o
Microsoft Visual C++, as bibliotecas opengl32.lib (OpenGL) e glu32.lib (GLU -
biblioteca de utilitrios OpenGL). Assim, para criar programas com ferramentas
Microsoft que usem OpenGL, tal como o MS Visual C++ 6.0, necessrio adicionar
estas duas bibliotecas lista de bibliotecas importadas. Prottipos para todas as funes,
tipos e macros OpenGL esto (por conveno) no header gl.h. Os prottipos da
biblioteca de funes utilitrias esto em um arquivo diferente, glu.h. Estes arquivos
normalmente esto localizados em uma pasta especial no path do include. O cdigo
abaixo mostra as incluses tpicas para um programa Windows que usa OpenGL
[Wright 2000]:
#include <windows.h>
#include <gl/gl.h>
#include <gl/glu.h>
Considerando o compilador MS Visual C++ 6.0, para utilizar a GLUT (veja a
explicao no captulo 05) necessrio fazer o download desta biblioteca (clique aqui
para fazer agora o download da GLUT para o MS Visual C++ 6.0), descompactar o
arquivo e copiar: os arquivos glut.dll e glut32.dll para a pasta System do Windows (ou
para a pasta System32 do Windows NT ou Windows 2000); os arquivos glut.lib e
glut32.lib para a mesma pasta do ambiente de programao onde esto as outras
bibliotecas (opengl32.lib e glu32.lib); e o arquivo glut.h para a mesma pasta do
ambiente de programao onde esto os arquivos gl.h e glu.h [Wright 2000]. Estes
arquivos normalmente esto compactados em um nico arquivo que pode ser obtido em
http://www.opengl.org/developers/documentation/glut/index.html.
Tambm necessrio criar um projeto no MS Visual C++ 6.0 da seguinte maneira:
no menu File selecione a opo New;
na janela aberta, selecione a opo Win32ConsoleApplication e coloque o nome do
projeto e o local onde ele ser gravado;
depois, inicialmente, pode ser selecionada a opo An empty project;
no menu Project selecione a opo Settings;
na janela aberta, selecione a guia Link e acrescente na caixa de texto Object/library
modules a(s) biblioteca(s) que devem ser linkadas com o programa, que so
opengl32.lib e glu32.lib, ou tambm a glut32.lib;
no final, adicione o arquivo fonte (.cpp) ao projeto, selecionando a opo Add to
Project/Files do menu Project.
Resumindo, para utilizar OpenGL e GLUT com ferramentas Microsoft, no caso o MS
Visual C++ 6.0, necessrio:
1. Fazer o download e instalar a biblioteca GLUT;
2. Criar um projeto para linkar as bibliotecas necessrias com o programa;
3. Incluir os headers adequados (<gl/gl.h> e <gl/glu.h>, ou <gl/glut.h>).
A implementao da OpenGL utilizada no ambiente Linux, a biblioteca Mesa, no
uma implementao "oficial", um projeto de software livre. A distribuio desta
biblioteca, cuja verso 5.0 possui suporte para o conjunto de instrues da OpenGL 1.4,
inclui makefiles e instrues para a sua correta utilizao.
Neste captulo esto descritos os passos necessrios para a utilizao de OpenGL com o
MS Visual C++ 6.0. Para verificar as instrues de como utilizar OpenGL com outros
compiladores, clique em um dos links abaixo.
Clique aqui para verificar as instrues sobre a utilizao de OpenGL com o Dev-
C++, que free.
Para utilizar OpenGL com o Borland C++ (verso free), necessrio fazer o
download do compilador e da biblioteca GLUT adequada. Para instrues de
como instalar corretamente clique aqui.
Um tutorial que explica como utilizar OpenGL com Delphi est disponvel em
http://www.inf.pucrs.br/~pinho/CG/Aulas/OpenGL/MustafaGL/MustafaGL.html.
O download do componente tambm pode ser feito neste endereo.
Clique aqui para acessar alguns links com instrues de como usar OpenGL com
Java.
OpenGL tambm pode ser usado com Visual Basic. Clique aqui para saber mais
informaes.

Utilizao do Dev-C++ com OpenGL
O Dev-C++ um ambiente de desenvolvimento integrado (IDE - Integrated
Development Environment) para a linguagem de programao C/C++. O compilador
Dev-C++, que d suporte a compiladores baseados no GCC (GNU Compiler
Collection), pode ser obtido em http://www.bloodshed.net/devcpp.html. Entretanto, para
facilitar, os arquivos tambm esto disponveis aqui. Para instalar o Dev-C++ 4.01 siga
as instrues a seguir.
1. Faa o download dos arquivos devcpp4.zip e devcpp401.zip;
2. Descompacte o arquivo devcpp4.zip em um diretrio temporrio (por exemplo,
c:\Temp);
3. Execute o Setup.exe (opo Typical, instala no diretrio C:\Dev-C++);
4. Descompacte o arquivo devcpp401.zip tambm em um diretrio temporrio;
5. Mova o arquivo DevCpp.exe para o diretrio onde o Dev-C++ foi instalado (por
exemplo, C:\Dev-C++) sobrepondo-o verso instalada anteriormente (este
novo executvel corrige algumas falhas da verso anterior).
O ambiente Windows j deve conter as DLLs necessrias para execuo dos programas
OpenGL. Neste caso, os arquivos opengl32.dll e glu32.dll devem estar na pasta System
(Windows98) ou System32 (Windows NT ou Windows 2000). Como o Dev-C++ d
suporte para programao com OpenGL, a pasta C:\Dev-C++\Include\GL contm os
arquivos gl.h, glaux.h e glu.h, e a pasta C:\Dev-C++\Lib contm os arquivos
opengl32.def, glaux.def e glu32.def. Neste caso, falta instalar apenas a biblioteca GLUT,
o que pode ser feito seguindo os passos descritos a seguir.
1. Faa o download do arquivo glut-devc.zip e descompacte o mesmo;
2. Mova o arquivo glut.h para a pasta GL do DevC++ (C:\Dev-C++\Include\GL);
3. Mova os arquivos glut32.def e libglut.a para a pasta Lib do DevC++ (C:\Dev-
C++\Lib);
4. Mova o arquivo glut32.dll para a mesma pasta onde se encontram os arquivos
opengl32.dll e glu32.dll;

03. Tipos de Dados
Para tornar o cdigo portvel, foram definidos tipos de dados prprios para OpenGL.
Estes tipos de dados so mapeados dos tipos de dados C comuns, que tambm podem
ser utilizados. Como os vrios compiladores e ambientes possuem regras diferentes para
determinar o tamanho das variveis C, usando os tipos OpenGL possvel isolar o
cdigo das aplicaes destas alteraes.
Na tabela 3.1, definida tanto por [Woo 1999], como por [Wright 2000], so
apresentados os tipos de dados OpenGL, os tipos de dados C correspondentes e o sufixo
apropriado. Estes sufixos so usados para especificar os tipos de dados para as
implementaes ISO C de OpenGL. Pode-se observar que todos os tipos comeam
"GL", e a maioria seguido pelo tipo de dado C correspondente.
Tipo de dado OpenGL
Representao
interna
Tipo de dado C
equivalente
Sufixo
GLbyte 8-bit integer signed char b
GLshort 16-bit integer short s
GLint, GLsizei 32-bit integer int ou long i
GLfloat, GLclampf 32-bit floating-point float f
GLdouble, GLclampd 64-bit floating-point double d
GLubyte, GLboolean 8-bit unsigned integer unsigned char ub
GLushort
16-bit unsigned
integer
unsigned short us
GLuint, GLenum,
GLbitfield
32-bit unsigned
integer
unsigned long ou unsigned
int
ui
Tabela 3.1 - Tipos de dados OpenGL
04. Convenes para os Nomes das Funes
Todos os nomes das funes OpenGL seguem uma conveno que indica de qual
biblioteca a funo faz parte e, freqentemente, quantos e que tipos de argumentos a
funo tem. Todas as funes possuem uma raiz que representa os comandos OpenGL
que correspondem s funes. Por exemplo, a funo glColor3f possui Color como raiz.
O prefixo gl representa a biblioteca gl, e o sufixo 3f significa que a funo possui trs
valores de ponto flutuante como parmetro. Resumindo, todas as funes OpenGL
possuem o seguinte formato:
< PrefixoBiblioteca> <ComandoRaiz> <ContadorArgumentosOpcional> <TipoArgumentosOpcional>
Variaes da funo do exemplo anterior, glColor3f, podem receber trs valores inteiros
como parmetro (glColor3i), trs doubles (glColor3d) e assim por diante. Algumas
verses da glColor tambm recebem quatro argumentos. Neste caso, um dos
argumentos usado para especificar o componente alfa (transparncia). Esta conveno
de adicionar o nmero e o tipo dos argumentos facilita a memorizao da lista de
argumentos.
05. Bibliotecas
Segundo [Woo 1999], OpenGL fornece um conjunto de comandos poderosos, mas
primitivos. Portanto, todas as rotinas de desenho de alto nvel devem ser elaboradas em
funo destes comandos. Sendo assim, foram desenvolvidas algumas bibliotecas para
simplificar a tarefa de programao. Estas bibliotecas so apresentadas a seguir.
GLU - OpenGL Utility Library: contm vrias rotinas que utilizam os
comandos OpenGL de baixo nvel para executar tarefas como, por exemplo,
definir as matrizes para projeo e orientao da visualizao, e fazer o
rendering de uma superfcie. Esta biblioteca fornecida como parte de cada
implementao de OpenGL, e suas funes usam o prefixo glu [Woo 1999].
GLUT - OpenGL Utility Toolkit: um toolkit independente de plataforma, que
inclui alguns elementos GUI (Graphical User Interface), tais como menus pop-
up e suporte para joystick. Esta biblioteca, escrita por Mark Kilgard, no
domnio pblico, mas free. O seu principal objetivo esconder a complexidade
das APIs dos diferentes sistemas de janelas. As funes desta biblioteca usam o
prefixo glut. interessante comentar que a GLUT substitiu a GLAUX, uma
biblioteca auxiliar OpenGL que havia sido criada para facilitar o aprendizado e a
elaborao de programas OpenGL independente do ambiente de programao
(Linux, Windows, etc.) [Woo 1999, Wright 2000].
GLX - OpenGL Extension to the X Window System: fornecido como um
"anexo" de OpenGL para mquinas que usam o X Window System. Funes
GLX usam o prefixo glX. Para Microsoft Windows 95/98/NT, as funes WGL
fornecem as janelas para a interface OpenGL. Todas as funes WGL usam o
prefixo wgl. Para IBM/OS2, a PGL a Presentation Manager para a interface
OpenGL, e suas funes usam o prefixo pgl. Para Apple, a AGL a interface
para sistemas que suportam OpenGL, e as funes AGL usam o prefixo agl
[Woo 1999].
FSG - Fahrenheit Scene Graph: um toolkit orientado objetos e baseado em
OpenGL, que fornece objetos e mtodos para a criao de aplicaes grficas
3D interativas. FSG, que foi escrito em C++ e separado de OpenGL, fornece
componentes de alto nvel para criao e edio de cenas 3D, e a habilidade de
trocar dados em outros formatos grficos [Woo 1999].

06. Mquina de Estados
OpenGL uma mquina de estados, conforme descrito por [Woo 1999]. possvel
coloc-la em vrios estados (ou modos) que no so alterados, a menos que uma funo
seja chamada para isto. Por exemplo, a cor corrente uma varivel de estado que pode
ser definida como branco. Todos os objetos, ento, so desenhados com a cor branca,
at o momento em que outra cor corrente especificada.
OpenGL mantm uma srie de variveis de estado, tais como estilo (ou padro) de uma
linha, posies e caractersticas das luzes, e propriedades do material dos objetos que
esto sendo desenhados. Muitas delas referem-se a modos que podem ser habilitados ou
desabilitados com os comandos glEnable() e glDisable().
Cada varivel de estado possui um valor inicial (default) que pode ser alterado. As
funes que utilizadas para saber o seu valor so: glGetBooleanv(), glGetDoublev(),
glGetFloatv, glGetIntegerv, glGetPointerv() ou glIsEnabled(). Dependendo do tipo de
dado, possvel saber qual destas funes deve ser usada [Woo 1999]. O trecho de
programa a seguir mostra um exemplo da utilizao destas funes.
int luz;
:
glEnable(GL_LIGHTING); //Habilita luz - GL_LIGHTING a
varivel de estado
:
luz = glIsEnabled(GL_LIGHTING); // retorna 1 (verdadeiro)
:
glDisable(GL_LIGHTING); //Desabilita luz
:
luz = glIsEnabled(GL_LIGHTING); // retorna 0 (falso)

07. Primeiro Programa
A biblioteca GLUT, descrita no captulo 5, utilizada nos exemplos deste tutorial que
comeam a ser apresentados a partir deste captulo. Portanto, estes exemplos podem ser
compilados em vrias plataformas sem a necessidade, por exemplo, de saber elaborar
programas com interface para ambiente Windows.
Para entender o funcionamento da GLUT, logo abaixo apresentado o menor programa
OpenGL possvel, implementado por [Wright 2000], que simplesmente abre uma janela
OpenGL.
// PrimeiroPrograma.c - Isabel H. Manssour
// Um programa OpenGL simples que abre uma janela GLUT
// Este cdigo est baseado no Simple.c, exemplo
// disponvel no livro "OpenGL SuperBible",
// 2nd Edition, de Richard S. e Wright Jr.

#include <gl/glut.h>

// Funo callback chamada para fazer o desenho
void Desenha(void)
{
//Limpa a janela de visualizao com a cor de fundo
especificada
glClear(GL_COLOR_BUFFER_BIT);

//Executa os comandos OpenGL
glFlush();
}

// Inicializa parmetros de rendering
void Inicializa (void)
{
// Define a cor de fundo da janela de visualizao como preta
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}

// Programa Principal
int main(void)
{
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutCreateWindow("Primeiro Programa");
glutDisplayFunc(Desenha);
Inicializa();
glutMainLoop();
}
Obs.: Clique nos links a seguir para fazer o download deste programa, incluindo o projeto e o
executvel, para os ambientes de programao Visual C++ e Dev-C++, respectivamente: Exemplo
Visual C++, Exemplo Dev-C++.
Este programa simples contm quatro funes da biblioteca GLUT (prefixo glut), e trs
funes OpenGL (prefixo gl). O contedo deste programa descrito detalhadamente a
seguir.
O arquivo glut.h contm os prottipos das funes utilizadas pelo programa.
Ele tambm inclui os headers gl.h e glu.h que definem, respectivamente, as
bibliotecas de funes OpenGL e GLU. O header #include requerido por todas
as aplicaes windows, mas a sua incluso opcional porque a verso WIN32
da GLUT j inclui o windows.h na glut.h. Entretanto, se o objetivo criar um
cdigo portvel, um bom hbito incluir este arquivo.
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); avisa a GLUT que tipo
de modo de exibio deve ser usado quando a janela criada. Neste caso os
argumentos indicam a criao de uma janela single-buffered (GLUT_SINGLE)
com o modo de cores RGBA (GLUT_RGB). O primeiro significa que todos os
comandos de desenho so feitos na janela de exibio. Uma alternativa uma
janela double-buffered, onde os comandos de desenho so executados para
criar uma cena fora da tela para depois rapidamente coloc-la na view (ou
janela de visualizao). Este mtodo geralmente utilizado para produzir
efeitos de animao. O modo de cores RGBA significa que as cores so
especificadas atravs do fornecimento de intensidades dos componentes red,
green e blue separadas.
glutCreateWindow("Primeiro Programa"); o comando da biblioteca GLUT
que cria a janela. Neste caso, criada uma janela com o nome "Primeiro
Programa". Este argumento corresponde a legenda para a barra de ttulo da
janela.
glutDisplayFunc(Desenha); estabelece a funo "Desenha" previamente
definida como a funo callback de exibio. Isto significa que a GLUT chama
a funo sempre que a janela precisar ser redesenhada. Esta chamada ocorre,
por exemplo, quando a janela redimensionada ou encoberta. nesta funo
que se deve colocar as chamadas de funes OpenGL, por exemplo, para
modelar e exibir um objeto.
Inicializa(); no uma funo OpenGL nem GLUT, apenas uma conveno
utilizada exemplos apresentados por [Wright 2000], nos quais este tutorial est
baseado. Nesta funo so feitas as inicializaes OpenGL que devem ser
executadas antes do rendering. Muitos estados OpenGL devem ser
determinados somente uma vez e no a cada vez que a funo Desenha
chamada.
glutMainLoop(); a funo que faz com que comece a execuo da mquina
de estados e processa todas as mensagens especficas do sistema operacional,
tais como teclas e botes do mouse pressionados, at que o programa termine.
glClearColor(0.0f, 0.0f, 1.0f, 1.0f); a funo que determina a cor utilizada
para limpar a janela. Seu prottipo : void glClearColor(GLclampf red,
GLclampf green, GLclampf blue, GLclampf alfa);. GLclampf definido como
um float na maioria das implementaes de OpenGL. O intervalo para cada
componente red, green, blue de 0 a 1. O componente alfa usado para efeitos
especiais, tal como transparncia.
glClear(GL_COLOR_BUFFER_BIT); "limpa" um buffer particular ou
combinaes de buffers, onde buffer uma rea de armazenamento para
informaes da imagem. Os componentes RGB so geralmente referenciados
como color buffer ou pixel buffer. Existem vrios tipos de buffer, mas por
enquanto s necessrio entender que o color buffer onde a imagem
armazenada internamente e limpar o buffer com glClear remove o desenho da
janela.
glFlush(); faz com que qualquer comando OpenGL no executado seja
executado. Neste primeiro exemplo tem apenas a funo glClear [Wright 2000].
08. Desenhando Primitivas
O exemplo de programa OpenGL do captulo anterior apenas abria uma janela vazia
com um fundo azul. Neste captulo apresentado um exemplo que mostra como fazer
um desenho, mover e redimensionar a janela [Wright 2000].
// Quadrado.c - Isabel H. Manssour
// Um programa OpenGL simples que desenha um
// quadrado em uma janela GLUT.
// Este cdigo est baseado no GLRect.c, exemplo
// disponvel no livro "OpenGL SuperBible",
// 2nd Edition, de Richard S. e Wright Jr.

#include <windows.h>
#include <gl/glut.h>

// Funo callback chamada para fazer o desenho
void Desenha(void)
{
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

// Limpa a janela de visualizao com a cor de fundo especificada
glClear(GL_COLOR_BUFFER_BIT);

// Especifica que a cor corrente vermelha
// R G B
glColor3f(1.0f, 0.0f, 0.0f);

// Desenha um quadrado preenchido com a cor corrente
glBegin(GL_QUADS);
glVertex2i(100,150);
glVertex2i(100,100);
// Especifica que a cor corrente azul
glColor3f(0.0f, 0.0f, 1.0f);
glVertex2i(150,100);
glVertex2i(150,150);
glEnd();

// Executa os comandos OpenGL
glFlush();
}

// Inicializa parmetros de rendering
void Inicializa (void)
{
// Define a cor de fundo da janela de visualizao como preta
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}

// Funo callback chamada quando o tamanho da janela alterado
void AlteraTamanhoJanela(GLsizei w, GLsizei h)
{
// Evita a divisao por zero
if(h == 0) h = 1;

// Especifica as dimenses da Viewport
glViewport(0, 0, w, h);

// Inicializa o sistema de coordenadas
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

// Estabelece a janela de seleo (left, right,
bottom, top)
if (w <= h)
gluOrtho2D (0.0f, 250.0f, 0.0f,
250.0f*h/w);
else
gluOrtho2D (0.0f, 250.0f*w/h, 0.0f,
250.0f);
}

// Programa Principal
int main(void)
{
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(400,350);
glutInitWindowPosition(10,10);
glutCreateWindow("Quadrado");
glutDisplayFunc(Desenha);
glutReshapeFunc(AlteraTamanhoJanela);
Inicializa();
glutMainLoop();
}
Obs.: Clique aqui para fazer o download deste programa.
Este programa, como mostra a figura 8.1, apenas exibe um quadrado azul e vermelho
numa janela com fundo preto. As novas funes utilizadas neste exemplo so descritas a
seguir.

Figura 8.1 - Sada do programa Quadrado.c
glutInitWindowSize(400,350); especifica o tamanho em pixels da janela GLUT.
glutInitWindowPosition(10,10); especifica a localizao inicial da janela
GLUT, que neste caso o canto superior esquerdo da tela do computador [Woo
1999].
glutReshapeFunc(AlteraTamanhoJanela); estabelece a funo
"AlteraTamanhoJanela" previamente definida como a funo callback de
alterao do tamanho da janela. Isto , sempre que a janela maximizada,
minimizada, etc., a funo "AlteraTamanhoJanela" executada para reinicializar
o sistema de coordenadas.
glColor3f(1.0f, 0.0f, 0.0f); determina a cor que ser usada para o desenho
(linhas e preenchimento). A seleo da cor feita da mesma maneira que na
funo glClearColor, sendo que no necessrio especificar o componente alfa,
cujo valor default 1.0 (completamente opaco).
glBegin(GL_QUADS); glEnd(); usada para desenhar um quadrado
preenchido a partir dos vrtices especificados entre glBegin e glEnd. O captulo
9 descreve a utilizao destas funes. OpenGL mapeia as coordenadas dos
vrtices para a posio atual da janela de visualizao na funo callback
AlteraTamanhoJanela.
Antes de descrever os parmetros e comandos da funo AlteraTamanhoJanela,
necessrio revisar alguns conceitos e especificaes. Em quase todos ambientes de
janelas, o usurio pode alterar o tamanho e dimenses da janela em qualquer momento.
Quando isto ocorre, o contedo da janela redesenhado levando em conta as novas
dimenses. Normalmente, o esperado que a escala do desenho seja alterada de
maneira que ele fique dentro da janela, independente do tamanho da janela de
visualizao ou do desenho [Foley 1990]. Assim, uma janela pequena ter o desenho
completo, mas pequeno, e uma janela grande ter o desenho completo e maior.
Apesar do exemplo mostrar um quadrado 2D, o desenho feito em um espao de
coordenadas 3D. A funo glBegin(GL_QUADS); glEnd(); desenha o quadrado no
plano xy em z=0. Portanto, necessrio determinar o tamanho da viewport (janela onde
ser feito o desenho) e do volume de visualizao (parte do universo da aplicao que
ser mapeada para viewport), pois estes parmetros influenciam o espao de
coordenadas e a escala do desenhos 2D e 3D na janela.
Sempre que o tamanho da janela alterado, a viewport e o volume de visualizao
devem ser redefinidos de acordo com as novas dimenses da janela. Assim, a aparncia
do desenho no alterada (por exemplo, um quadrado no vira um retngulo). Como a
alterao do tamanho da janela detectada e gerenciada de maneira diferente em cada
ambiente, a biblioteca GLUT fornece a funo glutReshapeFunc, descrita
anteriormente, que registra a funo callback que a GLUT ir chamar sempre que
houver esta alterao. A funo passada para a glutReshapeFunc deve ter o seguinte
prottipo: void AlteraTamanhoJanela(GLsizei w, GLsizei h);. O nome
"AlteraTamanhoJanela" foi escolhido porque descreve o que a funo faz. Os
parmetros recebidos sempre que o tamanho da janela alterado so a sua nova largura
e a sua nova altura, respectivamente. Esta informao usada para modificar o
mapeamento do sistema de coordenadas desejado para o sistema de coordenadas da tela
com a ajuda de duas funes uma OpenGL, glViewport, e uma da biblioteca GLU,
gluOrtho2D. Estas e outras funes chamadas na "AlteraTamanhoJanela", que definem
como a viewport especificada, so descritas a seguir.
glViewport(0, 0, w, h); recebe como parmetro a nova largura e altura da janela.
O prottipo desta funo : void glViewport(GLint x, GLint y, GLsizei width,
GLsizei height);. Seus parmetros especificam o canto inferior esquerdo da
viewport (x,y) dentro da janela, e a sua largura e altura em pixels (width e
height). Geralmente x e y so zero, mas possvel usar a viewport para
visualizar mais de uma cena em diferentes reas da janela. Em outras palavras, a
viewport define a rea dentro janela, em coordenadas de tela, que OpenGL pode
usar para fazer o desenho. O volume de visualizao , ento, mapeado para a
nova viewport.
gluOrtho2D (0.0f, 250.0f*w/h, 0.0f, 250.0f); usada para determinar que a
projeo ortogrfica (2D) ser utilizada para exibir na tela a imagem 2D que est
na janela de seleo definida atravs dos parmetros passados para esta funo.
O prottipo desta funo : void gluOrtho2D(GLdouble left, GLdouble right,
GLdouble bottom, GLdouble top);. No sistema de coordenadas cartesianas, os
valores left e right especificam os limites mnimo e mximo no eixo X;
analogamente, bottom e top especificam os limites mnimo e mximo no eixo Y.
glMatrixMode(GL_PROJECTION); e glLoadIdentity(); servem,
respectivamente, para avisar a OpenGL que todas as futuras alteraes, tais
como operaes de escala, rotao e translao, iro afetar a "cmera" (ou
observador), e para inicializar o sistema de coordenadas antes da execuo de
qualquer operao de manipulao de matrizes. Sem este comando, cada
chamada sucessiva de gluOrtho2D poderia resultar em uma corrupo do
volume de visualizao. Em outras palavras, a matriz de projeo onde o
volume de visualizao, que neste caso um plano, definido; a funo
gluOrtho2D no estabelece realmente o volume de visualizao utilizado para
fazer o recorte, apenas modifica o volume existente; ela multiplica a matriz que
descreve o volume de visualizao corrente pela matriz que descreve o novo
volume de visualizao, cujas coordenadas so recebidas por parmetro.
glMatrixMode(GL_MODELVIEW); avisa a OpenGL que todas as futuras
alteraes, tais como operaes de escala, rotao e translao, iro afetar os
modelos da cena, ou em outras palavras, o que desenhado. A funo
glLoadIdentity(); chamada em seguida, faz com que a matriz corrente seja
inicializada com a matriz identidade (nenhuma transformao acumulada)
[Wright 2000].
09. Linhas, Pontos e Polgonos
Com apenas algumas primitivas simples, tais como pontos, linhas e polgonos,
possvel criar estruturas complexas. Em outras palavras, objetos e cenas criadas com
OpenGL consistem em simples primitivas grficas que podem ser combinadas de vrias
maneiras [Wright 2000]. Portanto, OpenGL fornece ferramentas para desenhar pontos,
linhas e polgonos, que so formados por um ou mais vrtices. Neste caso, necessrio
passar uma lista de vrtices, o que pode ser feito entre duas chamadas de funes
OpenGL:
glBegin()
glEnd()
O argumento passado para glBegin() determina qual objeto ser desenhado. No exemplo
fornecido por [Hill 2000], para desenhar trs pontos pretos foi usada a seguinte
seqncia de comandos:
glBegin(GL_POINTS);
glColor3f(0.0f, 0.0f, 0.0f);
glVertex2i(100, 50);
glVertex2i(100, 130);
glVertex2i(150, 130);
glEnd();
Para desenhar outras primitivas, basta trocar GL_POINTS, que exibe um ponto para
cada chamada ao comando glVertex, por:
GL_LINES: exibe uma linha a cada dois comandos glVertex;
GL_LINE_STRIP: exibe uma seqncia de linhas conectando os pontos
definidos por glVertex;
GL_LINE_LOOP: exibe uma seqncia de linhas conectando os pontos
definidos por glVertex e ao final liga o primeiro como ltimo ponto;
GL_POLYGON: exibe um polgono convexo preenchido, definido por uma
seqncia de chamadas a glVertex;
GL_TRIANGLES: exibe um tringulo preenchido a cada trs pontos definidos
por glVertex;
GL_TRIANGLE_STRIP: exibe uma seqncia de tringulos baseados no trio de
vrtices v0, v1, v2, depois, v2, v1, v3, depois, v2, v3, v4 e assim por diante;
GL_TRIANGLE_FAN: exibe uma seqncia de tringulos conectados baseados
no trio de vrtices v0, v1, v2, depois, v0, v2, v3, depois, v0, v3, v4 e assim por
diante;
GL_QUADS: exibe um quadrado preenchido conectando cada quatro pontos
definidos por glVertex;
GL_QUAD_STRIP: exibe uma seqncia de quadrilteros conectados a cada
quatro vrtices; primeiro v0, v1, v3, v2, depois, v2, v3, v5, v4, depois, v4, v5,
v7, v6, e assim por diante [Hill 2000, Pinho 2000].
A funo glVertex2i pertence biblioteca GL e possui dois argumentos inteiros. De
maneira anloga, conforme explicado no captulo 4, tambm possvel passar valores
de ponto flutuante no lugar de inteiros, e trs coordenadas (x,y,z) no lugar de duas
usando, por exemplo, as seguintes chamadas s funes OpenGL:
glVertex2d(100.0, 50.0);
glVertex3f(50.0, 50.0, 50.0); Alm disso, para cada vrtice possvel definir uma cor
diferente. Neste caso, no desenho final feita uma "interpolao" das cores, como
mostra o exemplo da figura 8.1.
Para ilustrar a diferena na utilizao de algumas primitivas grficas o cdigo
apresentado no captulo 8 foi alterado da seguinte maneira: inicialmente, os parmetros
passados para a funo glutInitWindowSize foram alterados para (200,200), para
diminuir o tamanho da janela GLUT; depois, antes da funo glBegin(GL_QUADS)
foram chamadas as funes glPointSize(3) e glLineWidth(3); finalmente, GL_QUADS,
foi substitudo por GL_POINTS, GL_LINES, GL_LINE_STRIP e GL_LINE_LOOP,
gerando as imagens apresentadas na figura 9.1.

Figura 9.1 - Imagens geradas com a utilizao de (a) GL_POINTS, (b) GL_LINES,
(c) GL_LINE_STRIP e (d) GL_LINE_LOOP
10. Transformaes Geomtricas
As transformaes geomtricas so usadas para manipular um modelo, isto , atravs
delas possvel mover, rotacionar ou alterar a escala de um objeto. A aparncia final da
cena ou do objeto depende muito da ordem na qual estas transformaes so aplicadas.
A biblioteca grfica OpenGL capaz de executar transformaes de translao, escala e
rotao atravs de uma multiplicao de matrizes. A idia central destas transformaes
em OpenGL que elas podem ser combinadas em uma nica matriz, de tal maneira que
vrias transformaes geomtricas possam ser aplicadas atravs de uma nica operao.
Isto ocorre porque uma transformao geomtrica em OpenGL armazenada
internamente em uma matriz. A cada transformao que aplicada, esta matriz
alterada e usada para desenhar os objetos a partir daquele momento. A cada nova
alterao feita uma composio de matrizes. Para evitar este efeito "cumulativo",
necessrio utilizar as funes glPushMatrix() e glPopMatrix(), que salvam e restauram,
respectivamente, a matriz atual em uma pilha interna da OpenGL.
A translao feita atravs da funo glTranslatef(Tx, Ty, Tz), que pode receber trs
nmeros float ou double (glTranslated) como parmetro. Neste caso, a matriz atual
multiplicada por uma matriz de translao baseada nos valores dados.
A rotao feita atravs da funo glRotatef(ngulo, x, y, z), que pode receber quatro
nmeros float ou double (glRotated) como parmetro. Neste caso, a matriz atual
multiplicada por uma matriz de rotao de "ngulo" graus ao redor do eixo definido
pelo vetor "x,y,z" no sentido anti-horrio.
A escala feita atravs da funo glScalef(Ex, Ey, Ez), que pode receber trs nmeros
float ou double (glScaled) como parmetro. Neste caso, a matriz atual multiplicada
por uma matriz de escala baseada nos valores dados.
Logo abaixo a funo "Desenha" do exemplo do captulo 8 alterada para incluir as
transformaes geomtricas de translao e escala. As funes glPushMatrix( ) e
glPopMatrix( ) so usadas para que esta transformao no seja aplicada no modelo
cada vez que ele redesenhado [Wright 2000]. A figura 10.1 mostra como o quadrado
exibido aps a aplicao das transformaes especificadas.
void Desenha(void)
{
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0f, 0.0f, 0.0f);
glTranslatef(-100.0f, -30.0f, 0.0f);
glScalef(1.5f, 0.5f, 1.0f);

glBegin(GL_QUADS);
glVertex2i(100,150);
glVertex2i(100,100);
// Especifica que a cor corrente azul
glColor3f(0.0f, 0.0f, 1.0f);
glVertex2i(150,100);
glVertex2i(150,150);
glEnd();
glFlush();
}

Figura 10.1 - Sada do programa Quadrado.c aps a alterao da funo
"Desenha"

11. Animao com OpenGL e GLUT
Para exemplificar como fazer uma animao, como por exemplo mover ou girar objetos,
ser retomado o exemplo do captulo 8, que desenha um quadrado numa janela com
fundo preto. Agora, o quadrado ser movido numa direo at bater em uma das bordas
da janela e ento mudar de direo.
possvel criar um lao que continuamente altera as coordenadas do objeto antes de
chamar a funo "Desenha". Isto daria a impresso de que o quadrado se move na
janela. Porm, a biblioteca GLUT fornece a possibilidade de registrar uma funo
callback que torna mais fcil o processo de fazer uma simples animao. A funo
glutTimerFunc pega o nome da funo callback que deve ser chamada e o tempo que
ela deve esperar antes de chamar a funo. A seguir apresentado o cdigo do exemplo
de animao, e na seqncia as novas funes utilizadas so descritas [Wright 2000].
// Anima.c - Isabel H. Manssour
// Um programa OpenGL simples que mostra a animao
// de quadrado em uma janela GLUT.
// Este cdigo est baseado no Bounce.c, exemplo
// disponvel no livro "OpenGL SuperBible",
// 2nd Edition, de Richard S. e Wright Jr.

#include <windows.h>
#include <gl/glut.h>

// Tamanho e posio inicial do quadrado
GLfloat x1 = 100.0f;
GLfloat y1 = 150.0f;
GLsizei rsize = 50;

// Tamanho do incremento nas direes x e y
// (nmero de pixels para se mover a cada
// intervalo de tempo)
GLfloat xstep = 1.0f;
GLfloat ystep = 1.0f;

// Largura e altura da janela
GLfloat windowWidth;
GLfloat windowHeight;


// Funo callback chamada para fazer o desenho
void Desenha(void)
{
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

// Limpa a janela de visualizao com a cor de fundo especificada
glClear(GL_COLOR_BUFFER_BIT);

// Especifica que a cor corrente vermelha
// R G B
glColor3f(1.0f, 0.0f, 0.0f);

// Desenha um quadrado preenchido com a cor corrente
glBegin(GL_QUADS);
glVertex2i(x1,y1+rsize);
glVertex2i(x1,y1);
// Especifica que a cor corrente azul
glColor3f(0.0f, 0.0f, 1.0f);
glVertex2i(x1+rsize,y1);
glVertex2i(x1+rsize,y1+rsize);
glEnd();

// Executa os comandos OpenGL
glutSwapBuffers();
}

// Funo callback chamada pela GLUT a cada intervalo de tempo
// (a window no est sendo redimensionada ou movida)
void Timer(int value)
{
// Muda a direo quando chega na borda esquerda ou direita
if(x1 > windowWidth-rsize || x1 < 0)
xstep = -xstep;

// Muda a direo quando chega na borda superior ou inferior
if(y1 > windowHeight-rsize || y1 < 0)
ystep = -ystep;

// Verifica as bordas. Se a window for menor e o
// quadrado sair do volume de visualizao
if(x1 > windowWidth-rsize)
x1 = windowWidth-rsize-1;

if(y1 > windowHeight-rsize)
y1 = windowHeight-rsize-1;

// Move o quadrado
x1 += xstep;
y1 += ystep;

// Redesenha o quadrado com as novas coordenadas
glutPostRedisplay();
glutTimerFunc(33,Timer, 1);
}

// Inicializa parmetros de rendering
void Inicializa (void)
{
// Define a cor de fundo da janela de visualizao como preta
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}

// Funo callback chamada quando o tamanho da janela alterado
void AlteraTamanhoJanela(GLsizei w, GLsizei h)
{
// Evita a divisao por zero
if(h == 0) h = 1;

// Especifica as dimenses da Viewport
glViewport(0, 0, w, h);

// Inicializa o sistema de coordenadas
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

// Estabelece a janela de seleo (left, right, bottom, top)
if (w <= h) {
windowHeight = 250.0f*h/w;
windowWidth = 250.0f;
}
else {
windowWidth = 250.0f*w/h;
windowHeight = 250.0f;
}

gluOrtho2D(0.0f, windowWidth, 0.0f, windowHeight);
}

// Programa Principal
int main(void)
{
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(400,350);
glutInitWindowPosition(10,10);
glutCreateWindow("Anima");
glutDisplayFunc(Desenha);
glutReshapeFunc(AlteraTamanhoJanela);
glutTimerFunc(33, Timer, 1);
Inicializa();
glutMainLoop();
}
Obs.: Clique aqui para fazer o download deste programa.
glutTimerFunc(33, Timer, 1); estabelece a funo Timer previamente definida
como a funo callback de animao. Seu prottipo : void
glutTimerFunc(unsigned int msecs, void (*func)(int value), int value);. Esta
funo faz a GLUT esperar msecs milisegundos antes de chamar a funo func.
possvel passar um valor definido pelo usurio no parmetro value. Como esta
funo "disparada" apenas uma vez, para se ter uma animao contnua
necessrio reinicializar o timer novamente na funo Timer.
void Timer(int value) a funo chamada pela glutTimerFunc. No exemplo, as
variveis utilizadas para determinar a posio do retngulo so atualizadas nesta
funo.
Antes de prosseguir com a descrio das funes, necessrio explicar o funcionamento
do double-buffering, que uma das caractersticas mais importantes em qualquer pacote
grfico que est disponvel na GLUT. Double-buffering permite que um desenho seja
exibido na tela enquanto est sendo realizado o rendering em um offscreen buffer.
Ento, um comando de swap coloca a imagem na tela instantaneamente. Isto til,
principalmente, por dois motivos:
- Alguns desenhos complexos podem levar um certo tempo para serem feitos, e no
desejado que cada passo da composio da imagem seja visvel; ento, possvel
compor uma imagem e exibi-la somente depois de completa, de maneira que o usurio
nunca v uma imagem parcial, pois ela exibida somente quando est pronta.
- No caso de uma animao, cada quadro (ou frame) desenhado no offscreen buffer e
exibido (swapped) rapidamente depois de pronto.
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB), j explicada
anteriormente, foi usada para trocar o modo de exibio de GLUT_SINGLE
para GLUT_DOUBLE. Isto faz com que todo o rendering seja feito em um
offscreen buffer.
glutSwapBuffers(); usada no lugar da glFlush porque quando feita a troca
(ou swap) de buffers, realizada implicitamente uma operao de flush. Esta
funo continua fazendo o flush mesmo que o programa esteja sendo executado
no modo single-buffer, porm com uma qualidade bastante inferior [Wright
2000].
12. Gerenciamento de Eventos (teclado e mouse)
A biblioteca GLUT tambm contm funes para gerenciar eventos de entrada de
teclado e mouse. De acordo com [Woo 1999] e [Wright 2000], estas funes foram
descritas a seguir
glutKeyboardFunc
Estabelece a funo callback que chamada pela GLUT cada vez que uma tecla que
gera cdigo ASCII pressionada (por exemplo: a, b, A, b, 1, 2). Alm do valor ASCII
da tecla, a posio (x,y) do mouse quando a tecla foi pressionada tambm retornada.
Parmetros de entrada da funo callback: (unsigned char key, int x, int y)
glutSpecialFunc
Estabelece a funo callback que chamada pela GLUT cada vez que uma tecla que
gera cdigo no-ASCII pressionada, tais como Home, End, PgUp, PgDn, F1 e F2.
Alm da constante que identifica a tecla, a posio corrente (x,y) do mouse quando a
tecla foi pressionada tambm retornada. Parmetros de entrada da funo callback:
(unsigned char key, int x, int y). Os valores vlidos para o primeiro parmetro so:
GLUT_KEY_F1, GLUT_KEY_F2, GLUT_KEY_F3, GLUT_KEY_F4,
GLUT_KEY_F5, GLUT_KEY_F6, GLUT_KEY_F7, GLUT_KEY_F8,
GLUT_KEY_F9, GLUT_KEY_F10, GLUT_KEY_F11, GLUT_KEY_F12,
GLUT_KEY_LEFT, GLUT_KEY_UP, GLUT_KEY_RIGHT, GLUT_KEY_DOWN,
GLUT_KEY_PAGE_UP, GLUT_KEY_PAGE_DOWN, GLUT_KEY_HOME,
GLUT_KEY_END, GLUT_KEY_INSERT.
glutMouseFunc
Estabelece a funo callback que chamada pela GLUT cada vez que ocorre um evento
de mouse. Parmetros de entrada da funo callback: (int button, int state, int x, int y).
Trs valores so vlidos para o parmetro button: GLUT_LEFT_BUTTON,
GLUT_MIDDLE_BUTTON e GLUT_RIGHT_BUTTON. O parmetro state pode ser
GLUT_UP ou GLUT_DOWN. Os parmetros x e y indicam a localizao do mouse no
momento que o evento ocorreu.
O programa abaixo exemplifica a utilizao das funes acima especificadas. Neste
caso, foram implementadas as seguintes interaes: sempre que o usurio pressiona a
tecla "R" ou "r", o retngulo exibido com a cor vermelha; ao pressionar a tecla "G" ou
"g" o retngulo exibido com a cor verde; pressionar a tecla "B" ou "b" o retngulo
exibido com a cor azul; cada vez que o usurio clica com o boto esquerdo do mouse, o
tamanho do retngulo alterado (vai do centro da janela at a posio onde houve o
click do mouse); e cada vez que as teclas KEY_UP e KEY_DOWN so pressionadas
ocorre zoom-in e zoom-out, respectivamente.
// Interacao.c - Isabel H. Manssour
// Um programa OpenGL simples que desenha um quadrado em
// uma janela GLUT de acordo com interaes do usurio.
// Este cdigo est baseado nos exemplos
// disponveis no livro "OpenGL SuperBible",
// 2nd Edition, de Richard S. e Wright Jr.

#include <gl/glut.h>

GLfloat xf, yf, win;
GLint view_w, view_h;

// Funo callback chamada para fazer o desenho
void Desenha(void)
{
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glClear(GL_COLOR_BUFFER_BIT);
// Desenha um retngulo preenchido com a cor corrente
glBegin(GL_POLYGON);
glVertex2f(0.0f, 0.0f);
glVertex2f(xf, 0.0f);
glVertex2f(xf, yf);
glVertex2f(0.0f, yf);
glEnd();
glFlush();
}

// Inicializa parmetros de rendering
void Inicializa (void)
{
// Define a cor de fundo da janela de visualizao como preta
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
xf=50.0f;
yf=50.0f;
win=250.0f;
}

// Funo callback chamada quando o tamanho da janela alterado
void AlteraTamanhoJanela(GLsizei w, GLsizei h)
{
// Especifica as dimenses da Viewport
glViewport(0, 0, w, h);
view_w = w;
view_h = h;

// Inicializa o sistema de coordenadas
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D (-win, win, -win, win);
}

// Funo callback chamada para gerenciar eventos de teclado
void GerenciaTeclado(unsigned char key, int x, int y)
{
switch (key) {
case 'R':
case 'r':// muda a cor corrente para vermelho
glColor3f(1.0f, 0.0f, 0.0f);
break;
case 'G':
case 'g':// muda a cor corrente para verde
glColor3f(0.0f, 1.0f, 0.0f);
break;
case 'B':
case 'b':// muda a cor corrente para azul
glColor3f(0.0f, 0.0f, 1.0f);
break;
}
glutPostRedisplay();
}

// Funo callback chamada para gerenciar eventos do mouse
void GerenciaMouse(int button, int state, int x, int y)
{
if (button == GLUT_LEFT_BUTTON)
if (state == GLUT_DOWN) {
// Troca o tamanho do retngulo, que vai do centro
da
// janela at a posio onde o usurio clicou com o
mouse
xf = ( (2 * win * x) / view_w) - win;
yf = ( ( (2 * win) * (y-view_h) ) / -view_h) - win;
}
glutPostRedisplay();
}

// Funo callback chamada para gerenciar eventos do teclado
// para teclas especiais, tais como F1, PgDn e Home
void TeclasEspeciais(int key, int x, int y)
{
if(key == GLUT_KEY_UP) {
win -= 20;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D (-win, win, -win, win);
}
if(key == GLUT_KEY_DOWN) {
win += 20;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D (-win, win, -win, win);
}
glutPostRedisplay();
}

// Programa Principal
int main(void)
{
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(350,300);
glutInitWindowPosition(10,10);
glutCreateWindow("Exemplo de Interacao");
glutDisplayFunc(Desenha);
glutReshapeFunc(AlteraTamanhoJanela);
glutKeyboardFunc(GerenciaTeclado);
glutMouseFunc(GerenciaMouse);
glutSpecialFunc(TeclasEspeciais);
Inicializa();
glutMainLoop();
}
Obs.: Clique aqui para fazer o download deste programa.
13. Utilizando Menus e Exibindo Caracteres
A biblioteca GLUT tambm contm funes para gerenciar menus, exibir caracteres e
verificar a posio do mouse na janela em qualquer instante. As funes para realizar
estas tarefas esto descritas a seguir.
glutBitmapCharacter
Uma das fontes suportadas pela GLUT a bitmap, onde cada caracter corresponde a um
bitmap que gerado com a funo glBitmap. A funo glutBitmapCharacter exibe um
caracter deste tipo usando OpenGL. Os parmetros de entrada desta funo so: (void
*font, int character). O primeiro parmetro identifica a fonte que ser utilizada, e o
segundo o caracter. As fontes disponveis so: GLUT_BITMAP_8_BY_13,
GLUT_BITMAP_9_BY_15, GLUT_BITMAP_TIMES_ROMAN_10,
GLUT_BITMAP_TIMES_ROMAN_24, GLUT_BITMAP_HELVETICA_10,
GLUT_BITMAP_HELVETICA_12, GLUT_BITMAP_HELVETICA_18
glutMotionFunc
Estabelece a funo callback que chamada pela GLUT cada vez que o mouse
movido sobre a janela corrente enquanto um ou mais de seus botes esto pressionados.
Parmetros de entrada da funo callback: (int x, int y). Os parmetros x e y indicam a
posio do mouse em coordenadas da janela.
glutPassiveMotionFunc
Estabelece a funo callback que chamada pela GLUT cada vez que o mouse
movido sobre a janela corrente enquanto nenhum de seus botes est pressionado.
Parmetros de entrada da funo callback: (int x, int y). Os parmetros x e y indicam a
posio do mouse em coordenadas da janela.
glutCreateMenu
Cria um novo menu pop-up e estabelece a funo callback que ser chamada pela
GLUT quando uma de suas entradas for selecionada. Parmetros de entrada da funo
callback: (int value), onde value corresponde ao valor que identifica a entrada do menu
que foi selecionada.
glutAddMenuEntry
Adiciona uma entrada no final do menu corrente. Os parmetros de entrada desta funo
so: (char *name, int value), onde name o conjunto de caracteres que ser exibido
como uma entrada do menu, e value o valor que ser passado para a funo callback
caso esta entrada seja selecionada.
glutAddSubMenu
Adiciona um submenu no final do menu corrente. Os parmetros de entrada desta
funo so: (char *name, int menu), onde name o conjunto de caracteres que ser
exibido como uma entrada do menu, a partir da qual ser aberto o submenu, e menu o
identificador do submenu.
glutAttachMenu
Funo que "relaciona" um boto do mouse com o identificador do menu corrente. O
parmetro de entrada desta funo (int button), que corresponde ao identificador do
boto do mouse (GLUT_LEFT_BUTTON, GLUT_MIDDLE_BUTTON ou
GLUT_RIGHT_BUTTON).
Para exemplicar a utilizao das funes acima especificadas, observe o programa
abaixo. Neste exemplo foram implementadas as seguintes interaes: sempre que o
usurio movimenta o mouse, a sua posio (x,y) exibida no canto superior esquerdo da
janela, sendo tambm indicado se um dos botes est pressionado ou no; cada vez que
o usurio clica com o boto direito do mouse, exibido um menu onde possvel alterar
a cor e a primitiva grfica que est sendo desenhada; e cada vez que as teclas KEY_UP e
KEY_DOWN so pressionadas ocorre zoom-in e zoom-out, respectivamente.
// Menu.c - Isabel H. Manssour
// Um programa OpenGL simples que exemplifica
// como exibir textos e utilizar menus e funes
// callback para verificar a movimentao do
// mouse na janela GLUT.
// Este cdigo est baseado nos exemplos
// disponveis no livro "OpenGL SuperBible",
// 2nd Edition, de Richard S. e Wright Jr.

#include <gl/glut.h>
#include <string.h>
#include <stdio.h>

// Constantes
#define QUADRADO 1
#define TRIANGULO 2
#define LOSANGO 3

// Variveis
char texto[30];
GLfloat win, r, g, b;
GLint view_w, view_h, primitiva;

// Funo que desenha um quadrado
void DesenhaQuadrado(void)
{
glBegin(GL_QUADS);
glVertex2f(-25.0f, -25.0f);
glVertex2f(-25.0f, 25.0f);
glVertex2f(25.0f, 25.0f);
glVertex2f(25.0f, -25.0f);
glEnd();
}

// Funo que desenha um tringulo
void DesenhaTriangulo(void)
{
glBegin(GL_TRIANGLES);
glVertex2f(-25.0f, -25.0f);
glVertex2f(0.0f, 25.0f);
glVertex2f(25.0f, -25.0f);
glEnd();
}

// Funo que desenha um losango
void DesenhaLosango(void)
{
glBegin(GL_POLYGON);
glVertex2f(-25.0f, 0.0f);
glVertex2f(0.0f, 25.0f);
glVertex2f(25.0f, 0.0f);
glVertex2f(0.0f, -25.0f);
glEnd();
}

// Desenha um texto na janela GLUT
void DesenhaTexto(char *string)
{
glPushMatrix();
// Posio no universo onde o texto ser colocado
glRasterPos2f(-win,win-(win*0.08));
// Exibe caracter a caracter
while(*string)

glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_10,*string++);
glPopMatrix();
}

// Funo callback chamada para fazer o desenho
void Desenha(void)
{
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glClear(GL_COLOR_BUFFER_BIT);

// Define a cor corrente
glColor3f(r,g,b);

// Desenha uma primitiva
switch (primitiva) {
case QUADRADO: DesenhaQuadrado();
break;
case TRIANGULO: DesenhaTriangulo();
break;
case LOSANGO: DesenhaLosango();
break;
}

// Exibe a posio do mouse na janela
glColor3f(1.0f,1.0f,1.0f);
DesenhaTexto(texto);

glutSwapBuffers();
}

// Inicializa parmetros de rendering
void Inicializa (void)
{
// Define a cor de fundo da janela de visualizao como preta
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
win=150.0f;
primitiva = QUADRADO;
r = 0.0f;
g = 0.0f;
b = 1.0f;
strcpy(texto, "(0,0)");
}

// Funo callback chamada quando o tamanho da janela alterado
void AlteraTamanhoJanela(GLsizei w, GLsizei h)
{
// Especifica as dimenses da Viewport
glViewport(0, 0, w, h);
view_w = w;
view_h = h;

// Inicializa o sistema de coordenadas
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D (-win, win, -win, win);
}

// Funo callback chamada sempre que o mouse movimentado
// sobre a janela GLUT com um boto pressionado
void MoveMouseBotaoPressionado(int x, int y)
{
sprintf(texto, "Botao pressionado (%d,%d)", x, y);
glutPostRedisplay();
}

// Funo callback chamada sempre que o mouse movimentado
// sobre a janela GLUT
void MoveMouse(int x, int y)
{
sprintf(texto, "(%d,%d)", x, y);
glutPostRedisplay();
}

// Funo callback chamada para gerenciar eventos do teclado
// para teclas especiais, tais como F1, PgDn e Home
void TeclasEspeciais(int key, int x, int y)
{
if(key == GLUT_KEY_UP) {
win -= 10;
if (win < 10) win = 10;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D (-win, win, -win, win);
}
if(key == GLUT_KEY_DOWN) {
win += 10;
if (win > 500) win = 500;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D (-win, win, -win, win);
}
glutPostRedisplay();
}

// Gerenciamento do menu com as opes de cores
void MenuCor(int op)
{
switch(op) {
case 0:
r = 1.0f;
g = 0.0f;
b = 0.0f;
break;
case 1:
r = 0.0f;
g = 1.0f;
b = 0.0f;
break;
case 2:
r = 0.0f;
g = 0.0f;
b = 1.0f;
break;
}
glutPostRedisplay();
}

// Gerenciamento do menu com as opes de cores
void MenuPrimitiva(int op)
{
switch(op) {
case 0:
primitiva = QUADRADO;
break;
case 1:
primitiva = TRIANGULO;
break;
case 2:
primitiva = LOSANGO;
break;
}
glutPostRedisplay();
}

// Gerenciamento do menu principal
void MenuPrincipal(int op)
{
}

// Criacao do Menu
void CriaMenu()
{
int menu,submenu1,submenu2;

submenu1 = glutCreateMenu(MenuCor);
glutAddMenuEntry("Vermelho",0);
glutAddMenuEntry("Verde",1);
glutAddMenuEntry("Azul",2);

submenu2 = glutCreateMenu(MenuPrimitiva);
glutAddMenuEntry("Quadrado",0);
glutAddMenuEntry("Tringulo",1);
glutAddMenuEntry("Losango",2);

menu = glutCreateMenu(MenuPrincipal);
glutAddSubMenu("Cor",submenu1);
glutAddSubMenu("Primitivas",submenu2);

glutAttachMenu(GLUT_RIGHT_BUTTON);
}

// Funo callback chamada para gerenciar eventos do mouse
void GerenciaMouse(int button, int state, int x, int y)
{
if (button == GLUT_RIGHT_BUTTON)
if (state == GLUT_DOWN)
CriaMenu();

glutPostRedisplay();
}

// Programa Principal
int main(void)
{
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(350,300);
glutInitWindowPosition(10,10);
glutCreateWindow("Exemplo de Menu e Exibio de Caracteres");
glutDisplayFunc(Desenha);
glutReshapeFunc(AlteraTamanhoJanela);
glutMotionFunc(MoveMouseBotaoPressionado);
glutPassiveMotionFunc(MoveMouse);
glutMouseFunc(GerenciaMouse);
glutSpecialFunc(TeclasEspeciais);
Inicializa();
glutMainLoop();
}
Obs.: Clique aqui para fazer o download deste programa.

14. Programando em 3D
Os exemplos apresentados at aqui mostraram apenas desenhos 2D. Este captulo
descreve como trabalhar em 3D usando OpenGL. As bibliotecas GLU e GLUT possuem
uma srie de funes para desenhar primitivas 3D, tais como esferas, cones, cilindros e
teapot. Em 3D se assume que o processo utilizado para visualizar uma determinada cena
anlogo a tirar uma fotografia com uma mquina fotogrfica, o que inclui, segundo
[Woo 1999], os seguintes passos:
Arrumar o trip e posicionar a cmera para fotografar a cena - equivalente a
especificar as transformaes de visualizao (veja a funo gluLookAt descrita
mais abaixo);
Arrumar a cena para ser fotografada, incluindo ou excluindo objetos/pessoas -
equivalente etapa de modelagem (inclui as tranformaes geomtricas,
glTranslatef, glScalef, glRotatef, e o desenho dos objetos);
Escolher a lente da cmera ou ajustar o zoom - equivalente a especificar as
transformaes de projeo (veja a funo gluPerspective descrita mais abaixo);
Determinar o tamanho final da foto (maior ou menor) - equivalente a especificar
a viewport (funes glViewport e ChangeSize).
O exemplo abaixo exemplifica a utilizao das funes OpenGL para visualizao 3D.
// TeaPot3D.c - Isabel H. Manssour
// Um programa OpenGL que exemplifica a visualizao
// de objetos 3D.
// Este cdigo est baseado nos exemplos disponveis no livro
// "OpenGL SuperBible", 2nd Edition, de Richard S. e Wright Jr.

#include <gl/glut.h>

GLfloat angle, fAspect;

// Funo callback chamada para fazer o desenho
void Desenha(void)
{
glClear(GL_COLOR_BUFFER_BIT);

glColor3f(0.0f, 0.0f, 1.0f);

// Desenha o teapot com a cor corrente (wire-frame)
glutWireTeapot(50.0f);

// Executa os comandos OpenGL
glutSwapBuffers();
}

// Inicializa parmetros de rendering
void Inicializa (void)
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
angle=45;
}

// Funo usada para especificar o volume de visualizao
void EspecificaParametrosVisualizacao(void)
{
// Especifica sistema de coordenadas de projeo
glMatrixMode(GL_PROJECTION);
// Inicializa sistema de coordenadas de projeo
glLoadIdentity();

// Especifica a projeo perspectiva
gluPerspective(angle,fAspect,0.1,500);

// Especifica sistema de coordenadas do modelo
glMatrixMode(GL_MODELVIEW);
// Inicializa sistema de coordenadas do modelo
glLoadIdentity();

// Especifica posio do observador e do alvo
gluLookAt(0,80,200, 0,0,0, 0,1,0);
}

// Funo callback chamada quando o tamanho da janela alterado
void AlteraTamanhoJanela(GLsizei w, GLsizei h)
{
// Para previnir uma diviso por zero
if ( h == 0 ) h = 1;

// Especifica o tamanho da viewport
glViewport(0, 0, w, h);

// Calcula a correo de aspecto
fAspect = (GLfloat)w/(GLfloat)h;

EspecificaParametrosVisualizacao();
}

// Funo callback chamada para gerenciar eventos do mouse
void GerenciaMouse(int button, int state, int x, int y)
{
if (button == GLUT_LEFT_BUTTON)
if (state == GLUT_DOWN) { // Zoom-in
if (angle >= 10) angle -= 5;
}
if (button == GLUT_RIGHT_BUTTON)
if (state == GLUT_DOWN) { // Zoom-out
if (angle <= 130) angle += 5;
}
EspecificaParametrosVisualizacao();
glutPostRedisplay();
}

// Programa Principal
int main(void)
{
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(350,300);
glutCreateWindow("Visualizacao 3D");
glutDisplayFunc(Desenha);
glutReshapeFunc(AlteraTamanhoJanela);
glutMouseFunc(GerenciaMouse);
Inicializa();
glutMainLoop();
}
Obs.: Clique aqui para fazer o download deste programa.
O programa apresentado acima, como mostra a figura 14.1, apenas exibe um teapot (ou
bule de ch) azul, no formato wire-frame, numa janela com fundo preto. Ao posicionar
o mouse sobre a janela e clicar com o boto esquerdo e direito, possvel obter zoom-in
e zoom-out, respectivamente. As novas funes utilizadas neste exemplo so descritas a
seguir.

Figura 14.1 - Sada do programa TeaPot3D.c
gluPerspective(angle,fAspect,0.1,500); segundo [Wright 2000], esta funo
estabelece os parmetros da Projeo Perspectiva, atualizando a matriz de
projeo perspectiva. Seu prottipo : void gluPerspective( GLdouble fovy,
GLdouble aspect, GLdouble zNear, GLdouble zFar );. Descrio dos
parmetros: fovy o ngulo, em graus, na direo y (usada para determinar a
"altura" do volume de visualizao); aspect a razo de aspecto que determina a
rea de visualizao na direo x, e seu valor a razo em x (largura) e y
(altura); zNear, que sempre deve ter um valor positivo maior do que zero, a
distncia do observador at o plano de corte mais prximo (em z); zFar, que
tambm sempre tem um valor positivo maior do que zero, a distncia do
observador at o plano de corte mais afastado (em z). Esta funo sempre deve
ser definida ANTES da funo gluLookAt, e no modo GL_PROJECTION.
gluLookAt(0,80,200, 0,0,0, 0,1,0); define a transformao de visualizao.
Atravs dos seus argumentos possvel indicar a posio da cmera e para onde
ela est direcionada. Seu prottipo : void gluLookAt( GLdouble eyex, GLdouble
eyey, GLdouble eyez, GLdouble centerx, GLdouble centery, GLdouble centerz,
GLdouble upx, GLdouble upy, GLdouble upz );. Descrio dos parmetros: eyex,
eyey e eyez so usados para definir as coordenadas x, y e z, respectivamente, da
posio da cmera (ou observador); centerx, centery e centerz so usados para
definir as coordenadas x, y e z, respectivamente, da posio do alvo, isto , para
onde o observador est olhando (normalmente, o centro da cena); upx, upy e upz
so as coordenadas x, y e z, que estabelecem o vetor up (indica o "lado de cima"
de uma cena 3D) [Wright 2000].
glutWireTeapot(50.0f); usada para desenhar o wire-frame de um teapot (ou
bule de ch). Seu prottipo : glutWireTeapot(GLdoouble size);, onde o
parmetro size indica um raio aproximado do teapot. Uma esfera com este raio
ir "envolver" totalmente o modelo [Wright 2000].
Assim como o teapot, a biblioteca GLUT tambm possui funes para desenhar outros
objetos 3D. Estas funes esto listadas abaixo [Woo 1999]:
- void glutWireCube(GLdouble size);
- void glutWireSphere(GLdouble radius, GLint slices, GLint stacks);
- void glutWireCone(GLdouble radius, GLdouble height, GLint slices, GLint stacks);
- void glutWireTorus(GLdouble innerRadius, GLdouble outerRadius, GLint nsides,
GLint rings);
- void glutWireIcosahedron(void);
- void glutWireOctahedron(void);
- void glutWireTetrahedron(void);
- void glutWireDodecahedron(GLdouble radius);
Os parmetros slices e stacks que aparecem no prottipo de algumas funes,
significam, respectivamente, o nmero de subdivises em torno do eixo z (como se
fossem linhas longitudinais) e o nmero de subdivises ao longo do eixo z (como se
fossem linhas latitudinais). J rings e nsides correspondem, respectivamente, ao nmero
de sees que sero usadas para formar o torus, e ao nmero de subdivises para cada
seo. A figura 14.2 exibe um exemplo de um torus com rings=6 e nsides=20, e a figura
14.3 exibe um exemplo com rings=20 e nsides=20.

Figura 14.2 - Torus (rings=6, nsides=20)

Figura 14.3 - Torus (rings=20, nsides=20)
Todas estas funes tambm podem ser usadas para desenhar objetos slidos, ao invs
de exibir apenas o seu wire-frame. Para isto, basta substituir a substring Wire do nome
da funo por Solid. Por exemplo, se substituirmos a chamada funo
glutWireTeapot(50.0f) por glutSolidTeapot(50.0f) a imagem gerada a apresentada na
figura 14.4.

Figura 14.4 - Teapot gerado usando a funo glutSolidTeapot
Olhando a figura 14.4 possvel observar que a imagem gerada parece 2D. Isto ocorre
porque a verso Solid deve ser usada somente quando se est trabalhando com
iluminao (veja o prximo captulo deste tutorial).

15. Utilizando Luzes
Como possvel observar na figura 14.4, a imagem gerada no possui uma qualidade
satisfatria. Para adicionar um pouco de realismo nas imagens, necessrio, ento,
adicionar uma ou mais fontes de luz.
Inicialmente, preciso definir o modelo de colorizao que ser utilizado. OpenGL
fornece dois modelos: uma polgono preenchido pode ser desenhado com uma nica cor
(GL_FLAT), ou com uma variao de tonalidades (GL_SMOOTH, tambm chamado
de modelo de colorizao de Gouraud [Foley 1990]). A funo glShadeModel() usada
para especificar a tcnica de colorizao desejada.
Quando objetos 3D slidos so exibidos, importante desenhar os objetos que esto
mais prximos do observador (ou posio da cmera), eliminando objetos que ficam
"escondidos", ou "parcialmente escondidos", por estes. Sendo assim,algoritmos de
remoo de elementos escondidos foram desenvolvidos para determinar as linhas,
arestas, superfcies ou volumes que so visveis ou no para um observador localizado
em um ponto especfico no espao. A complexidade do problema dos elementos ocultos
resultou em um grande nmero de solues na Computao Grfica.
Conforme descrito por [Woo 1999], OpenGL possui um depth buffer que trabalha
atravs da associao de uma profundidade, ou distncia, do plano de visualizao
(geralmente o plano de corte mais prximo do observador) com cada pixel da window.
Inicialmente, os valores de profundidade so especificados para serem o maior possvel
atravs do comando glClear(GL_DEPTH_BUFFER_BIT). Entretanto, habilitando o
depth-buffering atravs dos comandos glutInitDisplayMode(GLUT_DEPTH | ...) e
glEnable(GL_DEPTH_TEST), antes de cada pixel ser desenhado feita uma
comparao com o valor de profundidade j armazenado. Se o valor de profundidade for
menor (est mais prximo) o pixel desenhado e o valor de profundidade atualizado.
Caso contrrio as informaes do pixel so desprezadas.
Em OpenGL a cor de uma fonte de luz caracterizada pela quantidade de vermelho (R),
verde (G) e azul (B) que ela emite, e o material de uma superfcie caracterizado pela
porcentagem dos componentes R, G e B que chegam e so refletidos em vrias direes.
No modelo de iluminao a luz em uma cena vem de vrias fontes de luz que podem ser
"ligadas" ou "desligadas" individualmente. A luz pode vir de uma direo ou posio
(por exemplo, uma lmpada) ou como resultado de vrias reflexes (luz ambiente - no
possvel determinar de onde ela vem, mas ela desaparece quando a fonte de luz
desligada).
No modelo de iluminao OpenGL a fonte de luz tem efeito somente quando existem
superfcies que absorvem e refletem luz. Assume-se que cada superfcie composta de
um material com vrias propriedades. O material pode emitir luz, refletir parte da luz
incidente em todas as direes, ou refletir uma parte da luz incidente numa nica
direo, tal com um espelho. Ento, conforme descrito por [Woo 1999], OpenGL
considera que a luz dividida em quatro componentes independentes (que so
colocadas juntas):
Ambiente: resultado da luz refletida no ambiente; uma luz que vem de todas
as direes;
Difusa: luz que vem de uma direo, atinge a superfcie e refletida em todas as
direes; assim, parece possuir o mesmo brilho independente de onde a cmera
est posicionada;
Especular: luz que vem de uma direo e tende a ser refletida numa nica
direo;
Emissiva: simula a luz que se origina de um objeto; a cor emissiva de uma
superfcie adiciona intensidade ao objeto, mas no afetada por qualquer fonte
de luz; ela tambm no introduz luz adicional da cena.
A cor do material de um objeto depende da porcentagem de luz vermelha, verde e azul
incidente que ele reflete. Assim como as luzes, o material possui cor ambiente, difusa e
especular diferentes, que determinam como ser a luz refletida. Isto combinado com
as propriedades das fontes de luz, de tal maneira que a reflexo ambiente e difusa
definem a cor do material. A especular geralmente cinza ou branca.
Os componentes de cor especificados para a luz possuem um significado diferente dos
componentes de cor especificados para os materiais. Para a luz, os nmeros
correspondem a uma porcentagem da intensidade total para cada cor. Se os valores R, G
e B para a cor da luz so 1, a luz branca com o maior brilho possvel. Se os valores so
0.5 a cor ainda branca, mas possui metade da intensidade, por isso parece cinza. Se
R=G=1 e B=0, a luz parece amarela.
Para os materiais, os nmeros correspondem s propores refletidas destas cores. Se
R=1, G=0.5 e B=0 para um material, este material reflete toda luz vermelha incidente,
metade da luz verde e nada da luz azul. Assim, simplificadamente, a luz que chega no
observador dada por (LR.MR, LG.MG, LB.MB), onde (LR, LG, LB) so os
componentes da luz e (MR, MG, MB) os componentes do material [Woo 1999].
O programa abaixo apresenta um exemplo completo da utilizao de luzes em OpenGL.
A imagem gerada, como mostra a figura 15.1, apenas exibe um teapot azul iluminado,
numa janela com fundo preto.
// Iluminacao.c - Isabel H. Manssour
// Um programa OpenGL que exemplifica a visualizao
// de objetos 3D com a insero de uma fonte de luz.
// Este cdigo est baseado nos exemplos disponveis no livro
// "OpenGL SuperBible", 2nd Edition, de Richard S. e Wright Jr.

#include <gl/glut.h>

GLfloat angle, fAspect;

// Funo callback chamada para fazer o desenho
void Desenha(void)
{
// Limpa a janela e o depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glColor3f(0.0f, 0.0f, 1.0f);

// Desenha o teapot com a cor corrente (solid)
glutSolidTeapot(50.0f);

glutSwapBuffers();
}

// Inicializa parmetros de rendering
void Inicializa (void)
{
GLfloat luzAmbiente[4]={0.2,0.2,0.2,1.0};
GLfloat luzDifusa[4]={0.7,0.7,0.7,1.0}; // "cor"
GLfloat luzEspecular[4]={1.0, 1.0, 1.0, 1.0};// "brilho"
GLfloat posicaoLuz[4]={0.0, 50.0, 50.0, 1.0};

// Capacidade de brilho do material
GLfloat especularidade[4]={1.0,1.0,1.0,1.0};
GLint especMaterial = 60;

// Especifica que a cor de fundo da janela ser preta
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

// Habilita o modelo de colorizao de Gouraud
glShadeModel(GL_SMOOTH);

// Define a refletncia do material
glMaterialfv(GL_FRONT,GL_SPECULAR, especularidade);
// Define a concentrao do brilho
glMateriali(GL_FRONT,GL_SHININESS,especMaterial);

// Ativa o uso da luz ambiente
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, luzAmbiente);

// Define os parmetros da luz de nmero 0
glLightfv(GL_LIGHT0, GL_AMBIENT, luzAmbiente);
glLightfv(GL_LIGHT0, GL_DIFFUSE, luzDifusa );
glLightfv(GL_LIGHT0, GL_SPECULAR, luzEspecular );
glLightfv(GL_LIGHT0, GL_POSITION, posicaoLuz );

// Habilita a definio da cor do material a partir da cor
corrente
glEnable(GL_COLOR_MATERIAL);
//Habilita o uso de iluminao
glEnable(GL_LIGHTING);
// Habilita a luz de nmero 0
glEnable(GL_LIGHT0);
// Habilita o depth-buffering
glEnable(GL_DEPTH_TEST);

angle=45;
}

// Funo usada para especificar o volume de visualizao
void EspecificaParametrosVisualizacao(void)
{
// Especifica sistema de coordenadas de projeo
glMatrixMode(GL_PROJECTION);
// Inicializa sistema de coordenadas de projeo
glLoadIdentity();

// Especifica a projeo perspectiva
gluPerspective(angle,fAspect,0.4,500);

// Especifica sistema de coordenadas do modelo
glMatrixMode(GL_MODELVIEW);
// Inicializa sistema de coordenadas do modelo
glLoadIdentity();

// Especifica posio do observador e do alvo
gluLookAt(0,80,200, 0,0,0, 0,1,0);
}

// Funo callback chamada quando o tamanho da janela alterado
void AlteraTamanhoJanela(GLsizei w, GLsizei h)
{
// Para previnir uma diviso por zero
if ( h == 0 ) h = 1;

// Especifica o tamanho da viewport
glViewport(0, 0, w, h);

// Calcula a correo de aspecto
fAspect = (GLfloat)w/(GLfloat)h;

EspecificaParametrosVisualizacao();
}

// Funo callback chamada para gerenciar eventos do mouse
void GerenciaMouse(int button, int state, int x, int y)
{
if (button == GLUT_LEFT_BUTTON)
if (state == GLUT_DOWN) { // Zoom-in
if (angle >= 10) angle -= 5;
}
if (button == GLUT_RIGHT_BUTTON)
if (state == GLUT_DOWN) { // Zoom-out
if (angle <= 130) angle += 5;
}
EspecificaParametrosVisualizacao();
glutPostRedisplay();
}

// Programa Principal
int main(void)
{
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(400,350);
glutCreateWindow("Visualizacao 3D");
glutDisplayFunc(Desenha);
glutReshapeFunc(AlteraTamanhoJanela);
glutMouseFunc(GerenciaMouse);
Inicializa();
glutMainLoop();
}
Obs.: Clique aqui para fazer o download deste programa.

Figura 15.1 - Sada do programa Iluminacao.c
As funes utilizadas neste exemplo, e que no foram descritas no captulo anterior, so
apresentadas a seguir segundo [Woo 1999] e [Wright 2000].
glShadeModel(GL_SMOOTH); estabelece o modelo de colorizao: GL_FLAT
(a cor no varia na primitiva que desenhada - um exemplo de primitiva o
tringulo); ou GL_SMOOTH (a cor de cada ponto da primitiva interpolada a
partir da cor calculada nos vrtices). Seu prottipo : void
glShadeModel(GLenum mode);. Descrio dos parmetros: mode especifica o
modelo de colorizao, sendo que o default GL_SMOOTH [Wright 2000].
glMaterialfv(GL_FRONT,GL_SPECULAR, especularidade); estabelece os
parmetros do material que sero usados pelo modelo de iluminao. Possui
algumas variaes cujos prottipos so:
glMaterialf(GLenum face, GLenum pname, GLfloat param);
glMateriali(GLenum face, GLenum pname, GLint param);
glMaterialfv(GLenum face, GLenum pname, const GLfloat *params);
glMaterialiv(GLenum face, GLenum pname, const GLint *params);
Descrio dos parmetros:
face determina se as propriedades do material dos polgonos que esto sendo
especificadas so front (GL_FRONT), back (GL_BACK) ou ambas
(GL_FRONT_AND_BACK);
pname para as duas primeiras variaes especifica o parmetro de um nico
valor que est sendo determinado (atualmente apenas GL_SHININESS possui
um nico valor como parmetro); para as duas ltimas variaes, que recebem
um vetor como parmetro, pode determinar as seguintes propriedades do
material: GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR, GL_EMISSION,
GL_SHININESS, GL_AMBIENT_AND_DIFFUSE ou
GL_COLOR_INDEXES;
param (GLfloat ou GLint) especifica o valor que ser atribudo para o parmetro
determinado por pname (neste caso, GL_SHININESS);
params (GLfloat* ou GLint*) um vetor de nmeros reais ou inteiros que contm
as componentes da propriedade que est sendo espeficada;
Atravs desta funo possvel determinar as propriedades de refletncia do
material dos polgonos. As propriedades GL_AMBIENT, GL_DIFFUSE e
GL_SPECULAR afetam a maneira na qual as componentes de luz incidente so
refletidas. GL_EMISSION usado para materiais que possuem "luz prpria".
GL_SHININESS pode variar de 0 a 128 (quanto maior o valor, maior a rea de
highlight especular na superfcie). GL_COLOR_INDEXES usado para as
propriedades de refletncia do material no modo de ndice de cores [Wright
2000].
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, luzAmbiente); estabelece
os parmetros do modelo de iluminao usado por OpenGL. possvel
especificar um, ou todos os trs modelos:
- GL_LIGHT_MODEL_AMBIENT usado para especificar a luz ambiente
default para uma cena, que tem um valor RGBA default de (0.2, 0.2, 0.2, 1.0);
- GL_LIGHT_MODEL_TWO_SIDE usado para indicar se ambos os lados de
um polgono so iluminados (por default apenas o lado frontal iluminado);
- GL_LIGHT_MODEL_LOCAL_VIEWER modifica o clculo dos ngulos de
reflexo especular;
Possui algumas variaes cujos prottipos so:
glLightModelf(GLenum pname, GLfloat param);
glLightModeli(GLenum pname, GLint param);
glLightModelfv(GLenum pname, const GLfloat *params);
glLightModeliv(GLenum pname, const GLint *params);
Descrio dos parmetros:
pname especifica um parmetro do modelo de iluminao:
GL_LIGHT_MODEL_AMBIENT, GL_LIGHT_MODEL_LOCAL_VIEWER
ou GL_LIGHT_MODEL_TWO_SIDE;
param (GLfloat ou GLint) para GL_LIGHT_MODEL_LOCAL_VIEWER um
valor 0.0 indica que os ngulos da componente especular tomam a direo de
visualizao como sendo paralela ao eixo z, e qualquer outro valor indica que a
visualizao ocorre a partir da origem do sistema de referncia da cmera; para
GL_LIGHT_MODEL_TWO_SIDE um valor 0.0 indica que somente os
polgonos frontais so includos nos clculos de iluminao, e qualquer outro
valor indica que todos os polgonos so includos nos clculos de iluminao;
params (GLfloat* ou GLint*) para GL_LIGHT_MODEL_AMBIENT ou
GL_LIGHT_MODEL_LOCAL_VIEWER, aponta para um vetor de nmeros
inteiros ou reais; para GL_LIGHT_MODEL_AMBIENT o contedo do vetor
indica os valores das componentes RGBA da luz ambiente [Wright 2000].
glLightfv(GL_LIGHT0, GL_AMBIENT, luzAmbiente); estabelece os
parmetros da fonte de luz para uma das oito fontes de luz disponveis. Possui
algumas variaes cujos prottipos so:
glLightf(GLenum light, GLenum pname, GLfloat param);
glLighti(GLenum light, GLenum pname, GLint param);
glLightfv(GLenum light, GLenum pname, const GLfloat *params);
glLightiv(GLenum light, GLenum pname, const GLint *params);
As duas primeiras variaes requerem apenas um nico valor para determinar
uma das seguintes propriedades: GL_SPOT_EXPONENT,
GL_SPOT_CUTOFF, GL_CONSTANT_ATTENUATION,
GL_LINEAR_ATTENUATION e GL_QUADRATIC_ATTENUATION. As
duas ltimas variaes so usadas para parmetros de luz que requerem um vetor
com mltiplos valores (GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR,
GL_POSITION e GL_SPOT_DIRECTION).
Descrio dos parmetros:
light especifica qual fonte de luz est sendo alterada (varia de 0 a
GL_MAX_LIGHTS); valores constantes de luz so enumerados de
GL_LIGHT0 a GL_LIGHT7
pname especifica qual parmetro de luz est sendo determinado pela chamada
desta funo (GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR,
GL_POSITION, GL_SPOT_DIRECTION, GL_SPOT_EXPONENT,
GL_SPOT_CUTOFF. GL_CONSTANT_ATTENUATION,
GL_LINEAR_ATTENUATION, GL_QUADRATIC_ATTENUATION);
param (GLfloat ou GLint) para parmetros que so especificados por um nico
valor (param); estes parmetros, vlidos somente para spotlights, so
GL_SPOT_EXPONENT, GL_SPOT_CUTOFF,
GL_CONSTANT_ATTENUATION, GL_LINEAR_ATTENUATION e
GL_QUADRATIC_ATTENUATION.
params (GLfloat* ou GLint*) um vetor de valores que descrevem os parmetros
que esto sendo especificados [Wright 2000].
glEnable(GL_COLOR_MATERIAL); conforme j explicado no captulo 6, a
funo glEnable usada para habilitar uma varivel de estado OpenGL. Neste
caso, esto sendo habilitadas: GL_COLOR_MATERIAL (atribui a cor para o
material a partir da cor corrente), GL_DEPTH_TEST (controla as comparaes
de profundidade e atualiza o depth buffer), GL_LIGHTING (habilita a
iluminao) e GL_LIGHT0 (habilita a luz de nmero 0) [Woo 1999].
glutSwapBuffers(); e glutInitDisplayMode(GLUT_DOUBLE...); j explicadas
anteriormente, so usadas para evitar que a imagem fique "piscando" a cada
interao (por exemplo, quando se faz zoom-in e zoom-out).
Tambm possvel eliminar o "brilho" do objeto, como se o material fosse opaco. Neste
caso, basta eliminar a componente especular removendo as seguintes linhas do cdigo
fonte:
GLfloat especularidade[4]={1.0,1.0,1.0,1.0};
GLint especMaterial = 60;
glMaterialfv(GL_FRONT,GL_SPECULAR, especularidade);
glMateriali(GL_FRONT,GL_SHININESS,especMaterial);
glLightfv(GL_LIGHT0, GL_SPECULAR, luzEspecular );

16. Malha de Polgonos
Como a maioria dos objetos em Computao Grfica representada atravs de uma
malha de polgonos, logo abaixo apresentada uma funo que exemplifica o uso de
uma malha de polgonos para fazer o desenho de um cubo.
void Desenha(void)
{

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(0.0f, 0.0f, 1.0f);

// Desenha um cubo

glBegin(GL_QUADS); // Face posterior
glNormal3f(0.0, 0.0, 1.0); // Normal da face
glVertex3f(40.0, 40.0, 40.0);
glVertex3f(-40.0, 40.0, 40.0);
glVertex3f(-40.0, -40.0, 40.0);
glVertex3f(40.0, -40.0, 40.0);
glEnd();


glBegin(GL_QUADS); // Face frontal
glNormal3f(0.0, 0.0, -1.0); // Normal da face
glVertex3f(40.0, 40.0, -40.0);
glVertex3f(40.0, -40.0, -40.0);
glVertex3f(-40.0, -40.0, -40.0);
glVertex3f(-40.0, 40.0, -40.0);
glEnd();
glBegin(GL_QUADS); // Face lateral esquerda
glNormal3f(-1.0, 0.0, 0.0); // Normal da face
glVertex3f(-40.0, 40.0, 40.0);
glVertex3f(-40.0, 40.0, -40.0);
glVertex3f(-40.0, -40.0, -40.0);
glVertex3f(-40.0, -40.0, 40.0);
glEnd();
glBegin(GL_QUADS); // Face lateral direita
glNormal3f(1.0, 0.0, 0.0); // Normal da face
glVertex3f(40.0, 40.0, 40.0);
glVertex3f(40.0, -40.0, 40.0);
glVertex3f(40.0, -40.0, -40.0);
glVertex3f(40.0, 40.0, -40.0);
glEnd();
glBegin(GL_QUADS); // Face superior
glNormal3f(0.0, 1.0, 0.0); // Normal da face
glVertex3f(-40.0, 40.0, -40.0);
glVertex3f(-40.0, 40.0, 40.0);
glVertex3f(40.0, 40.0, 40.0);
glVertex3f(40.0, 40.0, -40.0);
glEnd();
glBegin(GL_QUADS); // Face inferior
glNormal3f(0.0, -1.0, 0.0); // Normal da face
glVertex3f(-40.0, -40.0, -40.0);
glVertex3f(40.0, -40.0, -40.0);
glVertex3f(40.0, -40.0, 40.0);
glVertex3f(-40.0, -40.0, 40.0);
glEnd();
glutSwapBuffers();
}
Como a nica alterao em relao ao exemplo do captulo anterior o desenho do
cubo, s a funo Desenha ser descrita aqui.
Quando se trabalha com uma malha, normalmente so passadas como argumento para a
funo glBegin() as primitivas GL_QUADS, GL_POLYGON e GL_TRIANGLES
(captulo 9). GL_TRIANGLE_STRIP e GL_QUAD_STRIP tambm podem ser usadas,
desde que se tenha certeza de que os vrtices e faces esto ordenados da maneira
correta.
Conforme se observa no cdigo acima, necessrio informar o vetor normal normal de
cada face, pois OpenGL usa esta informao para calcular a cor de cada face de acordo
com os parmetros de iluminao. A funo usada para especificar o vetor normal
glNormal3f, e os seus parmetros so as componentes x, y e z do vetor normal,
respectivamente.

Você também pode gostar