Opengl - Um Tutorial: Resumo
Opengl - Um Tutorial: Resumo
Opengl - Um Tutorial: Resumo
Luis Valente
Instituto de Computao - Universidade Federal Fluminense
[email protected]
Dezembro, 2004
Resumo
OpenGL uma biblioteca para modelagem e visualizao tridimensional em tempo real,
que est disponvel para vrios sistemas operacionais. Desenvolvida inicialmente pela
Silicon Graphics em 1992, hoje um dos padres da indstria.
Este trabalho uma introduo a conceitos bsicos do OpenGL, desde a configurao
inicial at mapeamento por textura. Assume-se que o leitor possui conhecimento de
linguagem C e saiba utilizar algum compilador ou ambiente de desenvolvimento C
(como o GCC ou Microsoft Visual C++). O ambiente de desenvolvimento usado como
referncia o Microsoft Visual C++, mas os conceitos apresentados so independentes
do ambiente e sistema operacional.
Abstract
OpenGL is an API applied in 3D modeling and real-time 3D visualization, which is
available for many operating systems. The development of OpenGL was started by
Silicon Graphics in 1992, and today it's considered an industry standard.
This work introduces basic OpenGL concepts, from instalation to texture mapping. It's
assumed that the reader has knowledged of the C language and is comfortable in using
C compilers and/or development environments for C (like GCC or Microsoft Visual
C++). Microsoft Visual C++ was adopted as the reference development environment in
this work, although the concepts presented here are compiler and operating system
independent.
Luis Valente
1. Introduo
OpenGL (Open Graphics Library) uma biblioteca (API1) para Computao Grfica 3D e 2D
que foi desenvolvida inicialmente por Silicon Graphics Inc. (SGI). Atualmente, adminstrada pela
ARB (Architecture Review Board)2. A ARB uma entidade que congrega vrios representantes da
indstria, como SGI, Intel, NVIDIA e Sun Microsystems.
A API do OpenGL oferece algumas primitivas bsicas (como pontos, linhas, tringulos,
quadrilteros e polgonos), operaes para manipulao do sistema de coordenadas e operaes com
matrizes (translao, rotao e escala) e efeitos como mapeamento de textura, entre outros
comandos.
OpenGL foi projetado para ser utilizado em vrias plataformas e sistemas operacionais, como
Mac OS, OS/2, Unix, Windows, Linux, OPENStep e BeOS. Pode ser utilizado em diversos
ambientes de desenvolvimento de linguagens de programao como Delphi, Visual Basic, C/C++,
Java, Fortran e Python, entre outros. Devido a esse propsito, existem vrias funcionalidades que
no esto disponveis em OpenGL, porque so dependentes da plataforma nativa. Entre essas
funcionalidades, encontram-se janelas (e interface grfica), fontes para texto e comandos para
interao com o usurio (como processamento de eventos do teclado e mouse).
A verso atual do OpenGL 1.53. A biblioteca possui dois componentes principais:
GLU: uma biblioteca utilitria, que possui funes diversas para quadrics, NURBS e
matrizes, entre outras.
Uma caracterstica importante de OpenGL que o OpenGL uma API de modo imediato
(immediate mode). Em APIs de modo imediato, os comandos submetidos alteram o estado do
hardware grfico assim que so recebidos. O estado do hardware grfico representa um tipo de
configurao que est em uso no momento, e como essa configurao aplicada internamente pelo
hardware. Por exemplo, uma aplicao pode utilizar iluminao em uma cena. Desta forma, diz-se
que o estado de iluminao est ligado. Quando esse estado ligado, o hardware configurado
internamente para realizar uma srie de operaes que tm a ver com essa funcionalidade.
2. Usando OpenGL
No sistema operacional Windows, o OpenGL j est pronto para uso (em modo simulado, por
software, pelo menos). A implementao da biblioteca est contida em arquivos DLL (opengl32.dll
e glu32.dll) no Windows e em arquivos .so (libGL.so, libGLU.so) no Linux.
Para utilizar plenamente os recursos oferecidos pelo hardware com o OpenGL, preciso
instalar o driver especfico da placa grfica. Esses drivers podem ser encontrados nos sites dos
fabricantes dos chipsets da placa grfica (como NVIDIA4 ou ATI5). No Linux, uma das solues
instalar a Mesa3D6, que uma implementao no-oficial da API do OpenGL. Alguns fabricantes
(como a NVIDIA) oferecem drivers nativos para Linux, que podem ser obtidos no site da empresa.
1
2
3
4
5
6
Luis Valente
2.3. GCC
Para usar o OpenGL com o GCC, preciso incluir os seguintes arquivos nos programas:
#include <GL/gl.h>
#include <GL/glu.h>
O arquivo gl.h possui as funes principais do OpenGL, enquanto o glu.h possui as funes da
biblioteca utilitria.
Os arquivos de ligao com as DLLs podem ser especificados atravs dos parmetros
-lopengl32 e -lglu32 (caso se use a GLU), tanto em Windows quanto em Linux.
2.4. Convenes
Todos os comandos do OpenGL seguem uma conveno, que pode ser observada na Figura 2.1.
Luis Valente
O tipo dos argumentos. No exemplo, o tipo dos argumentos ponto flutuante. Dessa
forma, a funo aceita 3 nmeros de ponto flutuante.
Tipo de dado
Tipo correspondente
na linguagem C
inteiro 8 bits
GLbyte
signed char
inteiro 16 bits
GLshort
short
inteiro 32 bits
GLint, GLsizei
int, long
GLfloat, GLclampf
float
GLdouble, GLclampd
double
ub
GLubyte, GLboolean
unsigned char
us
GLushort
unsigned short
ui
Luis Valente
comum que existam diversas variaes de comandos, que diferem entre si pelo tipo e nmero
de argumentos aceitos. Exemplos:
glColor3f (1.0f, 1.0f, 1.0f);
GLfloat color [3];
glColor3fv (color);
3. Sistemas de janelas
Devido portabilidade do OpenGL, a API no possui funes para lidar com sistemas de
janelas, cujas caractersticas dependem do sistema operacional usado. Esse o primeiro problema a
ser enfrentado pelo desenvolvedor, j que para usar o OpenGL preciso abrir uma janela.
Eventualmente, a aplicao ter que interagir com o usurio, quando ser necessrio tratar eventos
relacionados com o teclado e o mouse.
O desenvolvedor possui duas opes:
Usar a API especfica do sistema operacional. Essa opo torna a aplicao dependente do
sistema operacional. Entretanto, possvel utilizar caractersticas avanadas (e/ou otimizadas)
relacionadas ao sistema sistemas. Obviamente, ser preciso aprender a utilizar a API do
sistema operacional escolhido.
Usar algum toolkit ou biblioteca que oferea uma abstrao para o sistema de janelas.
Existem vrios exemplos de ferramentas desse tipo disponveis na internet. Muitas delas esto
disponveis para vrios sistemas operacionais e possuem o cdigo aberto. Suas APIs
geralmente so bem mais fceis de aprender (e menos complexas) do que as APIs de sistemas
operacionais especficos. Entretanto, por tentar oferecer caractersticas que sejam comuns a
vrios sistemas operacionais, podem ter algumas limitaes em termos de funcionalidades.
7 http://freeglut.sourceforge.net/
5
Luis Valente
3.1.1. Compilao
A seguir, preciso compilar o cdigo fonte para gerar as DLLs e arquivos .lib. Para isso,
descompacte o arquivo para um diretrio qualquer (ex: c:\freeglut). Depois, basta abrir o arquivo do
workspace (freeglut.dsw). Esse arquivo de projeto foi construdo para ser usado com o Visual C++
6, mas pode ser utilizado pelo Visual C++ .NET sem problemas.
Nesse workspace, constam dois projetos: o freeglut_static e o freeglut (que est selecionado por
padro). O primeiro usada para se construir uma biblioteca esttica e o outro para se construir a
DLL. Neste trabalho, ser usada a verso em DLL.
Para compilar o projeto, preciso acessar o menu Build e depois Build freeglut.dll, caso o
compilador seja o Visual C++ 6. Se for o Visual C++ .NET, os menus so Build e depois Build
freeglut.
Essas instrues geram a verso debug da DLL. Caso se queira gerar a verso release
(recomendado), basta acessar os menus Build, Set active configuration e escolher freeglut
Win32 Release, no Visual C++ 6. No Visual C++ .NET, o caminho Build, Configuration
Manager ... e escolher Release em Active Solution Configuraration. A seguir preciso
construir a DLL como explicado anteriormente.
3.1.2. Configurao
Aps a construo da DLL, preciso configurar o Visual C++ para que seja possvel usar o
freeglut. Isso pode ser feito com os passos descritos aqui (supondo que o diretrio do freeglut seja
c:\freeglut).
Luis Valente
escolher VC++ Directories e em Show directories for, escolher library files. Criar uma
nova entrada e acrescentar c:\freeglut\lib (ou outro diretrio onde esteja o arquivo).
glFlush ();
return 0;
8 O DevC++ uma IDE (Integrated Development Environment) para o GCC do Windows. gratuita e est disponvel
em http://www.bloodshed.net/dev/devcpp.html
7
Luis Valente
Esse arquivo permite utilizar todas as funes do freeglut. Esse arquivo j inclui
automaticamente os arquivos principais do OpenGL (o gl.h e o glu.h). Dessa forma, no preciso
especific-los. No necessrio incluir o arquivo principal do Windows (windows.h).
Luis Valente
4. Primitivas
Uma primitiva um objeto simples que pode ser usado para a criao de outros objetos
complexos. As primitivas disponveis no OpenGL esto resumidas na figura 4.1.
A especificao de primtivas no OpenGL segue um padro, demonstrado no seguinte trecho de
cdigo:
glBegin (nome da primitiva)
...
glEnd ();
O nome da primitiva uma constante que indica qual o tipo de primitiva usado. Essas
constantes esto presentes na figura 4.1.
Para se especificar os vrtices da primitiva, o seguinte comando usado:
glVertex* ()
O * usado aqui para indicar que existem diversas variaes do comando, por exemplo:
glVertex3f
glVertex3i
glVertex2d
glVertex4f
Luis Valente
//
//
//
//
x,
x,
x,
x,
y,
y,
y,
y,
z,
z,
0,
z,
1
1
1
w
4.1. Pontos
Para especificar pontos simples, necessrio usar a constante GL_POINTS.
glBegin (GL_POINTS);
glVertex3f (0.0f, 0.0f, 0.0f);
glVertex3f (10.0f, 20.0f, -3.0f);
glVertex3f (4.0f, -10.0f, 1.0f);
glEnd ();
O exemplo desenha trs pontos na janela. Por padro, o OpenGL desenha os pontos com
tamanho igual a 1 pixel. Entretanto, possvel desenhar pontos maiores. Para isso, preciso usar o
seguinte comando:
glPointSize (GLfloat tamanho);
10
Luis Valente
O maior valor possvel depende do hardware onde o programa ser executado. O nico valor
garantido a existir 1.0 (que corresponde a um pixel). Para consultar a faixa de valores possveis,
basta usar o seguinte trecho de cdigo:
GLfloat faixa [2];
glGetFloatv (GL_POINT_SIZE_RANGE, faixa);
GLfloat min = faixa [0];
GLfloat max = faixa [1];
A faixa de valores possveis para o tamanho dos pontos apenas uma das propriedades do
OpenGL que podem ser consultadas. Existem diversas outras, que podem ser obtidas usando
funes como glGetFloatv , glGetIntegerv, glGetDoublev e glGetBooleanv.
Outra propriedade interessante que pode ser alterada a suavizao no desenho dos pontos
(anti-aliasing). O comando para especific-la :
glEnable (GL_POINT_SMOOTH);
O comando glEnable responvel por habilitar alguma propriedade do OpenGL (ou seja,
ligar o estado). O comando correspondente, para desligar, glDisable. Dessa forma, para
desligar a suavizao no desenho dos pontos, basta usar este comando:
glDisable (GL_POINT_SMOOTH);
4.2. Linhas
Existem trs primitivas relacionadas
GL_LINE_STRIP e GL_LINE_LOOP.
GL_LINE,
// descartado
glEnd ();
Quando essa primitiva usada, cada par de vrtices usado para desenhar uma linha. Caso
exista um nmero mpar de vrtices, o ltimo vrtice descartado.
Na primitiva GL_LINE_STRIP, os vrtices especificados so conectados em sequncia,
conforme so especificados:
glBegin (GL_LINE_STRIP)
glVertex3f (0.0f, 0.0f, 0.0f);
glVertex3f (10.0f, 10.0f, 5.0f);
glVertex3f (5.0f, -20.0f, 0.0f);
glEnd ();
11
Luis Valente
4.3. Polgonos
O OpenGL permite usar trs tipos de polgonos: tringulos, quadrilteros e polgonos genricos.
Comum a todos eles, existe uma propriedade importante: a ordenao dos vrtices (a ordem em que
so especificados) deve ser consistente. As ordenaes possveis so ilustradas na figura 4.2.
Figura 4.2 Ordenaes possveis. (a) Sentido horrio. (b) Sentido anti-horrio.
Essa propriedade importante porque a ordenao dos vrtices define o lado do polgono que
est voltado para a frente e o lado do polgono que est voltado para trs. O padro usado pelo
OpenGL (e neste trabalho) que as faces voltadas para frente so especificadas em sentido antihorrio. Esse padro pode ser alterado com o seguinte comando:
glFrontFace (ordem);
12
Luis Valente
4.3.1. Tringulos
Os triangulos so o tipo de primitiva mais usado em OpenGL (e em grficos 3D, em geral). No
OpenGL, existem trs variaes sobre o tema: GL_TRIANGLES, GL_TRIANGLE_STRIP e
GL_TRIANGLE_FAN.
A primitiva GL_TRIANGLE permite desenhar tringulos simples:
glBegin (GL_TRIANGLES)
glVertex2f (10.0f, 10.0f);
glVertex3f (20.0f, -5.0f);
glVertex3f (-20.0f, -5.0f);
glVertex3f (100.0f, 0.0f);
glVertex3f (100.0f, -8.0f);
// descartado
// descartado
glEnd ();
13
Luis Valente
Quando essa primitiva usada, o OpenGL usada cada trinca de vrtices para desenhar um
tringulo. Caso exista uma trinca incompleta, esta descartada.
A primitiva GL_TRIANGLE_STRIP usada para se desenhar uma tira de tringulos
(tringulos conectados sequencialmente). Esse esquema pode ser visualizado na figura 4.3.
Os trs primeiros vrtices so usados para formar o primeiro tringulo. A seguir, cada vrtice
subsequente conectado aos dois vrtices anteriores. Na figura 4.3, a ordenao dos vrtices segue
o sentido anti-horrio.
A primitiva GL_TRIANGLE_FAN usada para se conectar vrios tringulos em torno de um
ponto central, tal como um leque (fan):
glBegin (GL_TRIANGLE_FAN);
glVertex3f (0.0f, 0.0f, 0.0f);
glVertex3f
glVertex3f
glVertex3f
glVertex3f
glEnd ();
O primeiro vrtice especificado na primitiva o ponto central do leque. Os dois vrtices
seguintes formam o primeiro tringulo. A partir de ento, preciso somente especificar um novo
vrtice para formar um novo tringulo (o tringulo ser construdo usando o novo vrtice e dois
vrtices especificados antes deste).
A figura 4.4. ilustra um leque formado por essa primitiva.
14
Luis Valente
4.3.2. Quadrilteros
As primitivas para quadrilteros em OpenGL so duas: GL_QUADS e GL_QUAD_STRIP.
O uso de GL_QUADS possibilita que sejam gerados quadrilteros simples. O OpenGL utiliza
quatro vrtices de cada vez para formar um quadriltero, como neste exemplo:
glBegin (GL_QUADS);
glVertex3f
glVertex3f
glVertex3f
glVertex3f
// descartado
// descartado
glEnd ();
15
Luis Valente
A primitiva GL_QUAD_STRIP serve para formar tiras de quadrilteros conectados. Seu modo
de uso quase idntico ao de GL_TRIANGLE_STRIP. Em GL_QUAD_STRIP preciso
especificar quatro vrtices iniciais (para formar o primeiro quadrado) e mais dois vrtices de cada
vez para formar os outros quadrados. O uso dessa primitiva ilustrado na figura 4.6.
5. Cores e sombreamento
Cores em OpenGL so especificadas como RGBA. O comando para alterar as cores :
glColor* ()
Assim como vrios comandos, o glColor possui diversas variaes. Nas verses que aceitam
argumentos de ponto flutuante, os valores para cada componente variam entre 0.0 (ausncia) e 1.0
(intensidade mxima). Exemplos de uso:
glColor3f (1.0f, 1.0f, 1.0f);
glColor3f (0.0f, 0.0f, 0.0f);
glColor3f (1.0f, 0.0f, 0.0f);
// branco
// preto
// vermelho puro
Nas variaes que trabalham com nmeros inteiros sem sinal, os valores dos componentes
variam de 0 (ausncia) a 255 (intensidade mxima).
O OpenGL trabalha internamente com RGBA, de forma que se forem especificadas apenas trs
componntes, o quarto componente (alfa) ser 1.0 por padro.
glColor3f (0.0f, 1.0f, 0.0f);
// verde , alfa = 1.0
glColor4f (1.0f, 1.0f, 0.0f, 0.25f) // amarelo, alfa = 0.25
16
Luis Valente
Quando um comando de cor usado, a cor especificada ser usada para todas as primitivas at
que uma outra cor seja especificada. Segue um pequeno exemplo:
glColor3f (1.0f, 0.0f, 0.0f);
glBegin (GL_TRIANGLES);
glVertex3f ( 0.0f, 10.0f, 5.0f);
glVertex3f (-10.0f, 0.0f, 5.0f);
glVertex3f ( 10.0f, 0.0f, 5.0f);
glEnd ();
Nesse exemplo, o tringulo ser preenchido com a cor vermelha. Entretanto, as cores tambm
podem ser especificadas para cada vrtice, como no prximo exemplo:
glBegin (GL_TRIANGLES);
glColor3f (1.0f, 0.0f, 0.0f);
glVertex3f (0.0f, 10.0f, 5.0f);
glColor3f (0.0f, 1.0f, 0.0f);
glVertex3f (-10.0f, 0.0f, 5.0f);
glColor3f (0.0f, 0.0f, 1.0f);
glVertex3f (10.0f, 0.0f, 5.0f);
glEnd ();
Para entender o que acontece nesse exemplo, preciso explicar o conceito de modo de
sombreamento.
O modo de sombreamento do OpenGL indica como ser feita a colorao das primitivas (e
preenchimento dos polgonos. Existem dois modos possveis: o sombreamento suave (Gouraud) e
sombreamento fixo. No sombreamento fixo, uma nica cor usada para preencher o polgono. No
caso de sombreamento suave, o OpenGL ir realizar uma interpolao entre as cores dos vrtices
para preencher os polgonos.
O resultado desses dois modos (aplicados no exemplo) pode ser conferido na figura 5.1.
17
Luis Valente
Figura 5.1 Modos de sombreamento. (a) Sombreamento fixo. (b) Sombreamento suave.
6. Z-Buffer
O OpenGL usa o z-buffer para determinar a visibilidade dos objetos desenhados na cena. Esse
teste ocorre na etapa de rasterizao.
O z-buffer um dos vrios buffers que existem no OpenGL. Tipicamente, a implementao do
z-buffer feita no hardware da placa grfica. O z-buffer armazena valores que tm a ver com a
profundidade dos pixels da tela. Dessa forma, o z-buffer possui o mesmo tamanho da janela ou tela
da aplicao.
De maneira simplificada, o algoritmo de z-buffer usado da seguinte maneira: no incio da
aplicao (ou antes de imagem ser construda, por exemplo, no incio de um quadro de animao do
programa), o z-buffer preenchido (limpo) com um certo valor (um valor muito grande, por
exemplo). Quando um pixel precisa ser pintado na tela, o algoritmo consulta o valor correspondente
a esse pixel que est armazenado no z-buffer. Se o valor for menor (o que quer dizer que o novo
pixel estaria mais perto), o pixel pintado na tela e o valor de profundidade armazenado no zbuffer. Caso esse valor fosse maior do que aquele que l estivesse, o pixel no seria pintado. A
consequncia da aplicao desse algoritmo que a cena desenhada corretamente (em termos de
determinao de visibilidade).
18
Luis Valente
Para se usar o z-buffer no OpenGL, preciso requisitar sua criao. No freeglut, basta usar a
constante GLUT_DEPTH junto com as outras na hora da inicializao:
glutInitDisplayMode (GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGB);
A seguir, preciso habilitar o uso do z-buffer no OpenGL (que est desligado por padro). Isso
pode ser feito com o seguinte comando:
glEnable (GL_DEPTH_TEST);
Caso se queira desligar o teste de z-buffer, basta usar o comando glDisable
(GL_DEPTH_TEST).
Durante o ciclo de vida da aplicao, o z-buffer dever ser zerado toda vez que se desejar criar
uma nova imagem. Isso normalmente feito no mesmo momento em que se limpa a tela. Para
realizar essa operao conjunta, basta usar este comando:
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
O funcionamento do z-buffer e suas configuraes podem ser alteradas com grande
flexibilidade, mas esse detalhamento est fora do escopo deste trabalho. Para maiores informaes,
por favor, consulte a documentao do OpenGL.
7. Transformaes e projees
O OpenGL usa diversos tipos de transformaes geomtricas na especificao da cena. Essas
transformaes podem ser dos seguites tipos: Viewport, Modelagem, Projeo e Cmera.
O sistema de coordenadas tridimensional usado no OpenGL o sistema de coordenadas da mo
direita, que pode ser visualizado na figura 7.1.
7.1. Viewport
A transformao de viewport indica a rea da janela onde sero realizadas as operaes de
desenho. A figura 7.2 ilustra um exemplo de viewport.
19
Luis Valente
7.2. Matrizes
O OpenGL usa matrizes para implementar todas as transformaes existentes. Normalmente, o
usurio no precisa lidar com as matrizes diretamente (embora isso seja possvel se for desejado),
pois existem vrios comandos para manipul-las.
As transformaes de modelagem e projeo so independentes entre si. Internamente, o
OpenGL mantm uma matriz para cada um desses tipos.
Em um dado momento, s permitido usar um dos tipos de matriz. O tipo de matriz usado no
momento determinado pelo seguinte comando:
glMatrixMode (nome da matriz);
O nome da matriz de modelagem GL_MODELVIEW e o da matriz de projeo
GL_PROJECTION. Segue um exemplo:
glMatrixMode (GL_PROJECTION);
// a partir deste momento, a matriz afetada a de
// projeo
...
glMatrixMode (GL_MODELVIEW);
20
Luis Valente
Existem algumas operaes pr-definidas que podem ser aplicadas em matrizes. Esses
comandos afetam o tipo de matriz selecionado no momento. As operaes principais so translao,
rotao, escala e carregar a matriz identidade.
A matriz identidade serve para reiniciar o sistema de coordenadas, ou seja, a posio
selecionada ser a origem, no existiro rotaes e a escala ser igual a 1 em todos os eixos. O
comando para carregar a matriz identidade :
glLoadIdentity ();
A operao de translao desloca o sistema de coordenadas pelo nmero de unidades
especificadas. O comando correspondente :
glTranslate* (x, y, z);
// * = f ou d
Esse comando acumulativo (assim como todos os outros), como descrito neste exemplo:
glLoadIdentity ();
// posio = 0,0,0
// posio = 10,0,0
// posio = 10,5,-1
// * = f ou d
// * = f ou d
Os parmetros representam os fatores de escala em cada eixo. O valor 1.0 no afeta a escala.
7.3. Modelagem
Como exemplo, suponha que se queria desenhar um tringulo na posio (10, 10, 0). Isso pode
ser feito com o seguite trecho de cdigo:
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
glTranslatef (10, 10, 0);
glBegin (GL_TRIANGLES);
21
Luis Valente
7.4. Projeo
O OpenGL possui funes para configurar dois tipos de projees: projees ortogrficas e
projees em perspectiva.
left,
right,
bottom,
top,
near,
far
);
Os parmetros correspondem aos valores dos planos que formam o volume de viso da projeo
ortogrfica. Esse volume de viso pode ser visualizado na figura 7.3.
22
Luis Valente
9 Na verdade, que esteja no centro da viewport. Nesse exemplo, considera-se que a viewport ocupe toda a janela (o
que bastante comum).
23
Luis Valente
Para corrigir essa distoro, necessrio levar em considerao a razo de aspecto da janela ao
se calcular a projeo. Isso pode ser feito da seguinte forma:
// largura e altura da viewport
largura = ...
altura = ...
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
GLdouble proporcao = largura/altura;
if (proporcao >= 1.0)
glOrtho (left * proporcao, right * proporcao, bottom, top,
near, far);
else
glOrtho (left, right, bottom / proporcao, top / proporcao,
near, far);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
24
Luis Valente
25
Luis Valente
7.5. Cmera
A separao do conceito de transformao de cmera, em OpenGL, apenas uma notao de
convenincia. No existe uma matriz separada para transformao de cmera, na verdade, essa
transformao afeta a matriz de modelagem.
A transformao de cmera serve para posicionar e orientar o ponto de vista na cena. O
OpenGL oferece uma funo para especificar essa transformao:
gluLookAt (pos_x , pos_y , pos_z,
alvo_x, alvo_y, alvo_z,
up_x , up_y , up_z);
Os primeiros trs parmetros correspondem posio do observador (ou da cmera) na cena. Os
trs seguintes correspondem ao ponto para onde a cmera est apontada. Os trs ltimos
especificam um vetor que indica qual a direo que pode ser considerada para cima. Por
exemplo, se o usurio est posicionado em (0, 0, 0) e olhando para (0, 0, -20), a direo para cima
corresponde a (0, 1, 0).
A transformao de cmera deve ser a primeira a ser especificada na renderizao da cena:
// supondo que o modo de matriz atual seja GL_MODELVIEW
void desenharCena ()
{
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity ();
glLookAt (0.0, 0.0, 0.0,
0.0, 0.0, -20.0,
0.0, 1.0, 0.0);
26
Luis Valente
27
Luis Valente
// * = f ou d
glMultMatrix* (m);
// * = f ou d
A funo glLoadMatrix* permite substituir a matriz atual pela matriz especificada como
parmetro. A funo glMultMatrix* permite multiplicar a matriz atual por uma matriz
qualquer.
A definio da matriz m deve ser feita usando um array simples:
GLfloat matriz [16];
O OpenGL trabalha internamente vetores coluna, por isso a matriz m tratada da seguinte
forma:
28
Luis Valente
// C convencional
8. Composio de objetos
A maneira mais simples de se desenhar algum objeto seria especificar os seus vrtices em
alguma funo qualquer, como por exemplo:
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
desenharMeuObjeto ();
Existem vrias desvantagens em se usar essa abordagem. Por exemplo, se for necessrio realizar
clculos complexos para gerar a geometria do objeto, nesse exemplo esses clculos seriam
realizados vrias vezes (quando eles poderiam ser feitos uma vez s, como na inicializao do
programa).
Com o OpenGL, possvel agrupar comandos para serem executados em uma nica chamada,
com as diplay lists. Display lists so listas de comandos do OpenGL pr-processados.
No exemplo do clculo da geometria do objeto, ao se usar uma display list, somente o resultado
final do processo (como os vrtices) seria armazenado.
As display lists so referenciadas por um identificador, que um nmero simples. Entretanto,
preciso requisitar ao OpenGL que gere um identificador vlido. Isso pode ser feito da seguinte
forma:
GLuint minhaLista = glGenLists (1);
A varivel minhaLista contm o identificador da lista, e o argumento da funo glGenLists
indica quantas listas devero ser criadas. Caso sejam criadas vrias listas, elas podero ser acessadas
sequencialmente, a partir do identificador principal. Por exemplo, caso se queira criar cinco listas:
29
Luis Valente
9. Iluminao
Para usar iluminao em OpenGL, preciso seguir alguns passos:
30
Luis Valente
O uso de iluminao est desabilitado por padro. Para habilitar a iluminao, necessrio usar
o seguinte comando:
glEnable (GL_LIGHTING);
A iluminao pode ser desligada a qualquer momento usando este comando:
glDisable (GL_LIGHTING);
9.2. Materiais
Os materiais so propriedades de uma superfcie que definem sua aparncia. Essas propriedades
tm a ver com a componente da luz que eles so capazes de refletir.
Os tipos de material que podem ser especificados no OpenGL so: GL_AMBIENT,
GL_DIFFUSE, GL_SPECULAR, GL_EMISSION e GL_SHININESS.
O GL_AMBIENT, GL_DIFFUSE e GL_SPECULAR especificam a reflectncia de luz ambiente,
difusa e especular, respectivamente. O GL_EMISSION especifica a intensidade de luz emitida pelo
material,. O GL_SHININESS especifica um valor (specular exponent) que tem a ver com a
concentrao de brilho em uma superfcie. Quando maior esse valor, mais concentrado o brilho
especular (a rea ocupada por ele menor).
31
Luis Valente
32
Luis Valente
glEnable (GL_COLOR_MATERIAL);
glColorMaterial (GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
glColor3f (1.0f, 0.0f, 0.0f);
glBegin (GL_TRIANGLES);
glVertex3f (0.0f, 10.0f, 30.0f);
glVertex3f (-50.0f, 0.0f, 30.0f);
glVertex3f (50.0f, 0.0f, 30.0f);
glEnd ();
33
Luis Valente
Os valores possveis para essa propriedade variam de 0 a 90. Existe um valor especial, 180,
que pode ser usado para desabilitar essa propriedade (efetivamente desabilitando esse tipo de fonte
de luz). Esse valor o padro.
A propriedade GL_SPOT_DIRECTION indica qual a direo do feixe de luz. O valor da
propriedade expresso em coordenadas do objeto (ou seja, em relao fonte de luz).
A propriedade GL_SPOT_EXPONENT indica a intensidade de distribuio da luz. Os valores
aceitos variam de 0 a 128. Quanto maior o valor, mais concentrada a luz no centro do cone. O
valor padro 0, que resulta em uma distribuio uniforme da luz.
34
Luis Valente
Leitura da imagem em disco (ou gerao dos dados da textura atravs de algum
algoritmo);
Luis Valente
Quando a textura no for mais necessria, ser preciso liberar os recursos que foram alocados.
Essa tarefa realizada como no exemplo a seguir:
glDeleteTextures (1, & identificador);
glDeleteTextures (5, texturas);
O comando glDeleteTextures recebe como parmetros a quantidade de texturas a terem
seus recursos devolvidos ao sistema e um local (uma varivel ou array) que contm os
identificadores das texturas.
GLuint
...
Luis Valente
id;
// alocar buffer para imagem e carrega imagem do disco
// (isso ainda ser visto com mais detalhes)
10.3.1. Mipmaps
A tcnica de mipmaps foi definida por Lance Williams no artigo Pyramidal Parametrics
(SIGGRAPH '83). A tcnica consiste em se criar vrias verses de uma mesma imagem, em
resolues diferentes, como ilustrado na figura 10.1.
37
Luis Valente
Esse processo realizado at que se chegue menor imagem possvel (com 1 pixel). As
mipmaps podem ser aplicadas para mapeamento de texturas em polgonos da seguinte forma: os
polgonos que esto distantes do observador usariam verses de menor resoluo das texturas,
enquanto os que esto prximos do observador utilizariam uma textura de maior resoluo.
Algumas vantagens desse mtodo so:
Melhoria do desempenho da aplicao, porque como as imagens so pr-fltradas,
possvel escolher uma imagem que possua tamanho prximo ao do polgono a ser mapeado,
reduzindo o custo do processamento em tempo real da interpolao. Adicionalmente, podem
ser aplicados filtros mais custosos (que produzam melhores resultados visuais) na etapa de
inicializao (gerao das mipmaps), o que talvez no poderia ser feito em tempo real.
//
//
//
//
//
//
igual
igual
igual
igual
igual
igual
ao
ao
ao
ao
ao
ao
glTexImage2D
glTexImage2D
glTexImage2D
glTexImage2D
glTexImage2D
glTexImage2D
);
Luis Valente
Luis Valente
ilBindImage (image);
// determinamos que o 0,0 da figura o canto
// inferior esquerdo
ilEnable (IL_ORIGIN_SET);
ilOriginFunc (IL_ORIGIN_LOWER_LEFT);
// carregamos a imagem do disco
ilLoadImage (arquivo);
// algum erro no carregamento do arquivo ?
ILenum erro = ilGetError ();
if (erro != IL_NO_ERROR)
{
// desaloca recursos usados para carregar a imagem
ilDeleteImages (1, & image);
}
return 0;
Luis Valente
bytesPerPixel, //
width,
height,
0,
imageFormat,
GL_UNSIGNED_BYTE
imageData
);
// inicializar a DevIL
41
Luis Valente
42
Luis Valente
43
Luis Valente
GL_LINEAR: Utiliza interpolao linear. Prov melhores resultados visuais, mas mais
custoso em termos computacionais. Pode ser usado como filtro de reduo e ampliao. Esse
filtro o selecionado por padro.
Outro parmetro que pode ser alterado indica o modo como a textura ser afetada pelas cores
dos polgonos e informaes de iluminao calculadas. O modo padro (GL_MODULATE) indica
que essas informaes sejam interpoladas com os dados da textura. J o modo GL_DECAL indica
que o mapeamento deve ignorar essas informaes (a textura mapeada como se fosse um
adesivo).
Esses modos podem ser determinados com o comando:
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_MODE, modo);
tipo
de
dados
#include <GL/glu.h>
GLUquadricObj * quadric = gluNewQuadric ();
Quando no for mais necessrio usar o objeto quadric, ser necessrio liberar os recursos
alocados para a superfcie:
gluDeleteQuadric (quadric);
Existem vrias propriedades da superfcie que podem ser configuradas atravs de comandos da
GLU.
44
Luis Valente
11.1. Cilindros
Os cilindros podem ser desenhados com o seguinte comando:
void gluCylinder (GLUquadricObj * qobj,
GLdouble baseRadius,
GLdouble topRadius,
GLdouble height,
GLint
slices,
GLint
stacks
);
Os parmetros baseRadius e topRadius indicam os raio da base do cilindro e do topo do
cilindro, respectivamente. O parmetro height indica qual a altura do cilindro. O parmetro
slices indica qual o nmero de faces na lateral do cilindro. J o parmetro stacks indica
quantas divises existem ao longo do corpo do cilindro. Esses parmetros so ilustrados na figura
11.1.
45
Luis Valente
11.2. Discos
Os discos podem ser desenhados com a seguinte funo:
void gluDisk (GLUquadricObj * qobj,
GLdouble innerRadius,
GLdouble outerRadius,
GLint
slices,
GLint
loops
);
Os parmetros innerRadius e outerRadius correspondem aos raios interno e externo do
disco. O parmetro slices indica quantos lados o disco possui. Esses parmetros so ilustrados na
figura 11.2.
46
Luis Valente
Finalmente, o parmetro loops indica o nmero de crculos concntricos que devem ser
desenhados entre os raios interno e externo.
O disco desenhado no plano z = 0.
11.4. Esferas
Para se desenhar esferas, utilizado o seguinte comando:
void gluSphere (GLUquadricObj * qobj,
GLdouble radius,
GLint slices,
GLint stacks
);
A esfera desenhada de forma que o seu centro coincida com a origem. O parmetro radius
define raio da esfera. O parmetro slices indica o nmero de divises da esfera em torno do eixo
Z (como longitude). J o parmetro stacks indica o nmero de divises da esfera ao longo do
eixo Z (como latitude). A figura 11.3 ilustra os parmetros slices e stacks.
47
Luis Valente
OnUpdate ();
OnResize (int width, int height);
OnRender ();
OnKeyPress (unsigned char key, int x, int y);
48
Luis Valente
(OnRender);
(OnResize);
(OnKeyPress);
(OnUpdate);
InitGL ();
glutMainLoop ();
}
(OnRender);
(OnResize);
(OnKeyPress);
(OnUpdate);
49
Luis Valente
12.2. Inicializao
Na etapa de inicializao, so submetidos comandos que determinam funcionalidades que sero
usadas no restante da aplicao. A funo correspondente descrita a seguir:
void InitGL ()
{
glEnable (GL_DEPTH_TEST);
glEnable (GL_CULL_FACE);
glClearColor (0.0f, 0.0f, 0.0f, 1.0f);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
}
Essa funo requisita que o testes de z-buffer e eliminao de faces escondidas (backface
culling) sejam habilitados.
A seguir, a cor de fundo da janela estabelecida. (preto).
Finalmente, determina-se que o tipo de projeo usado a partir deste momento ser a matriz de
modelagem.
50
Luis Valente
12.4. Atualizao
A funo OnUpdate atualiza a posio do quadrado e verifica se existiu alguma coliso contra
as bordas da janela (viewport, na verdade). Caso exista, a posio do quadrado corrigida e a sua
velocidade invertida (no eixo onde ocorreu a coliso). O quadrado possui aresta de tamanho igual
a 4 unidades.
void OnUpdate ()
{
quad_x += vx; quad_y += vy;
quad_z += vz;
12.5. Teclado
A funo OnKeyPress recebe como parmetros a tecla que foi pressionada e a posio do
mouse no momento em que a tecla foi pressionada.
void OnKeyPress (unsigned char key, int x, int y)
{
switch (key)
{
case 'q': case 'Q' :
exit (0); break;
}
}
Existem outras funes para se tratar eventos do teclado, que podem ser consultadas na
documentao do freeglut ou do GLUT.
12.6. Renderizao
A funo responsvel pela renderizao inicia com a requisio para que a tela e o z-buffer
sejam limpos.
51
Luis Valente
A seguir, a matriz identidade carregada, para que o sistema de coordenadas seja reiniciado
para a origem.
void OnRender ()
{
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity ();
glTranslatef (quad_x, quad_y, quad_z);
glColor3f (1.0f, 0.0f, 0.0f);
glBegin (GL_QUADS);
glVertex3f
glVertex3f
glVertex3f
glVertex3f
glEnd ();
glutSwapBuffers ();
}
A seguir, necessrio posicionar o quadrado, o que feito com o comando glTranslatef.
O quadrado , ento, especificado.
A funo glutSwapBuffers requisita que o buffer usado para as operaes de renderizao
seja exibido na tela.
13. Concluses
OpenGL uma API muito rica e cheia de recursos. Este trabalho aborda apenas uma parte do
que poderia ser usado.
Existem tutoriais e outros recursos para se aprender mais sobre OpenGL em vrios lugares na
internet. Aqui esto alguns deles:
GameTutorials Vrios tutoriais sobre OpenGL, com enfoque para programao de jogos:
http://www.gametutorials.com
52
Luis Valente
WrSw99
Wright, Richard S.; Sweet, Michael OpenGL SuperBible Second Edition, Waite
Group Press, 1999
NeDa97
FGLUT04
DEVIL04
53