Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D...

148
Computa¸c˜ ao Gr´ afica Manual de Apoio 2010 Lu´ ıs Filipe Lobo <[email protected]>

Transcript of Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D...

Page 1: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Computacao Grafica

Manual de Apoio2010

Luıs Filipe Lobo <[email protected]>

Page 2: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Conteudo

1 Introducao 51.1 A caminho do 3D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51.2 Efeitos 3D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61.3 Transformacoes Geometricas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

1.3.1 Eye Coordinates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71.3.2 Viweing Transformations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71.3.3 Modeling Transformations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81.3.4 Projection Transformations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81.3.5 Viewport Transformations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

2 Princıpios Basicos de Programacao 3D 112.1 Sistemas de Coordenadas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

2.1.1 Coordenadas Cartesianas - 2D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112.1.2 Viewport - Mapeamento de coordenadas para pixels . . . . . . . . . . . . . . . . . . . . . 112.1.3 O Vertex (vertice) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132.1.4 Coordenadas Cartesianas 3D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

2.2 Projeccoes: 3D → 2D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132.2.1 Projeccoes Ortogonais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132.2.2 Projeccoes em Perspectiva . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

3 Introducao ao OpenGL 153.1 O pipeline OpenGL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153.2 Tipos de Dados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

3.2.1 Nomes de Funcoes - Convencao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153.3 JOGL - Java OpenGL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163.4 The State Machine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173.5 O pipeline de Transformacoes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

3.5.1 Matriz Modelview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183.5.2 A Matriz Identidade (Identity Matrix ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

3.6 Projeccoes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213.7 Camaras e Actores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

4 Primitivas Geometricas e Buffers 244.1 O ponto 3D - (Vertex ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244.2 Primitivas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

4.2.1 Pontos: GL POINTS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254.2.2 Linhas: GL LINES . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264.2.3 Tiras de Linha: GL LINE STRIP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274.2.4 Loops de Linha: GL LINE LOOP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274.2.5 Padroes de Linha:GL LINE STIPPLE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 304.2.6 Triangulos: GL TRIANGLES . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 314.2.7 Tiras de Triangulos:GL TRIANGLE STRIP . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324.2.8 Triangle Fans:GL TRIANGLE FANS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

4.3 Outras Primitivas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334.3.1 Quadrilateros: GL QUADS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334.3.2 Tiras de Quadrados:GL QUAD STRIP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 344.3.3 Polıgonos: GL POLYGON . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 344.3.4 Preenchimento de Polıgonos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34

1

Page 3: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

4.3.5 Regras na Criacao de Polıgonos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364.3.6 Sub-divisao de Arestas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

4.4 Buffers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364.4.1 Buffer de Profundidade . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374.4.2 Scissors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37

5 Cores, Materiais e Luzes 395.1 Cor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

5.1.1 Modos de Display . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 405.2 Utilizacao de Cores no OpenGL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

5.2.1 Shading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 425.3 Cores no Mundo Real . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44

5.3.1 Luz Ambiente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 445.3.2 Luz Difusa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 445.3.3 Luz Especular . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 455.3.4 Luz de Modo Geral . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45

5.4 Materiais no Mundo Real . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 455.5 Adicao de Luzes ao Cenario . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 465.6 Fontes de Luz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48

5.6.1 Configurando uma Fonte de luz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 535.7 Efeitos de Iluminacao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54

5.7.1 Luz Especular . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 545.7.2 Normal Averaging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 555.7.3 Especificando um Spotlight . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 565.7.4 Tesselation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57

6 Cores e Materiais (Continuacao) 586.1 Blending . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58

6.1.1 Combinacao de Cores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 586.1.2 Alteracao da Equacao de Blending . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61

6.2 Antialiasing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 626.2.1 Multisampling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63

6.3 Nevoeiro (Fog) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 636.4 Accumulation Buffer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65

7 Imagens no OpenGL 687.1 Bitmaps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 687.2 Pixmaps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 707.3 Operacoes com Pixels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 717.4 Outras Operacoes com Imagens . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74

8 Mapeamento de Texturas 788.1 Carregamento de Texturas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78

8.1.1 Pipeline do Carregamento de Imagens . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 798.1.2 Utilizando o Color Buffer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 798.1.3 Actualizacao de Texturas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80

8.2 Mapeamento de Texturas a Geometria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 818.3 Exemplo de Textura 2D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 828.4 Texture Environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 848.5 Parametrizacao de Texturas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85

8.5.1 Filtering Basico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 858.5.2 Texture Wrap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 868.5.3 Mipmapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 868.5.4 Mipmap Filtering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 878.5.5 Geracao de nıveis de Mipmapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 878.5.6 Geracao de Mipmaps por Hardware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 888.5.7 Level Of Detail (LOD) Bias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89

8.6 Texture Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89

2

Page 4: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

9 Mapeamento de Texturas: Conceitos Avancados 909.1 Cor Secundaria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 909.2 Anisotropic Filtering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 909.3 Compressao de Texturas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 929.4 Geracao de Coordenadas de Texturas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93

9.4.1 Oject Linear Mapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 939.4.2 Eye Linear Mapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 949.4.3 Sphere Mapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95

9.5 Cube Mapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 959.5.1 Carregamento do Cube Map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 959.5.2 Utilizacao dos Cube Maps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98

10 Curvas e Superfıcies 10010.1 Superfıcies Incorporadas no OpenGL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100

10.1.1 Configuracao de Superfıcies Quadricas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10110.1.2 Desenho de Superfıcies Quadricas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102

10.2 Curvas de Bezier e Superfıcies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10410.2.1 Representacao Parametrica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10510.2.2 Pontos de Control (control points) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10510.2.3 Continuidade . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10610.2.4 Evaluators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10610.2.5 Superfıcies 3D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10810.2.6 Luzes e Vectores Normais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109

11 Conceitos Avancados 11111.1 Display Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111

11.1.1 Pros e Contras . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112

A Exemplos 113A.1 Exemplo Simples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113

B Tabelas 114B.1 Formato de Imagem (pixmap) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114B.2 Tipo de Dados (pixmap) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115

C Codigo Fonte 116C.1 Example0.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116C.2 Imaging.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118C.3 Pyramid.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122C.4 TexGen.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126C.5 CubeMap.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131C.6 SnowMan.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136C.7 Bezier2D.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139C.8 Bezier3D.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141C.9 BezierLighting.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144

3

Page 5: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Convencoes

Na medida dos possıveis foram traduzidos os nomes de ingles para portugues. No entanto, para o desenvolvimentocom a API OpenGL, algumas palavras chave sao de grande relevo na lıngua original, o ingles.

Para facilitar a localizacao de metodos nas classes JOGL, estes sao apresentados sob a forma:

Classe.metodo(Tipo1 arg1 , ..., TipoN argN);

Referencias

Os apontamentos foram elaborados com base nas referencias:

• OpenGL Superbible [?]

4

Page 6: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Capıtulo 1

Introducao

1.1 A caminho do 3D

Os objectos tri-dimensionais podem ser mostrados ou descritos com recurso a tres medidas: largura, altura eprofundidade. Nos dispositivos graficos, superfıcies inevitavelmente 2D, a forma de dar a sensacao de profundidadee conseguida pela introducao de perspectiva (Figura 1.1).

Figura 1.1: Wireframe de um cubo 3D

A visao humana obtem a percepcao tridimensional pela utilizacao de dois olhos. O nosso cerebro recebeduas imagens bidimensionais ligeiramente diferentes por serem recebidas em angulos diferentes (Figura 1.2). Asduas imagens sao entao combinadas numa so com o objectivo de produzir uma unica imagem, mas desta veztridimensional.

Figura 1.2: Visao tridimensional

A medida que um determinado objecto se afasta, o angulo (θ) entre as duas imagens vai diminuindo.Normalmente os dispositivos graficos que simulam o efeito de realismo 3D (estereoscopicos) utilizam duas imagensdiferentes para cada olho.

Os dispositivos graficos flat utilizam o mesmo mecanismo que a natureza providencia para que pessoas comum unico olho possam ver a tres dimensoes. O “artefacto” utilizado para conseguir este efeito e, com efeito, aperspectiva. Para alem deste artefacto, mesmo com um unico olho, o nosso cerebro continua a conseguir discernirprofundidade, em grande parte devido aos efeitos presentes nos objectos.

5

Page 7: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

1.2 Efeitos 3D

Uma palavra a ter em mente na computacao grafica e rendering. Rendering consiste na conversao da descricaode um objecto tridimensional numa imagem no ecra. Os efeitos seguintes sao aplicados aquando do rendering deuma imagem.

Perspective : A perspectiva refere-se aos angulos entre as linhas que levam a ilusao de estarmos napresenca de tres dimensoes.

Color and Shading: A colocacao de cores nas varias faces do cubo, permite replicar nıveis de escuridao(shading), reafirmando o aspecto de um objecto solido.

(a)

Light & Shadows: Ainda com a utilizacao de cores e possıvel dar as superfıcies a sensacao de iluminacao.Adicionando sombra avancamos um passo no caminho do realismo.

(b)

Texture Mapping: A maneira brute-force de alcancar realismo, pode passar pela adicao de mais polıgonos(mais detalhe) a imagem, no entanto, a custa de processamento adicional. Outra forma de obter o mesmoefeito, passa pela utilizacao de imagens nas faces dos objectos - texture mapping.

– A imagem fornecida para utilizar e chamada de texture– Cada elemento da imagem que e aplicado numa face e chamado texel– O processo esticar a imagem a face do objecto e denominada de filtering

Fog: A adicao de nevoeiro podera contribuir para a credibilidade da imagem.

6

Page 8: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Blenging & Transparency: Blending consiste na mistura de objectos ou cores. Atraves da sobreposicaode imagens ou objectos, e possıvel dar a sensacao de transparencia ou reflexao.

Antialiasing: O Aliasing e provocado pelo processo de rastering nos monitores. Um processo semelhanteao blenging dos pixels com a cor de fundo confere-lhe um aspecto suave.

1.3 Transformacoes Geometricas

As transformacoes geometricas em OpenGL sao efectuadas por intermedio de operacoes matriciais. Transformacoesconsecutivas resultam na multiplicacao de varias matrizes. Deste modo, duas transformacoes consecutivas saoacumulativas.

As transformacoes geometricas podem ser de tres tipos: viewing, modeling e projection.A terminologia utilizada no OpenGL para as transformacoes e:

ViewingEspecificacao da Localizacao do Observador (ou camara)

ModelingLocalizacao de Objectos na Cena

ModelViewDualidade de transformacoes Viewing e Modeling

ProjectionModificacoes no clip e size do volume (clipping volume) da cena

ViewportRelacionado com a escala do output final para o utilizador

1.3.1 Eye Coordinates

As coordenadas do olho representam um ponto virtual absoluto (independente de qualquer transformada), ondeesta localizado o observador.

Na Figura 1.3a, olhamos o nosso sistema cartesiano 3D de frente (o eixo-z nao e visıvel). Na Figura 1.3b oeixo-x e eixo-y foram rodados. A medida que o valor de z aumenta, os objectos ficam mais perto do observador.

1.3.2 Viweing Transformations

As primeiras transformacoes a serem executadas, sao as relacionadas com o ponto para onde o observador esta aolhar.

Por omissao, a nossa cena contem um observador localizado no ponto O0 = [x = 0, y = 0, z = 0] e a direccaodo olhar aponta para a parte negativa do eixo z de tal forma que os objectos desenhados com z > 0 ficamsituados nas costas do utilizador.

7

Page 9: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Figura 1.3: Duas perspectivas diferentes (eye coordinates)

1.3.3 Modeling Transformations

Este tipo de transformacoes (Figura 1.4), sao aplicadas aos objectos no nosso model (modelo 3D).

Figura 1.4: Transformacoes do Modelo (modeling)

A ordem das transformacoes dita o aspecto final da nossa cena uma vez que as transformacoes sao acumulativas.Na Figura 1.5 e mostrada a diferenca na ordem da aplicacao de duas transformacoes, ainda que com os mesmosvalores.

Dualidade Model/Viewing

A dualidade e utilizada porque no fim de contas, transformacoes efectuadas no model ou no viewing tem umefeito semelhante. A diferenca e entre mover a referencia das coordenadas na nossa direccao (Figura 1.6a) ouaproximarmos-nos da referencia (Figura 1.6b), o que representa o mesmo resultado.

Basicamente, uma transformacao viewing e semelhante a uma transformacao modeling que aplicamos a umobjecto virtual - o observador.

1.3.4 Projection Transformations

As transformacoes feitas ao sistema de projeccoes configuram o volume da area visıvel da nossa cena.Os principais tipos de projeccoes sao:

Orthographic ProjectionNeste tipo de projeccao os objectos sao desenhados no ecra usando linhas paralelas para a definicao

da perspectiva, o que implica que os objectos apresentam todos tamanho semelhante independentemente dadistancia.

Perspective ProjectionA aparencia dos objectos e mais semelhante a realidade. Objectos mais distantes aparecem mais pequenos

que objectos mais proximo. Neste perspectiva, linhas paralelas convergem num ponto distante.

8

Page 10: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Figura 1.5: Transformacoes: rotacao/translacao e translacao/rotacao

Figura 1.6: Dualidade Model/Viewing

Figura 1.7: esquerda: Ortogonal, direita: Perspectiva

9

Page 11: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

1.3.5 Viewport Transformations

No final do pipeline das transformacoes, obtemos uma imagem 2D que tera que ser mostrada na nossa janela.As transformacoes de viewport definem a porcao do nosso “universo” 3D que e desenhada na janela e onde.

10

Page 12: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Capıtulo 2

Princıpios Basicos de Programacao 3D

2.1 Sistemas de Coordenadas

Antes de ser possıvel colocar um objecto numa cena e preciso um quadro de referencia. Num dispositivo flat alocalizacao e feita com recurso a dois valores, um deles normalmente refere-se a distancia desde o lado esquerdo eo outro refere-se a distancia desde o topo do ecra.

Nas APIs 3D, existem varios sistemas de coordenadas. Ao inicializar a nossa cena o sistema de coordenadasescolhido, define a forma como os valores fornecidos sao mapeados em pixels no ecra.

2.1.1 Coordenadas Cartesianas - 2D

O sistema de coordenadas 2D mais utilizado e o sistema cartesiano. O sistema e composto por uma coordenadasx que define a distancia horizontal a origem ([x = 0, y = 0]) e uma coordenada y que define a distancia vertical aorigem (Figura 2.1).

Figura 2.1: Plano Cartesiano

Clipping de Coordenadas

Antes de comecarmos a desenhar pontos e linhas e necessario dizer a API que zona do sistema cartesiano deveraaparecer na janela. Esta zona e normalmente denominada de clipping region (Figura 2.2).

2.1.2 Viewport - Mapeamento de coordenadas para pixels

Raramente as coordenadas cartesianas do nosso sistema, correspondem ao tamanho em pixels da janelas. Enecessario fazer um mapeamento da zona visıvel do nosso sistema de coordenadas para o espaco mostrado empixels na janela. Este mapeamento e chamado de viewport.

Na Figura 2.3 o tamanho do viewport e o dobro da area de clipping. Na Figura 2.4 o clipping volume, ocupaapenas uma zona da janela.

11

Page 13: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Figura 2.2: Duas zonas de clipping diferentes

Figura 2.3: Viewport com o dobro da area de clipping

Figura 2.4: Viewport com a mesma dimensao da area de clipping

12

Page 14: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

2.1.3 O Vertex (vertice)

Um objecto numa imagem, pode ser decomposto em formas mais pequenas normalmente denominadas deprimitives. As primitives podem ser entidades ou superfıcies (pontos, linhas, planos ou polıgonos) no espaco. Ocubo nas imagens da introducao, sao compostos de seis faces quadradas. Cada canto destes quadrados, ou dequalquer outra primitive e denominado de vertex. Cada vertex e representado por uma coordenada. O processode construir geometria em 3D, consiste num jogo de liga-os-pontos.

2.1.4 Coordenadas Cartesianas 3D

Nas coordenadas cartesianas 3D, ao sistema bidimensional, adicionamos profundidade. Um terceiro eixo (z) eperpendicular aos eixos x e y. A Figura 2.5 mostra o nosso sistema cartesiano com uma rotacao (y e rodadopara a esquerda, x rodado para baixo), caso contrario o eixo z nao estaria visıvel.

Figura 2.5: Coordenadas Cartesianas 3D

2.2 Projeccoes: 3D → 2D

Por mais que tentemos convencer o olho da sensacao de imagem 3D, o nosso display sera 2D. O nosso sistema3D e mostrado em 2D com ajuda de trigonometria e operacoes matriciais simples.

As coordenadas 3D sao “achatadas” ou projectadas numa superfıcie 2D (o fundo da janela). O resultadoobtido e semelhante ao de pintar os contornos de um objecto num vidro de uma janela (Figura 2.6).

O tipo de projeccao especifica como o volume deve ser transformado na janela.

Figura 2.6: Projeccao 2D de uma imagem 3D

2.2.1 Projeccoes Ortogonais

Numa projeccao ortogonal, o volume visıvel e definido com recurso a uma superfıcie rectangular. Qualquerobjecto fora do volume nao e desenhado. Os objectos aparentam todos o mesmo aspecto, independentemente daprofundidade em que se encontram.

A Figura 2.7 ilustra o volume visıvel (viewing volume) definido especificando os clipping planes - far, near,left, right, top e bottom. O conjunto das projeccoes dos planos sao entao projectados numa imagem 2D.

13

Page 15: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Figura 2.7: O clipping volume de uma projeccao ortogonal

2.2.2 Projeccoes em Perspectiva

Uma projeccao em perspectiva e em tudo semelhante a ortogonal. Os objectos mais distantes sao, no entantomais pequenos, dando a sensacao de profundidade. O viewing volume e parecido com uma piramide com a partesuperior cortada. A forma resultante e denominada frustrum (Figura 2.8). Esta projeccao e a que confere ummaior realismo.

Figura 2.8: O clipping volume (frustrum) de uma projeccao em perspectiva

14

Page 16: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Capıtulo 3

Introducao ao OpenGL

O OpenGL pode ser definido como uma interface de software para dispositivos graficos. Consiste de uma bibliotecagrafica de 3D e modeling. E altamente portable (suportada em varios sistemas operativos e dispositivos). Tirapartido da aceleracao hardware (onde disponıvel), conseguindo nıveis de desempenho elevados.

Mais do que uma linguagem ou uma simples API, define um standard.

3.1 O pipeline OpenGL

O processo de desenho com recurso a OpenGL, e feito com recurso a um conjunto de passos (stages). O nomepipeline sintetiza numa palavra esta topologia (Figura 3.1).

Figura 3.1: Versao simplificada do pipeline OpenGL

Os comandos feitos com recurso a API sao colocados num fila denominada command buffer (dados dosvertices (vertex ), texturas, . . . ). Quando e dada uma ordem de processamento ao buffer (flush), quer de formaprogramatica ou pelo driver, os dados sao passados ao passo seguinte na pipeline.

No passo transform and lighting, sao efectuadas as transformacoes matematicas e geometricas que permitemo calculo da localizacao e orientacao dos nossos pontos e objectos.

Na fase de rasterizacao a imagem e criada a partir dos dados de geometria, textura e cor do passo anterior.A imagem resultante e entao colocada no frame buffer que pode ser considerado como a memoria do nossodispositivo grafico que finalmente a coloca no ecra.

3.2 Tipos de Dados

A fim de garantir portabilidade, o OpenGL define os seus proprios tipos de dados (data types). Ao faze-lo,permite ao developer, abstrair-se dos pormenores relacionados com os compiladores de cada sistema operativo.

A cada tipo de dados corresponde um sufixo. Este sufixo sera utilizado a fim de identificar o tipo de dadosde cada funcao da API. A Tabela 3.1 mostra os tipos de dados, a sua representacao em C e o sufixo utilizado nanomenclatura OpenGL.

3.2.1 Nomes de Funcoes - Convencao

As funcoes OpenGL seguem uma nomenclatura que ajuda na identificacao da biblioteca, comando, numero deargumentos e tipo de dados a utilizar nesses argumentos (Figura 3.2), segundo a sintaxe:

< biblioteca >< comando >< argumentos >< tipo >

O exemplo em cima e uma funcao da biblioteca gl, o comando Color, que recebe 3 argumentos do tipo float(f).

15

Page 17: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Tipo Interno OpenGL Tipo em C Sufixo

GLbyte signed char bGLshort short sGLint, GLsizei long lGLfloat, GLclampf float fGLdouble, GLclampd double dGLubyte, GLboolean unsigned char ubGLushort unsigned short usGLuint, GLenum, GLbitfield unsigned long ui

Tabela 3.1: Tipos de dados OpenGL

Figura 3.2: Funcao OpenGL

3.3 JOGL - Java OpenGL

O JOGL e um binding para a API OpenGL desenvolvido em Java. Um binding representa uma forma de utilizarfuncionalidades de uma biblioteca (nativa ou nao) do sistema operativo com base numa linguagem diferente daque foi utilizada nessa biblioteca. Para o caso do JOGL, a biblioteca OpenGL (ficheiro .dll no Windows, .so noLinux) do sistema e disponibilizada na linguagem de programacao Java.

Uma das formas mais comuns de utilizar a API consiste na criacao de uma classe que implementa a interfaceGLEventListener. Esta interface define os metodos:

void init(GLAutoDrawable drawable );

void dispose(GLAutoDrawable drawable );

void display(GLAutoDrawable drawable );

void reshape(GLAutoDrawable drawable ,

int x, int y,

int width , int height );

init(GLAutoDrawable drawable)

Este metodo sera invocado imediatamente depois de o contexto OpenGL ser inicializado. Normalmente eutilizado para inicializar a nossa cena, tal como configurar luzes.

dispose(GLAutoDrawable drawable)

Este metodo e invocado aquando da libertacao de recursos no contexto OpenGL. A chamada tem lugarimediatamente antes de o contexto OpenGL ser destruıdo.

display(GLAutoDrawable drawable)

Invocado pelo contexto OpenGL para inicializar o processo de rendering. No caso de double buffering (ver . . . ),a chamada a este metodo troca automaticamente os buffers.

16

Page 18: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

reshape(GLAutoDrawable drawable, int x, int y, int width, int height)

Chamada sempre que a janela (ou componente) contendo o viewport, sao redimensionados. Permite a actualizacaoe ajuste do viewport ou da visualizacao em geral, de forma a adequa-lo ao novo tamanho da janela.

3.4 The State Machine

O desenho em OpenGL e conseguido com a ajuda de um conjunto de variaveis e atributos que vao sendo definidosao longo da execucao. No entanto, nao e facil ao developer estar consciente de todos esses elementos aquando daadicao de nova geometria.

Estes elementos fazem parte estado no pipeline. O OpenGL funciona como uma maquina de estados quepermite gerir o estado destes elementos.

Utilizando a maquina de estados, o OpenGL permite que no mesmo desenho possamos ter, por exemplo,objectos desenhados com lighting e outros sem lighting activando e desactivando uma simples flag.

gl.glEnable(GL.GL_LIGHTING);

// ...

// draw geometry with lighting

gl.glDisable(GL.GL_LIGHTING);

// ...

// draw geometry without lighting

A verificacao do estado de uma determinada flag pode ser feito com recurso a gl.glIsEnabled(flag).

3.5 O pipeline de Transformacoes

As transformacoes mais comuns sao feitas na projection matrix e na modelview matrix.O caminho desde as coordenadas de simples vertex ate a imagem no ecra esta descrito na Figura 3.3.

Figura 3.3: Pipeline de transformacoes de vertices

No primeiro passo, cada vector e convertido numa matrix 1× 4, contento as coordenadas [x, y, z] e um factorde escala1. O vertex e entao multiplicado pela matriz de transformacoes Modelview, que contem as transformadasrelacionadas com o observador. O resultado e multiplicado pela matriz de transformacoes Projection, o queelimina todos os objectos fora do nosso volume de clipping2. No passo seguinte, as coordenadas resultantes saodivididas pelo factor w do vertex, com o objectivo de normalizar as coordenadas.

1Utilizado nas funcoes de vectores com 4 argumentos, ex.: glVertex4f(x, y, z, w)2O que representa uma mais-valia em termos de processamento

17

Page 19: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

O passo final consiste no mapeamento do nosso sistema de coordenadas a um plano 2D pelas transformacoesna matriz de transformacoes Viewport.

3.5.1 Matriz Modelview

Felizmente para os utilizadores da API OpenGL, uma grande parte das transformadas e disponibilizada sob aforma de um conjunto de funcoes de alto nıvel. Ainda que estas funcoes de alto nıvel permitam ao utilizadorabstrair-se das operacoes matematicas, existe a possibilidade de efectuar operacoes avancadas com matrizesespecıficas1

Translation

Funcao de Translacao:

GL.glTranslatef(

float x, float y, float z

)

A funcao recebe como argumentos os valores da translacao no x, y e z. O pseudo-codigo seguinte e ilustradona Figura 3.4.

GL2 gl = drawable.getGL (). getGL2 ();

GLUT glut = new GLUT ();

// Translacao de y=10

gl.glTranslatef (0f, 10f, 0f);

// Desenhar o cubo ...

glut.glutWireCube (10f);

Figura 3.4: Translation

Rotation

Funcao de Rotacao:

GL.glRotatef(

float angle ,

float x, float y, float z

)

A funcao recebe como argumentos, o angulo de rotacao. Os valores x, y e z, representam um eixo arbitrariosobre o qual deve ser feita a rotacao2. O pseudo-codigo seguinte e ilustrado na Figura 3.5.

GL2 gl = drawable.getGL (). getGL2 ();

GLUT glut = new GLUT ();

// Rodar 45 em Torno do vector Vr=[1,1,1]

gl.glRotatef (45f, 1f, 1f, 1f);

1Consultar na referencia da API - glLoadMatrix*2Por exemplo: para obter um eixo perpendicular ao eixo− y basta fornecer o vector Vy =[0f, 1f, 0f]

18

Page 20: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

// Desenhar o cubo ...

glut.glutWireCube (10f);

Figura 3.5: Rotation

Scaling

Funcao de Escala:

GL.glScalef(

float x, float y, float z

)

A funcao recebe como argumentos os factores de escala em cada um dos eixos x, y e z. O pseudo-codigoseguinte e ilustrado na Figura 3.6.

GL2 gl = drawable.getGL (). getGL2 ();

GLUT glut = new GLUT ();

// Escalar x=2*x, y=1*x e z=2*z

gl.glScalef (2f, 1f, 2f);

// Desenhar o cubo ...

glut.glutWireCube (10f);

Figura 3.6: Scale

3.5.2 A Matriz Identidade (Identity Matrix)

Ao tentar conseguir o resultado na Figura 3.7, podemos ser tentados a escrever o codigo:

GL2 gl = drawable.getGL (). getGL2 ();

GLUT glut = new GLUT ();

// Translate y=10

19

Page 21: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Figura 3.7: Duas Esferas

gl.glTranslatef (0f, 10f, 0f);

// Desenhar a primeira esfera

glut.glutSolidSphere (1f, 15, 15);

// Translate x=10

gl.glTranslatef (10f, 0f, 0f);

// Desenhar a segunda esfera

glut.glutSolidSphere (1f, 15, 15);

No entanto, o resultado final sera mais parecido com o da Figura 3.8.

Figura 3.8: Duas Esferas (continuacao)

Isto deve-se ao facto de as transformacoes no pipeline OpenGL serem acumulativas. O que aconteceu de facto foiuma translacao de 10 no eixo-y seguida do desenho da primeira esfera (tudo correcto), depois movemos-nos 10 noeixo-x sem voltar a origem, o que provocou que a esfera final aparecesse com uma translacao de [x = 10, y = 10].

Para obter o efeito da Figura 3.7, e preciso repor o sistema de coordenadas original (uma especie de reset).Isto pode ser obtido pelo carregamento da indentity matrix. O nosso codigo ficaria entao mais parecido com:

GL2 gl = drawable.getGL (). getGL2 ();

GLUT glut = new GLUT ();

// Escolher a Matriz de Transformacoes

// MODELVIEW e fazer um reset inicial

gl.glMatrixMode(GL2.GL_MODELVIEW );

gl.glLoadIdentity ();

// Translate y=10

gl.glTranslatef (0f, 10f, 0f);

// Desenhar a primeira esfera

glut.glutSolidSphere (1f, 15, 15);

20

Page 22: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

// reset !

gl.glLoadIdentity ();

// Translate x=10

gl.glTranslatef (10f, 0f, 0f);

// Desenhar a segunda esfera

glut.glutSolidSphere (1f, 15, 15);

3.6 Projeccoes

Orthographic Projections

A perspectiva ortogonal consiste de um volume com os lados todos iguais (Figura 2.7). Este tipo de projeccao eutilizada normalmente em software CAD, onde e necessaria uma percepcao das dimensoes reais dos objectos. Noentanto, a sua aproximacao a realidade e um pouco vaga (Figura 3.9).

(a)

Figura 3.9: Ortogonal- Normal/Lado/Frente

A funcao que permite configurar uma projeccao ortogonal, tem o seguinte prototipo:

GL2.glOrtho(

double left , double right ,

double bottom , double top ,

double near , double far

)

Os argumentos representam as distancia ate a origem do sistema de coordenadas das faces - esquerda (left),direita (right), fundo (bottom), topo (top), a face mais proxima (near) e mais distante (far) do observador(Figura 3.10).

Figura 3.10: Projeccao Ortogonal

O volume de desenho (viweing volume), corresponde ao volume compreendido entre os 6 planos do cubo.

Perspective Projections

Ao contrario da perspectiva ortogonal, numa projeccao de perspectiva, os objectos mais distantes sao “encolhidos”.O viewing volume e agora uma especie de piramide com a parte superior cortada - denominada frustrum (Figura3.11).

21

Page 23: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Figura 3.11: Frustrum

A definicao deste frustrum pode ser feita com recurso a funcao glPerspective1:

GL.glPerspective(

double fovy , fouble aspect ,

double zNear , doule zFar

);

Os parametros da funcao sao o campo de visao (field of view) expresso em graus (angulo vertical), o aspectratio da altura e largura e as distancias ao plano mais proximo e mais afastado do volume de visualizacao(viewing volume), como mostra a Figura 3.12.

Figura 3.12: Frustrum utilizando glPerspective

Podemos comparar a diferenca em relacao a perspectiva ortogonal, analisando a Figura 3.13.

(a)

Figura 3.13: Perspectiva - Normal/Lado/Frente

3.7 Camaras e Actores

Agora que temos o nosso cenario configurado, seria interessante conseguirmos movimentar-nos, nos os observadores.O conceito de camara ou actor nao existe realmente no OpenGL, o nome serve apenas como metafora para

facilitar a compreensao do conceito.A forma de mimetizarmos esta funcionalidade passa pela utilizacao da funcao glLookAt:

GLU.gluLookAt(

float eyex , float eyey , float eyez ,

float atx , float aty , float atz ,

float upx , float upy , float upz

);

1Existe a funcao glFrustrum, no entanto a funcao glPerspective e mais intuitiva

22

Page 24: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Figura 3.14: glLookAt

Os argumentos desta funcao sao, a posicao do observador - Eye(x, y, z), o ponto para o qual o observadoresta a olhar At(x, y, z) e o vector que determina qual a direccao vertical do observador VUP (x, y, z) (Figura3.14).

23

Page 25: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Capıtulo 4

Primitivas Geometricas e Buffers

Utilizando ferramentas ou bibliotecas de desenho grafico convencionais, o elemento mais basico e o pixel.Basicamente colocamos um determinado pixel na tela com uma determinada cor e uma posicao especıfica.

Desenhar em OpenGL e um pouco diferente, nao desenhamos numa determinada especıfica no ecra, mas simem coordenadas no nosso viewing volume. A forma como a nossa cena aparece no ecra esta a cargo do OpenGL.

As seccoes seguintes descrevem como sao desenhadas as varias primitivas geometricas com recurso a APIOpenGL.

4.1 O ponto 3D - (Vertex)

A funcao utilizada para desenhar um ponto 3D na nossa cena e a funcao glVertex. O ponto desenhado dependedo numero de argumentos e tipo utilizados na funcao.

Figura 4.1: Ponto P(50,50,50)

Por exemplo, para obter o ponto na Figura 4.1, podemos utilizar:

gl.glVertex3f (50f, 50f, 0f);

Ou ainda:

gl.glVertex2f (50f, 50f);

Podemos ainda especificar o factor de escala w (por omissao 1f) utilizando o codigo:

gl.glVertex4f (50f, 50f, 0f, 1f);

4.2 Primitivas

Um vertex por si so no espaco, nao tem grande significado. Um ponto pode representar a interseccao de duaslinhas ou curvas ou entao o canto de um polıgono ou solido.

24

Page 26: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

A forma como um conjunto de pontos e interpretado no nosso espaco 3D e chamada de primitiva. O OpenGLtem 10 tipos de primitivas.

Para desenhar com uma determinada primitiva, utilizamos a funcao glBegin para iniciar, desenhamos osnossos pontos e terminamos utilizando o glEnd para terminar a utilizacao da primitiva.

Para desenhar varios tipos de primitivas, teremos que utilizar varios blocos glBegin/glEnd, por exemplo:

gl.glBegin(GL_POINTS );

gl.glVertex3f (0.0f, 0.0f, 0.0f);

gl.glVertex3f (50.0f, 50.0f, 50.0f);

gl.glEnd ();

4.2.1 Pontos: GL POINTS

Esta primitiva e a mais simples de todas: pontos. Os vertices desenhados dentro de um bloco GL POINTS,aparecem como pontos.

Figura 4.2: Desenho utilizando a primitiva GL POINTS

O codigo utilizado para obter a Figura 4.2 sera:

float GL_PI = 3.1415f;

// Comecar a Desenhar Pontos

gl.glBegin(GL2.GL_POINTS );

float angle , x, y, z = -50.0f;

for(angle=0f; angle <=(2f*GL_PI )*3f; angle +=0.1f) {

x = 50f * (float) Math.sin(angle);

y = 50f * (float) Math.cos(angle);

gl.glVertex3f(x, y, z);

z += 0.5f;

}

// Terminar Pontos

gl.glEnd ();

O exemplo acima faz variar o x, y de forma a descrever um circulo no plano x, y, onde x = cos(angle) ey = sin(angle). A medida que o angle varia, vamos aumentando o z por forma a desenhar uma espiral (Figura4.3).

Tamanho de um Ponto

O tamanho de um ponto e 1pixel, por omissao. Para alterar o tamanho do ponto, podemos utilizar a funcaoglPontSize(float pSize). Dependendo da plataforma, os valores mınimo e maximo possıvel para o tamanhodo ponto podem variar. Para obter os valores possıveis para o mınimo, maximo e step1, podemos utilizar:

float [] sizes = new float [2];

gl.glGetFloatv(GL2.GL_POINT_SIZE_RANGE , sizes , 0);

1A mınima diferenca possıvel entre tamanhos consecutivos

25

Page 27: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Figura 4.3: Explicacao da espiral de pontos

float [] step = new float [1];

gl.glGetFloatv(GL2.GL_POINT_SIZE_GRANULARITY , step , 0);

O array size (float[] de tamanho 2) ira conter os valores mınimo (PSmin = size[0]) e maximo (PSmax =size[1]) possıveis para o tamanho de um ponto, o array step (float[] de tamanho 1) ira conter o valor dadiferenca mınima (PSstep =step[0]) possıvel entre tamanhos do ponto.

Os valor passado a funcao glPointSize, devera estar compreendido entre PSmin e PSmax, sendo a diferencamınima entre eles de PSstep.

Assim ao utilizar o codigo em baixo em conjunto com os arrays do exemplo anterior, obtemos a Figura 4.4.

float GL_PI = 3.1415f;

float angle , x, y, z = -50.0f;

float psize = sizes [0];

for(angle=0f; angle <=(2f*GL_PI )*3f; angle +=0.1f) {

x = 50f * (float) Math.sin(angle);

y = 50f * (float) Math.cos(angle);

gl.glPointSize(psize );

psize += step [0];

// Comecar Pontos

gl.glBegin(GL2.GL_POINTS );

gl.glVertex3f(x, y, z);

// Terminar Pontos

gl.glEnd ();

z += 0.5f;

}

A funcao glPointSize foi invocada fora do bloco glBegin/glEnd. Algumas funcoes nao podem ser invocadasdentro destes blocos. O tamanho do ponto afecta todos os pontos desenhados para a frente, mas antes doglBegin(GL POINTS), o desenho de pontos ainda nao foi iniciado, daı ser invocado fora.

De modo geral no OpenGL, se os valores sao especificados fora do intervalo possıvel, eles sao truncados aoreferido intervalo. Assim para valores acima do permitido, o valor maximo e forcado e para valores abaixo dopermitido, o valor mınimo e forcado.

4.2.2 Linhas: GL LINES

Utilizando a primitiva GL LINES, entre dois vertices e desenhada uma linha.

gl.glBegin(GL_LINES );

gl.glVertex3f (0.0f, 0.0f, 0.0f);

26

Page 28: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Figura 4.4: Pontos com varios tamanhos

gl.glVertex3f (50.0f, 50.0f, 50.0f);

gl.glEnd ();

Porque as linhas sao so desenhadas entre 2 pontos, ao utilizar um numero ımpar de pontos, o ultimo eignorado. O codigo em baixo ilustra o desenho com o uso da primitiva GL LINES:

float z = 0.0f, angle , x, y;

// Comecar Linhas

gl.glBegin(GL2.GL_LINES );

for(angle = 0.0f; angle <= GL_PI; angle += (GL_PI /20.0f)) {

// Primeira metade do circulo

x = 50f * (float)Math.sin(angle);

y = 50f * (float)Math.cos(angle);

gl.glVertex3f(x, y, z);

// Segunda metade do circulo angle+ πx = 50f * (float) Math.sin(angle + GL_PI);

y = 50f * (float) Math.cos(angle + GL_PI);

gl.glVertex3f(x, y, z);

}

// Terminar Linhas

gl.glEnd ();

O resultado do codigo em cima e o da Figura 4.5.

4.2.3 Tiras de Linha: GL LINE STRIP

Esta primitiva permite definir quais os vertices pelos quais a linha deve passar.

gl.glBegin(GL_LINE_STRIP );

gl.glVertex3f (0f, 0f, 0f); // V0

gl.glVertex3f (50f, 50f, 0f); // V1

gl.glVertex3f (50f, 100f, 0f); // V2

gl.glEnd ();

O codigo em cima desenharia no plano x, y os pontos da Figura 4.6.

4.2.4 Loops de Linha: GL LINE LOOP

Da mesma forma que o GL LINE STRIP, podemos utilizar o GL LINE LOOP para definir os pontos pelos quais umalinha passa, mas desta vez, uma ultima linha e desenhada entre o ultimo vertice e o primeiro.

27

Page 29: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Figura 4.5: Desenho com GL LINES

Figura 4.6: Tiras de Linhas: GL LINE STRIP

Figura 4.7: Loops de Linhas: GL LINE LOOP

28

Page 30: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

A Figura 4.7 mostra os mesmos vertices da Figura 4.6 desenhados com a primitiva GL LINE LOOP.

Exemplo: Aproximacao a Curvas com recurso a Tiras de Linha

Utilizando o exemplo da Figura 4.2, onde desenhamos uma espiral de pontos e substituindo a primitiva GL POINTSpela primitiva GL LINE STRIP, podemos fazer uma aproximacao a uma espiral. Ao diminuir o espaco entre ospontos podemos tornar a sensacao de curva ainda mais real.

float GL_PI = 3.1415f;

// Comecar a Tiras de Linha

gl.glBegin(GL2.GL_LINE_STRIP );

float angle , x, y, z = -50.0f;

for(angle=0f; angle <=(2f*GL_PI )*3f; angle +=0.1f) {

x = 50f * (float) Math.sin(angle);

y = 50f * (float) Math.cos(angle);

gl.glVertex3f(x, y, z);

z += 0.5f;

}

// Terminar Tiras de Linha

gl.glEnd ();

Ao utilizar o codigo em cima, obtemos o resultado na Figura 4.8.

Figura 4.8: Espiral com Tiras de Linha

Largura de uma Linha

Da mesma forma que podemos definir o tamanho de um ponto, podemos definir o tamanho de uma linha pelautilizacao da funcao glLineWidth. Da mesma forma o argumento tem um valor mınimo, maximo e um step.

float [] widths = new float [2];

gl.glGetFloatv(GL2.GL_LINE_WIDTH_RANGE , widths , 0);

float [] step = new float [1];

gl.glGetFloatv(GL2.GL_LINE_WIDTH_GRANULARITY , step , 0);

O array widths (float[] de tamanho 2) ira conter os valores mınimo (LWmin = widths[0]) e maximo(LWmax = widths[1]) possıveis para a largura de uma linha, o array step (float[] de tamanho 1) ira contero valor da diferenca mınima (LWstep =step[0]) possıvel entre larguras de linhas.

Os valor passado a funcao glLineWidth, devera estar compreendido entre LWmin e LWmax, sendo a diferencamınima entre eles de LWstep.

29

Page 31: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

float y, curwidth = widths [0];

gl.glColor3f (1f, 1f, 1f);

for(y=-90f; y<90f; y+=20f) {

// Alterar a Largura

gl.glLineWidth(curwidth );

// Comecar Tiras

gl.glBegin(GL2.GL_LINE_STRIP );

gl.glVertex2f (-80f, y);

gl.glVertex2f (80f, y);

// Terminar Tiras

gl.glEnd ();

curwidth += 1f;

}

Com o codigo em cima, obtemos o desenho na Figura 4.9.

Figura 4.9: Linhas de Varias Larguras

4.2.5 Padroes de Linha:GL LINE STIPPLE

O desenho de linhas baseadas em padroes e conseguindo activando o stippling, o que pode ser feito utilizando:

gl.glEnable(GL2.GL_LINE_STIPPLE );

O padrao da linha e estabelecido com a ajuda da funcao:

gl.glLineStipple(

int factor ,

short pattern

);

O padrao consiste de um valor de 16 bits (short) que representa cada segmento da linha. Cada bit representaum elemento nesse segmento de linha que podera estar on ou off.

Por omissao cada bit representa um pixel no nosso desenho. O valor de factor define o numero de bits quecada pixel representa. O bit menos significativo (bit 0 - lado direito) e utilizado para o inicio da linha comomostra Figura 4.10.

float y;

short pattern = 0x5555;

int factor = 1;

gl.glColor3f (1f, 1f, 1f);

for(y=-90f; y<90f; y+=20f) {

// Alterar o Stipple

30

Page 32: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Figura 4.10: Padrao Stipple

gl.glLineStipple(factor++, pattern );

// Comecar Linhas

gl.glBegin(GL2.GL_LINE_STRIP );

gl.glVertex2f (-80f, y);

gl.glVertex2f (80f, y);

// Terminar Linhas

gl.glEnd ();

}

O pattern 0x5555 e um valor hexadecimal, que em binario representa 0101010101010101, o que resultaranuma linha dotted. A medida que o ciclo avanca vamos aumentando o factor, pelo que a linha passa de dottedpara dashed de forma progressiva, como mostra a Figura 4.11.

Figura 4.11: Desenho com recurso a stippling

4.2.6 Triangulos: GL TRIANGLES

Ate aqui as formas criadas com recurso as primitivas de pontos e linhas, nao contem qualquer preenchimento.Para desenhar superfıcies solidas com preenchimento e necessario utilizar polıgonos.

Um polıgono e uma forma fechada que pode estar ou nao preenchida com a cor actual de preenchimento. EmOpenGL, todo o desenho de solidos assenta na composicao baseada em polıgonos.

O polıgono mais simples possıvel e o triangulo e pode ser desenhado com recurso a primitiva GL TRIANGLES.

gl.glBegin(GL2.GL_TRIANGLES );

31

Page 33: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

gl.glVertex2f (0f, 0f); // V0

gl.glVertex2f (25f, 25f); // V1

gl.glVertex2f (50f, 0f); // V2

gl.glVertex2f (-50f, 0f); // V3

gl. glVertex2f (-75f, 50f); // V4

gl.glVertex2f (-25f, 0f); // V5

gl.glEnd ();

O codigo acima desenha dois triangulos preenchidos com a cor de preenchimento actual (definida por glColor)no plano x, y (Figura 4.12).

Figura 4.12: Desenho de Triangulos

Winding

A ordem pela qual os vertices sao desenhados, define o lado para que esta virado o polıgono por eles definido.Assim o primeiro triangulo (V0, V1, V2) e desenhado no sentido dos ponteiros do relogio (clockwise) esta decostas para o observador, enquanto que o segundo triangulo (V3, V4, V5) foi desenhado no sentido inverso(counterclockwise), esta de frente para o observador (Figura 4.13).

Figura 4.13: Winding

O conceito de winding e importante quando estamos a preencher um determinado polıgono com caracterısticasdiferentes a frente e atras.

Para alterar o comportamento do winding podemos forcar o caminho clockwise a representar a face de umpolıgono activando a flag GL CW:

gl.glEnable(GL2.GL_CW );

Para restaurar o comportamento por omissao activamos a flag GL CCW.

4.2.7 Tiras de Triangulos:GL TRIANGLE STRIP

O desenho da maioria das superfıcies consiste num conjunto de triangulos. O desenho dessas superfıcies pode serfacilitado pela utilizacao da primitiva de desenho de triangulos GL TRIANGLE STRIP. Os triangulos sao desenhadosentre os vertices a medida que eles sao especificados (Figura 4.14).

32

Page 34: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Figura 4.14: Tiras de Triangulos

No caso do GL TRIANGLE STRIP, o winding e forcado para counterclockwise independentemente da ordem dedesenho.

Uma vantagem evidente deste metodo de desenho e o facto de, depois dos tres primeiros vertices, o desenhode triangulos adicionais so precisa de mais um vertice por triangulo.

4.2.8 Triangle Fans:GL TRIANGLE FANS

Nesta primitiva, os triangulos sao desenhados em volta de um ponto central, definido pelo primeiro vertice aser desenhado (V0). Depois dos primeiros tres vertices definirem o primeiro triangulo, todos os restantes saodefinidos com apenas um vertice (Figura 4.15).

Figura 4.15: Triangle Fans

4.3 Outras Primitivas

A utilizacao de triangulos na construcao de objectos em OpenGL e preferida pelo facto da maior parte do hardwareacelerar o seu desenho. No entanto a utilizacao de outras formas que nao o triangulo podera ser pertinente.

4.3.1 Quadrilateros: GL QUADS

A primitiva GL QUADS permite desenhar um polıgono quadrilatero com recurso a quatro vertices. Os verticesteriam que ser complanares (Figura 4.16).

Figura 4.16: Quadrilateros

33

Page 35: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

4.3.2 Tiras de Quadrados:GL QUAD STRIP

Da mesma forma que a primitiva GL TRIANGLE SRTIP, a primitiva GL QUAD STRIP permite desenhar uma tira dequadrilateros pela adicao de vertices aos quatro primeiros (Figura 4.17).

Figura 4.17: Tiras de Quadrilateros

4.3.3 Polıgonos: GL POLYGON

Esta primitiva permite o desenho de polıgonos com um numero variado de lados. No entanto, a restricao dosvertices serem complanares mantem-se (Figura 4.18).

Figura 4.18: Desenho de Polıgonos

Esta restricao pode ser evitada pela utilizacao da primitiva GL TRIANGLE FAN em lugar da utilizacao daprimitiva GL POLYGON.

4.3.4 Preenchimento de Polıgonos

As duas formas mais utilizadas para preenchimento de polıgonos sao, a utilizacao de cores solidas ou a aplicacaode texturas. No entanto, da mesma forma que utilizamos os padroes de preenchimento de linhas, podemosutilizar padroes de preenchimento (stippling) de polıgonos.

O padrao e agora definido por uma matriz on/off de 32× 32 bits (Figura 4.19).Para construir a mascara que vai ser utilizada para fazer o stippling utilizamos um array de 32× 4 bytes1.

Em vez de um array bidimensional e utilizado um array simples.O padrao pode ser aplicado activando o stippling de polıgonos e utilizando um array do tipo descrito em

cima:

byte[] pattern = {

0x00 , 0x00 , 0x00 , 0x00

...

0x00 , 0x00 , 0x10 , 0x00

};

gl.glEnable(GL2.GL_POLYGON_STIPPLE );

gl.glPolygonStipple(pattern );

Mais uma vez o array e definido ao contrario, sendo o bit menos significativo, o primeiro bit da imagem, ouseja, a primeira linha corresponde a ultima linha da imagem.

11byte = 8bit =⇒ 32× 4byte =⇒ 32× 32bit

34

Page 36: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Figura 4.19: Padrao de Preenchimento de Polıgonos

Figura 4.20: Exemplo de Stippling de Polıgonos

35

Page 37: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

4.3.5 Regras na Criacao de Polıgonos

1. A primeira regra a ter em mente na construcao de polıgonos e que, todos os seus vertices devem residir nomesmo plano. Um polıgono nao pode “dobrar-se” no espaco (Figura 4.21).

Figura 4.21: Polıgonos Planos/Nao-planos

Esta primeira regra pende a favor da utilizacao de triangulos na definicao dos nossos polıgonos, uma vezque matematicamente um plano e definido por tres pontos.

2. Outra regra diz que os segmentos do polıgono nao devem intersectar-se e o polıgono deve ser convexo. Opolıgono e convexo quando qualquer linha que o atravesse sai e entra apenas uma vez no polıgono (Figura4.22).

Figura 4.22: Polıgonos validos e invalidos

4.3.6 Sub-divisao de Arestas

Apesar de o OpenGL so conseguir desenhar polıgonos convexos, existem situacoes em que polıgonos nao-convexosfazem sentido, por exemplo ao desenhar uma estrela. A primeira estrela da Figura 4.23 nao e convexa, mas aodividirmos o polıgono em varios triangulos obtemos uma figura convexa valida.

Figura 4.23: Polıgonos nao Convexos

A fim de evitar que as linhas (edges) no interior da segunda estrela sejam visıveis podemos a edge flag. Estaflag e activa/inactiva pela funcao glEdgeFlag(boolean enable). Esta funcao diz ao OpenGL se os segmentosseguintes sao considerados arestas do polıgono.

4.4 Buffers

O OpenGL nao desenha realmente as primitivas no ecra, utiliza antes um buffer buffer de cor, inicialmenteinvisıvel, que posteriormente e colocado no ecra. Chamamos aos dois buffers de cor, o front buffer (o que seencontra actualmente no ecra) e o back buffer (o que esta a ser desenhado).

36

Page 38: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

No JOGL a configuracao do display e feita alterando as capacidades na classe GLDrawable1. As capacidadesactuais do display podem ser consultadas utilizando:

public class MyGl implements GLEventListener {

...

@Override

public void init(GLAutoDrawable drawable) {

GLCapabilities cap = drawable.getChosenGLCapabilities ();

boolean db = cap.getDoubleBuffered ();

...

}

...

}

O double buffering encontra-se activo por omissao. Pode no entanto ser activado ou desactivado utilizando ocodigo:

GLCapabilities cap = drawable.getChosenGLCapabilities ();

// Desactivar o double buffer

cap.setDoubleBuffered(false);

A troca de buffers pode ser conseguida utilizando a funcao GLDrawable.swapBuffers()2.

Utilizando Buffer Targets

E possıvel desenhar directamente no front buffer dizendo ao OpenGL qual o buffer de destino (target) para asprimitivas que estamos actualmente a desenhar, utilizando:

gl.glDrawBuffer(int mode);

Especificando GL2.GL FRONT, desenhamos directamente no front buffer, utilizando GL2.GL BACK, remetemoso desenho para o back buffer. Outra forma de desenhar directamente no front buffer passa pela desactivacao dodouble buffering.

Ao desenhar com recurso a um unico buffer e aconselhavel a utilizacao da funcao glFlush ou glFinish paraforcar o pipeline a processar a lista de comandos no buffer.

4.4.1 Buffer de Profundidade

O OpenGL suporta mais buffers para alem dos buffers de cor. Um deles e o depth buffer que em vez de armazenarvalores de cor, armazena valores de profundidade.

O teste de profundidade faz corresponder a cada elemento de cor no color buffer, um valor de profundidadeno depth buffer.

Para utilizar o buffer de profundidade usamos o codigo:

gl.glEnable(GL2.GL_DEPTH_TEST );

Para desactivar temporariamente o teste de profundidade sem descartar os valores actualmente no buffer,podemos utilizar:

gl.glDepthMask(false );

Utilizando true em vez de false, podemos reactivar o teste de profundidade.

4.4.2 Scissors

Afim de optimizar recursos, pode ser pertinente desenhar apenas uma porcao do ecra. O OpenGL permite definira zona rectangular do ecra que e renderizada.

O rectangulo pode ser definido activando o scissor test com recurso a funcao glEnable(GL2.GL SCISSOR TEST)e definindo a o seu rectangulo, utilizando a funcao:

GL2.glScissor(int x, int y, int width , int height );

Os valores x e y especificam o canto inferior direito do rectangulo. Os valores width e height definem alargura e altura do rectangulo.

1No caso da interface GLEventListener, os metodos recebem uma instancia de um GLAutoDrawable que e do tipo GLDrawable

por heranca2Quando o double buffering esta activo, isto e feito de forma automatica

37

Page 39: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

GL2 gl = drawable.getGL (). getGL2 ();

// Activar o Scissor Test

gl.glEnable(GL2.GL_SCISSOR_TEST );

gl.glClearColor (1f, 0f, 0f, 0f);

gl.glScissor (50, 50, 200, 200));

gl.glClear(GL2.GL_COLOR_BUFFER_BIT );

gl.glClearColor (1f, 1f, 0f, 0f);

gl.glScissor (120, 120, 60, 60);

gl.glClear(GL2.GL_COLOR_BUFFER_BIT );

// Desactivar o Scissor Test

gl.glDisable(GL2.GL_SCISSOR_TEST );

gl.glFlush ();

O codigo em cima, define uma scissor box inicial com o canto inferior direito [x, y] = [50, 50] e com a largurae altura de 200. Seguidamente a cor de fundo e “limpa” de vermelho. Uma scissor box mais pequena e entaodefinida e pintada de amarelo (Figura 4.24).

Figura 4.24: Scissor Test

38

Page 40: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Capıtulo 5

Cores, Materiais e Luzes

5.1 Cor

A cor e simplesmente um comprimento de onda da luz visıvel aos nossos olhos. A luz e uma onda que viaja peloespaco como uma onda num lago, no entanto e modelada, na fısica, como uma partıcula, como uma gota deagua que cai no chao.

A luz vista como uma onda

A luz visıvel ao nosso olho e realmente uma mistura de diferentes tipos de luz. O que caracteriza cada tipo deluz, e o seu comprimento de onda (Figura 5.1).

Figura 5.1: Medida do Comprimento de Onda

O espectro visıvel ao olho humano varia desde os 390 manometros (luz violeta) e os 720 nanometros (luzvermelha) (Figura 5.2). Os termos ultra-violeta e infra-vermelho referem-se ao espectro fora do espectro visıvel.

Figura 5.2: Espectro de Luz Visıvel

39

Page 41: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

A luz vista como uma partıcula

A cor que vemos nos objectos e realmente a soma de todas os comprimentos de onda de luz que o objectoconsegue reflectir. Por exemplo, o branco e a soma de todos os comprimentos de onda do espectro, enquanto queo preto e a ausencia de luz (pelo menos da luz visıvel).

Dependendo do tipo e quantidade de atomos de uma superfıcie, esta reflecte um determinado comprimentode onda dos fotoes de luz que a bombardeiam e absorve os restantes. Cada um destes fotoes tem tambem umcomprimento de onda associado (dai a dualidade onda/partıcula), o somatorio dos comprimentos de onda daspartıculas reflectidas confere a cor visıvel aos nossos olhos (Figura 5.3).

Figura 5.3: Partıculas (fotoes) reflectidos dos materiais

A retina do olho humano e “excitada” pelo conjunto de fotoes reflectidos pelas superfıcies e o cerebrointerpreta-os como luz. As celulas fotossensıveis da nossa retina sao sensıveis a tres tipos de comprimento deonda - o vermelho, o verde e o azul. A mistura de quantidades diferentes das tres componentes resulta na corinterpretada pelo nosso cerebro (Figura 5.4).

Figura 5.4: Interpretacao da cor pelo olho humano

Computador → Gerador de Fotoes

A geracao de cores num computador utilizando varias intensidade de Red, Green e Blue (RGB), faz agora algumsentido. Os nossos monitores sao compostos de pequenos elementos contendo as tres componentes de cor (RGB).Ao mudar as intensidades das varias cores, obtemos a palete de cores visıvel (Figura 5.5).

5.1.1 Modos de Display

Hoje em dia, gracas aos fabricantes dos sistemas operativos, o desenho nos dispositivos graficos e feito comrecurso a uma camada de virtualizacao, chamada de driver grafico, que permite, por intermedio de uma API (talcomo o OpenGL), desenhar no ecra sem ter que conhecer os pormenores do hardware.

No entanto, devemos ter presentes algumas palavras chaves na utilizacao destas APIs.

40

Page 42: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Figura 5.5: Computador → Gerador de Fotoes

Resolucao

As resolucoes mais usadas nos monitores actuais varia entre os 640x480 e os 1920x1080 (full hd). Devemoster sempre em conta o tamanho da janela e ajustar o nosso clipping volume e viewport de forma a manter aimagem que o utilizador visualiza coerente. E de esperar que a medida que a janela e aumentada, a resolucaodos objectos sera maior.

Profundidade de Cor

Da mesma forma que mais resolucao significa uma imagem mais detalhada, o aumento nos nıveis de cor disponıveis(color depth) devera aumentar a claridade da nossa imagem.

Ao utilizar a API OpenGL devemos ter em mente tres profundidades de cor:

• 4-bit: 16 nıveis de cor

• 8-bit: 256 nıveis de cor

• 24-bit: A cor de cada pixel e definida com recurso a 3 componentes de 8-bit (8 + 8 + 8 = 25), o queproporciona mais de 16 milhoes de cores

A maioria do hardware grafico actual tem aceleracao para os 24-bit de profundidade de cor.Os 16-bit e 32-bit de profundidade foram em tempos utilizados como uma forma de optimizar o desempenho,

uma vez que permitem o alinhamento mais eficiente em memoria (endereco de 32-bit). No entanto, 32-bit naosignifica um aumento do numero de cores, mas sim um desperdıcio de 8-bit de memoria.

41

Page 43: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

5.2 Utilizacao de Cores no OpenGL

Podemos representar todas as cores possıveis com a utilizacao de um cubo, mapeando as componentes Red,Green e Blue nos eixos x, y e z respectivamente (Figura 5.6).

Figura 5.6: RGB Colorspace

Na origem ([x, y, z] = [0, 0, 0]) encontra-se o preto, no ponto [x, y, z] = [255, 255, 255] encontra-se o branco enos extremos do cubo em cada um dos eixos encontram-se as cores vermelho (x), verde (y) e azul (z).

Alterando a Cor utilizada para desenhar

A funcao utilizada para alterar a cor utilizada para desenho e a funcao:

GL2.glColor <x><t>(red , green , blue [, alpha ]);

Na nome da funcao, o <x> representa o numero de argumentos. No caso de ser 3, a cor sera definida com astres componentes RGB, no caso de ser 4, e especificado o valor adicional alpha que define o nıvel de transparencia.

O <t> no nome na funcao especifica o tipo de argumento, que podera ser b, d, f, i, s, ub, ui, or us, querepresentam respectivamente, byte, double, float, integer, short, unsigned byte, unsigned integer, andunsigned short.

A grande maioria dos programas em OpenGL utilizam o glColor3f que permite especificar a intensidadede cor entre 0f e 1f (1f = intensidade maxima de cor). No entanto e possıvel representar, por uma questao deconveniencia, o valor da cor entre 0 e 255, utilizando por exemplo:

gl.glColor3ub (0, 255, 128);

No entanto, o seu uso e desaconselhado, uma vez que, a tendencia no futuro aponta para adicao de maisnıveis de intensidade (> 255). O OpenGL na realidade representa os nıveis de cor internamente utilizando umfloat, pelo que forcar a utilizacao de glColor3ub, implica um passo adicional para a conversao.

5.2.1 Shading

Figura 5.7: Shading de uma linha

42

Page 44: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Ao utilizar a funcao glColor estamos a dizer ao OpenGL que cor deve ser utilizada para os vertices desenhadosa seguir. No entanto, todas as primitivas para alem do ponto contem mais do que um vertice. A forma comosao desenhados os pontos intermedios dos vertices, nessas primitivas, por exemplo para uma linha, depende domodelo de shading escolhido.

A Figura 5.7 mostra como as cores sao seleccionadas no caminho entre dois vertices de uma linha, onde oprimeiro e preto e o segundo e branco. Pela analise da figura, podemos concluir que a linha aparecera como umgradiente de preto para branco.

O shading de polıgonos e um pouco mais complexo. Um triangulo pode ser tambem desenhado dentro docubo RGB Colorspace, como mostra a Figura 5.8(a).

(a) Cores dos vertices nos eixos de cor (b) Triangulo RGB

Figura 5.8: Triangulo no RGB Colorspace

A imagem 5.8(b), pode ser obtida com o codigo:

GL2 gl = drawable.getGL (). getGL2 ();

...

// Utilizar smooth shading

gl.glShadeModel(GL2.GL_SMOOTH );

gl.glBegin(GL2.GL_TRIANGLE_STRIP );

// Vermelho

gl.glColor3f (1f, 0f, 0f);

gl.glVertex3f (40f, 0f, 0f);

// Verde

gl.glColor3f (0f, 1f, 0f);

gl.glVertex3f (0f, 60f, 0f);

// Azul

gl.glColor3f (0f, 0f, 1f);

gl.glVertex3f (-40f, 0f, 0f);

gl.glEnd ();

O modelo por omissao de shading no OpenGL e o GL2.GL SMOOTH, no qual a transicao entre as cores e adescrita em cima. O outro modelo e o GL2.GL FLAT, no qual a cor da superfıcie utilizada corresponde a cor doultimo vertice, com a excepcao das primitivas GL POLYGON, onde a cor utilizada e do primeiro vertice.

Para alterar o shading model utilizado pelo OpenGL, podemos utilizar a funcao:

gl.glShadeModel(int model );

Utilizando como argumento uma das constantes GL2.GL SMOOTH ou GL2.GL FLAT.

43

Page 45: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

5.3 Cores no Mundo Real

O shading dos objectos no mundo real nao se resume apenas aos valores RGB das cores. Ao preenchermossuperfıcies com cores, os nossos modelos estao longe de parecer reais (Figura 5.9).

Figura 5.9: Objecto preenchido com cores diferentes em cada polıgono

O OpenGL simula de forma bastante aproximada as condicoes de luz num ambiente real. Com a excepcao dosobjectos que emitem luz propria, todos eles sao afectados por tres tipos de luz: ambiente, difusa e especular.

5.3.1 Luz Ambiente

A luz ambiente nao tem direccionalidade. As superfıcies dos objectos de uma cena sao afectadas de forma igual euniforme (Figura 5.10). O resultado de uma cena com uma luz ambiente e semelhante aos exemplos ilustradosate agora onde a cor e uniforme.

Figura 5.10: Objecto iluminado com luz ambiente

5.3.2 Luz Difusa

A luz difusa provem de uma direccao especıfica mas e reflectida de maneira uniforme pelas superfıcies em variosangulos (Figura 5.11). No entanto, as superfıcies iluminadas directamente, sao mais claras que as ilmunidadascom um determinado angulo. Um bom exemplo de luz difusa e uma lampada fluorescente.

Figura 5.11: Objecto iluminado com Luz Difusa

44

Page 46: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

5.3.3 Luz Especular

A luz especular vem de uma direccao em especifico, e reflectida de maneira uniforme, mas o feixe da sua reflexaocontinua a ser direccional (Figura 5.12). Os objectos afectados por luz especular costumam mostrar um pontomais iluminado, onde a luz incide com mais intensidade.

Figura 5.12: Objecto iluminado com Luz Especular

5.3.4 Luz de Modo Geral

Nenhuma cena e composta de um unico tipo de luz, e antes composta pelo conjunto das varias componentes comvarias intensidades. A titulo de exemplo, imaginemos um feixe de laser vermelho num quarto escuro. O feixepodera ser comparado com a luz especular, as partıculas de po que reflectem parte da luz do laser podem serconsideradas luz difusa e o matizado vermelho nas paredes do quarto pode ser comparado com a luz ambiente.

Da mesma forma que a cor, os varios tipos de luz tem um valor RGBA associado1. Assim por exemplo parao laser vermelho poderıamos ter os valores na Tabela 5.1.

Red Green Blue AlphaSpecular 0.99 0.0 0.0 1.0Diffuse 0.10 0.0 0.0 1.0Ambient 0.05 0.0 0.0 1.0

Tabela 5.1: Distribuicao de Luz e Cor de um Laser Vermelho

Pela interpretacao da tabela, podemos concluir que o laser vermelho tem uma forte componente especular,uma pequena componente difusa e pouquıssima componente de luz ambiente. O mais certo e que, a presenca departıculas, gere uma componente difusa de luz, induzindo luz ambiente no compartimento.

As componentes difusa e ambiente sao muito semelhantes na natureza e sao normalmente combinadas.

5.4 Materiais no Mundo Real

A forma como os materiais aparecem no mundo real depende dum conjunto de factores, no entanto, os maisdeterminantes tem a ver com a sua cor, e as condicoes de iluminacao que o rodeiam. Assim, por exemplo, umabola azul reflecte a maior parte dos comprimentos de onda azuis e absorve grande parte dos outros.

Na maioria dos cenarios, a luz e branca, no entanto mudando a luz para amarelo, por exemplo, a nossa bolateria uma cor escura (ou mesmo preto) uma vez que absorve tudo que nao seja azul.

Propriedades dos Materiais

Quando utilizamos luzes, nao definimos o material de um determinado polıgono so pela cor, dizemos antes, qual acor da luz que eles reflectem. Os materiais podem reflectir luz especular de uma determinada cor e absorver todaa luz difusa da mesma cor, ou ao contrario. Outra propriedade que e definida nos materiais, e a sua capacidadede gerar luz propria.

Adicao de Luz aos Materiais

Nao existe nenhuma regra (como a do RGB Colorspace) para ajudar a definir as propriedades ideais de luzes emateriais. Normalmente os resultados sao conseguidos com alguma pratica e analise.

1Para efeitos de luz o alpha e ignorado

45

Page 47: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Ao desenhar objectos, o OpenGL decide qual a cor para cada pixel. Cada vertice das nossas primitivas temum valor RGB diferente baseado no efeito conjunto das 3 componentes de luz ambiente, difusa e especularmultiplicado pela reflectividade ambiente, difusa e especular do material.

Calculo do Efeito das luzes

O calculo do RGB das tres componentes de luz e feito de forma similar. No entanto, a direccionalidade das luzesdifusa e especular depende do angulo de incidencia da luz.

O calculo do RGB obtido a partir da incidencia da luz (ambiente neste caso) com o RGB (0.5, 0.5, 0.5)numa superfıcie com propriedades reflectivas da luz ambiente (0.5, 1.0, 0.5) pode ser calculado da seguinteforma;

RGBreflected = RGBlight ×RGBmaterial

Ou seja,

RGBreflected = (0.5, 0.5, 0.5)× (0.5, 1.0, 0.5) = (0.25, 0.5, 0.25)

Figura 5.13: Compontente de luz ambiente de um Objecto

5.5 Adicao de Luzes ao Cenario

A fim de consolidar os conceitos teoricos nas seccoes anteriores, e antes de avancarmos com mais conceitos, epertinente contextualiza-los no OpenGL.

Activacao a Luz

Para utilizar a luz no OpenGL activamos a flag GL LIGHTING:

gl.glEnable(GL2.GL_LIGHTING );

gl.glColor3f (0.75f, 0.75f, 0.75f);

gl.glBegin(GL2.GL_TRIANGLES );

gl.glVertex3f (60f, -40, 0f);

gl.glVertex3f (-60f, -40f, 0f);

gl.glVertex3f (0f, 40f, 0f);

gl.glEnd ();

Ao activar a flag GL LIGHTING, o OpenGL determina a cor de cada vertice com base nos parametros dosmateriais. Como ainda nao foram definidos quaisquer parametros dos materiais, os objectos no nosso cenarioaparecem escuros e sem qualquer luz (Figura 5.14).

Configuracao do Modelo de Lighting

O primeiro passo depois de activar o calculo de luzes e configurar o modelo de lighting. As tres componentes deluz que afectam o nosso modelo de lighting sao definidos com recurso a funcao:

glLightModelfv(int mode , float [] params , int offset );

46

Page 48: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Figura 5.14: Polıgono sem parametros de materiais definidos

O argumento mode permite-nos seleccionar qual a(s) componente(s) que estamos a configurar. O segundoargumento e um array contendo os valores RGBA da luz1.

Para definir a componente de luz ambiente utilizamos a variavel GL LIGHT MODEL AMBIENT, como mostra oexemplo:

gl.glEnable(GL2.GL_LIGHTING );

float [] ambientLight = new float[] {1f, 1f, 1f, 1f};

gl.glLightModelfv(GL2.GL_LIGHT_MODEL_AMBIENT , ambientLight , 0);

Configuracao das Propriedades dos Materiais

A configuracao das propriedades dos materiais e feita antes de os desenhar, definindo as cores que estes reflectempara cada componente. Isto pode ser feito com recurso a funcao:

glMaterialfv(int face , int pname , float [] params , int offset)

O parametro face define qual a face que toma os valores que estamos a definir:

• GL FRONT: Frente

• GL BACK: Tras

• GL FRONT AND BACK: Ambas as faces

O parametro pname define qual a propriedade que estamos a configurar e pode tomar os valores:

• GL AMBIENT, GL DIFFUSE, GL SPECULAR: Luz ambiente, difusa e especular

• GL AMBIENT AND DIFFUSE: Componentes ambiente e difusa (tomarao os mesmos valores).

• GL EMISSION: Luz propria do objecto.

O seguinte exemplo mostra uma possıvel utilizacao da funcao glMaterial:

float gray[] = { 0.75f, 0.75f, 0.75f, 1.0f };

gl.glMaterialfv(GL2.GL_FRONT , GL2.GL_AMBIENT_AND_DIFFUSE , gray , 0);

Na maior parte das vezes, a luz ambiente e difusa tomam valores semelhantes, para tal a flag GL AMBIENT AND DIFFUSEe utilizada. A nossa imagem tera agora o aspecto da Figura 5.15.

A segunda forma de atribuir propriedades aos materiais e activando o color tracking. Com o color tracking,dizemos ao OpenGL para utilizar as cores definidas com recurso a glColor.

Para activar o color tracking, activamos a flag GL COLOR MATERIAL:

glEnable(GL2.GL_COLOR_MATERIAL );

Da mesma forma utilizamos a funcao glColorMaterial para definir a face e a componente de luz afectada:

glColorMaterial(GL2.GL_FRONT , GL2.GL_AMBIENT_AND_DIFFUSE );

1O parametro offset e especıfico do binding JOGL. No contexto deste documento tomara sempre o valor 0.

47

Page 49: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Figura 5.15: Polıgono apos definicao com glMaterial

Juntando tudo no mesmo bloco de codigo obtemos:

...

// No metodo init (...)

gl.glEnable(GL2.GL_LIGHTING );

float [] ambientLight = new float[] {1f, 1f, 1f, 1f};

gl.glLightModelfv(GL2.GL_LIGHT_MODEL_AMBIENT , ambientLight , 0);

gl.glEnable(GL2.GL_COLOR_MATERIAL );

...

// No metodo display (...)

gl.glColorMaterial(GL2.GL_FRONT , GL2.GL_AMBIENT_AND_DIFFUSE );

gl.glColor3f (0.75f, 0.75f, 0.75f);

gl.glBegin(GL2.GL_TRIANGLES );

gl.glVertex3f (60f, -40, 0f);

gl.glVertex3f (-60f, -40f, 0f);

gl.glVertex3f (0f, 40f, 0f);

gl.glEnd ();

O resultado final da utilizacao do GL COLOR MATERIAL, sera semelhante ao obtido definindo o material paracada polıgono individual (Figura 5.15).

A Figura 5.16 mostra os resultados para varios nıveis da luz ambiente num objecto mais complexo.

5.6 Fontes de Luz

Num cenario real, as fontes de luz podem ser variadas. Para alem da cor e intensidade, sao providas de umalocalizacao e direccionalidade. Com o OpenGL e possıvel definir 8 fontes de luzes independentes com umalocalizacao no nosso viewing volume.

Ao especificar uma luz, dizemos ao OpenGL a sua localizacao e para onde se dirige. Ao especificar umaluz direccional, esta incide nos objectos com um determinado angulo, que determina a forma como o objectoe iluminado. A fim de conseguir calcular o shading (as sombras) numa superfıcie, o OpenGL deve conhecer oangulo de incidencia da luz.

A luz incide numa superfıcie com um determinado angulo (A) e e reflectida com outro angulo (B) em direccaoao observador (Figura 5.17). Estes angulos sao utilizados em conjunto com as propriedades dos materiais, paradeterminar a cor aparente de cada vertice. Posteriormente pela utilizacao de smooth shading (GL SMOOTH), edada a sensacao de iluminacao do polıgono.

Se tivermos em consideracao que cada polıgono e definido por um conjunto de pontos, determinar o anguloque a luz faz com um ponto pode representar uma dificuldade1. Para resolver esse problema, cada ponto teraque conter informacao acerca do vector que define a sua orientacao vertical (upward).

1O segundo angulo (B) pode tomar uma infinidade de valores possıveis

48

Page 50: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

(a) ambientList = .8, .8, .8 (b) ambientList = .4, .4, .4

Figura 5.16: Varios nıveis de Luz Ambiente

Figura 5.17: Reflexao da Luz nos Objectos

49

Page 51: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Vectores Normais as Superfıcies

O vector normal (normal vector) de uma determinada superfıcie, e um vector que comeca num ponto imaginarioalgures na superfıcie fazendo um angulo recto com esta (Figura 5.18).

Figura 5.18: Vectores Normais (2D e 3D)

E possıvel especificar normais para os polıgonos gerados pelas primitivas OpenGL. No entanto, pode fazersentido especificar normais para pontos em particular, por exemplo, no caso em que a normal nao e totalmenteperpendicular ao polıgono.

Especificacao da Normal

A Figura 5.19 mostra um plano paralelo ao plano xy no espaco 3D. O vector normal podera sera definido pelovector entre o ponto (1, 1, 0) e qualquer outro ponto (acima deste) na recta que o atravessa, como por exemplo oponto (1, 10, 0).

Figura 5.19: Exemplo de um vector normal a uma superfıcie

Para especificar o vector normal do exemplo seriam necessarios 2 pontos. No OpenGL e possıvel especificaro vector normal utilizando apenas um ponto, para tal, movemos o vector para a origem (0, 0, 0), subtraindo oprimeiro ponto ao segundo, obtendo:

Vnormal = V(1,10,10) − V(1,1,0) = V(0,9,0)

O angulo do vector normal inicial mantem-se no vector entre a origem e nosso novo ponto (Figura 5.20).O vector normal pode ser associado a uma superfıcie utilizando a funcao glNormal, como mostra o exemplo:

gl.glBegin(GL_TRIANGLES );

gl.glNormal3f (0.0f, -1.0f, 0.0f);

gl.glVertex3f (0.0f, 0.0f, 60.0f);

gl.glVertex3f (-15.0f, 0.0f, 30.0f);

gl.glVertex3f (15.0f,0.0f,30.0f);

gl.glEnd ();

50

Page 52: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Figura 5.20: Vector Normal movido para a Origem

No exemplo, a funcao glNormal3f especifica o vector normal a superfıcie definida pelos tres vectoressubsequentes (neste caso um triangulo), na direccao do eixo-y negativo. Os vectores sao desenhados emcounterclock-wise quando vistos do lado para que aponta o vector, de forma a manter o winding coerente.

Vectores Normais Unitarios

Todos os vectores normais no OpenGL, devem ser vectores unitarios (de comprimento 1). Podemos converterqualquer vector para um vector unitario obtendo o seu cumprimento e dividindo as componentes nos 3 eixos poresse cumprimento:

Length =√x2 + y2 + z2

x1 =x

Length, y1 =

y

Length, z1 =

z

Length

V1 = (x1, y1, z1)

O processo de tornar um vector unitarios denomina-se de normalizacao de vectores.A fim de evitar os calculos, podemos dizer ao OpenGL para converter automaticamente as nossas normais

para vectores unitarios, activando a flag :

glEnable(GL2.GL_NORMALIZE );

No entanto, isto tem um custo no desempenho. A melhor solucao sera efectuar o pre-calculo dos vectoresnormais ja normalizados.

Sem mais configuracao, a transformacao efectuada pela funcao glScale, altera, junto com a geometria, otamanho das normais definidas para os nossos polıgonos. Para evitar esse efeito podemos activar a flag :

glEnable(GL2.GL_RESCALE_NORMALS );

Junto com este documento, foi criado um projecto do eclipse contendo classes de auxılio a programacaoOpenGL. Uma dessas classes e a classe GlTools que contem um conjunto de funcoes uteis. Uma dessas funcoes ea funcao:

GLVector GlTools.normalizeVector(GLVector v);

Esta funcao recebe como argumento um vector (classe GLVector) e devolve uma instancia normalizada dovector fornecido.

51

Page 53: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Figura 5.21: Um vector normal nao trivial

Figura 5.22: Produto Vectorial

52

Page 54: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Determinando a Normal

No caso da Figura 5.21 o vector normal nao e tao obvio.A determinacao de um vector normal pode ser feita utilizando 2 vectores (ou 3 pontos) do plano que representa

a superfıcie (Figura 5.22). O produto vectorial desses vectores e um vector perpendicular a superfıcie.Tomando o vector V1 ( ~P1P2) e V2 ( ~P1P3), o produto vectorial (VP = V1 × V2) pode ser obtido utilizando a

formula:

xP = y1 × z2 − y2 × z1yP = x1 × z2 − x2 × z1zP = x1 × y2 − x2 × y1

Mais uma vez, com o fim de facilitar o calculo, foi criado codigo para facilitar esta tarefa:

GLVector v1 = new GLVector (1f, 2f, 3f);

GLVector v2 = new GLVector (4f, 5f, 6f);

GLVector vp = v1.crossProduct(v2);

O exemplo acima, cria dois vectores (v1 e v2) e utiliza a funcao crossProduct da instancia v1 para criar ovector vp com o resultado do produto vectorial.

5.6.1 Configurando uma Fonte de luz

Conhecidos que estao os requisitos para a iluminacao de polıgonos, podemos adicionar luzes ao nosso cenario. Aconfiguracao de luzes e feita utilizando a funcao:

glLightfv(int light , int pname , float[] params , int offset );

A criacao de um ponto de luz pode ser feita da seguinte forma:

// na funcao init (...)

float [] ambientLight = { 0.1f, 0.1f, 0.1f, 1.0f };

float [] diffuseLight = { 0.4f, 0.4f, 0.4f, 1.0f };

// Configurar e Activar a Luz 0

gl.glLightfv(GL2.GL_LIGHT0 , GL2.GL_AMBIENT , ambientLight , 0);

gl.glLightfv(GL2.GL_LIGHT0 , GL2.GL_DIFFUSE , diffuseLight , 0);

gl.glEnable(GL2.GL_LIGHT0 );

// na funcao display (...)

// Posicionar a luz no cenario

float lightPos [] = { -50.f, 50.0f, 100.0f, 1.0f };

gl.glLightfv(GL2.GL_LIGHT0 , GL2.GL_POSITION , lightPos );

Os arrays ambientLight[] e diffuseLight[] contem o RGBA das componentes ambiente e difusa da luz.O array lightPos[] define a posicao da luz. A posicao da luz e definida na ModelView Matrix uma vez quee um objecto geometrico, daı ser posicionada normalmente na funcao display(). Quando o ultimo valor daposicao da luz e 1f, o array define a posicao da luz, quando o seu valor e 0, a luz encontra-se na direccao dovector lightPos[], mas no infinito.

Ao desenhar os polıgonos dos nossos objectos e necessario definir os vectores normais. Para facilitar o calculodos vectores normais foi criada uma funcao na classe GlTools, que pode ser utilizada da seguinte forma:

// Criar uma lista de vectores

GLTVectorList vPoints = new GLTVectorList ();

vPoints.add (15.0f, 0.0f, 30.0f);

vPoints.add (0.0f, 15.0f, 30.0f);

vPoints.add (0.0f, 0.0f, 60.0f);

// Obter o vector normal ao plano

GLVector vNormal = GlTools.getNormalVector(vPoints );

gl.glNormal3fv(vNormal.toArray(), 0); // 0 -> ignorar

vPoints.draw ();

A classe GLTVectorList fornece uma forma simples de criar listas de vectores. O vector normal pode serobtido com a funcao GlTools.getNormalVector que recebe como argumento a lista de vectores criada. Ocalculo e feito com base nos primeiros 3 vectores adicionados na lista. Para utilizar nas funcoes do OpenGL,

53

Page 55: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

classe GLVector fornece o metodo toArray como forma simples de converter a instancia actual para um arrayde float.

Depois de aplicada a nossa fonte de luz, a imagem da Figura 5.16(b) toma o aspecto da Figura 5.23.

Figura 5.23: Imagem com Fonte de Luz

Sugestao A fim de aumentar o desempenho da nossa aplicacao e uma vez que a geometria normalmente econhecida a partida, seria boa ideia guardar a lista de vectores (polıgonos) e suas normais a priori e apenasdesenha-los no momento oportuno.

5.7 Efeitos de Iluminacao

A luz ambiente e difusa sao suficientes no caso de estarmos a modelar superfıcies que nao tem componenteespecular da luz, tais como, madeira, papel, carvao, ou semelhantes.

No entanto, em superfıcies tais como a pele e metalicas em geral, e desejavel a componente especular. Aoadicionar esta componente podemos dar brilho as superfıcies, tal como o brilho numa esfera colorida de vidro.

5.7.1 Luz Especular

Podemos adicionar luz especular a fonte de luz definida anteriormente da seguinte forma:

// metodo init (...)

float [] specularLight = { 1f, 1f, 1f, 1f };

...

gl.glLightfv(GL2.GL_LIGHT0 , GL2.GL_SPECULAR , specularLight , 0);

O array specularLight[] especifica uma componente especular muito brilhante na nossa fonte de luz (luzbranca RBG=[255, 255, 255]). Seguidamente, utilizando a funcao glLightfv adicionamos a luz GL LIGHT0 acomponente especular.

A seguir e necessario definir a forma como o nosso objecto reflecte a luz especular, o que pode ser feito com ocodigo:

// metodo display (...)

// Definir a componente especular dos objectos ...

float [] specref = { 1.0f, 1.0f, 1.0f, 1.0f };

gl.glMaterialfv(GL2.GL_FRONT , GL2.GL_SPECULAR , specref , 0);

// ..com um valor alto de brilho

gl.glMateriali(GL2.GL_FRONT , GL2.GL_SHININESS , 128);

...

Mantendo o color tracking activo, as cores utilizadas sao as definidas pela funcao glColor. O array specref[]define os valores RGBA para a reflexao especular. Utilizando a cor branca, dizemos que as superfıcies reflectem

54

Page 56: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

praticamente todas as cores da componente especular. Utilizamos depois este array na propriedade GL SPECULARna face GL FRONT dos nossos objectos (Figura 5.24).

Figura 5.24: Adicao de Luz Especular

Expoente Especular

Para obter o efeito de brilho nas zonas onde a luz especular incide e sombra a medida que nos afastamos,alteramos a propriedade GL SHININESS na face do objecto:

gl.glMateriali(GL2.GL_FRONT , GL2.GL_SHININESS , 128);

Esta funcao define o chamado expoente especular dos materiais. Basicamente define o quao pequeno e o focoda luz. Com o valor proximo de 0, o foco e grande e provocando uma incidencia semelhante a difusa/ambiente.A medida que aumentamos o valor, a nossa luz vai ficando mais “focada” provocando um ponto de luz maisdefinido. O valor do GL SHININESS pode variar entre 1 e 128.

5.7.2 Normal Averaging

A tecnica de normal averaging e um tweaking que permite dar a ilusao de uma superfıcie suave (smooth) aindaque seja composta por polıgonos planos, como o exemplo da Figura 5.25.

Figura 5.25: Esfera composta de quads e triangulos

Se especificarmos as normais aos polıgonos, o que vamos obter e uma superfıcie parecida com um diamante.No entanto, se especificarmos as “verdadeiras” normais, ou seja, nos vertices, o OpenGL interpola de forma suaveatraves da superfıcie dos polıgonos. O resultado e a ilusao de uma superfıcie suave.

A Figura 5.26 ilustra as diferencas entre as normais aos polıgonos e aos vertices. No segundo caso as normaissao perpendiculares a superfıcie real do circulo.

55

Page 57: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

(a) Normais perpendiculares a cada face (b) Normais perpendiculares a cada vertice

Figura 5.26: Normal Averaging

Calcular este tipo de normal para uma esfera e relativamente simples, uma vez que todas as normais passampelo seu centro. No entanto, para superfıcies mais complexas o calculo e feito com base nas normais de variospolıgonos que partilham o vertice em questao. A normal resultante e a media destas normais, daı o nome normalaveraging.

5.7.3 Especificando um Spotlight

Para transformarmos uma fonte de luz num Spotlight basta adicionar-lhe direccionalidade e definir a sua abertura.Podemos conseguir esse efeito utilizando o codigo:

// algures no init (...)

gl.glLightf(GL2.GL_LIGHT0 , GL2.GL_SPOT_CUTOFF , 30f);

// algures no display (...)

float [] spotDir = {-1f, -1f, 0f};

gl.glLightfv(GL2.GL_LIGHT0 , GL2.GL_SPOT_DIRECTION , spotDir , 0);

O efeito conseguido com a adicao de um spotlight sera semelhante ao da Figura 5.27.

Figura 5.27: Adicao de um Spotlight

56

Page 58: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

A propriedade GL SPOT CUTOFF define o angulo de abertura do nosso spotlight, conforme mostra a Figura5.28.

Figura 5.28: Angulo do cone do Spotlight

A propriedade GL SPOT DIRECTION define a direccao do spot segundo um vector normalizado. Neste caso ovector (−1,−1, 0) diz que o nosso spot aponta no sentido negativo dos eixos x e y e faz um angulo de 45o com oeixo-y para esquerda.

5.7.4 Tesselation

O conjunto de polıgonos que descrevem uma superfıcie denomina-se de tesselation. Quanto maior for o nıvel detesselation mais realistas parecem as nossas curvas no caso da esfera. A Figura 5.29 mostra duas esferas comnumeros diferentes de polıgonos.

Figura 5.29: Tesselation

57

Page 59: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Capıtulo 6

Cores e Materiais (Continuacao)

Os exemplos constantes daqui para a frente, serao baseados no codigo fornecido junto com este item, na classeExample0 (Apendice C.1). O exemplo contem um torus, definicoes basicas de luz e um chao como mostra aFigura 6.1.

Figura 6.1: Example0

6.1 Blending

Ja vimos que o OpenGL armazena os valores de cor no buffer de cor (em circustancias normais) na altura derenderizar. Ja vimos tambem que o mesmo acontece a informacao da profundidade de cada um dos elementos(depth buffer). Quando activamos o teste de profundidade (depth test), um elemento substitui outro, apenas seestiverem mais perto no clipping volume ao utilizador.

No caso do blending estas regras nao se aplicam:

glEnable(GL2.GL_BLEND );

Quando activo, novas cores sao combinadas com as que existem actualmente no buffer de cor. Esta combinacaoe feita com base num conjunto de criterios.

6.1.1 Combinacao de Cores

A terminologia utilizada para as cores e:

• destination color : Valores RGBA da cor que se encontra actualmente no buffer de cor

• source color : Valores RGBA da cor do elemento que vai interagir com a destination color

58

Page 60: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

A forma como estas duas componentes interagem e controlada pela equacao de blending :

Cf = (CS ∗ S) + (CD ∗D)

Em que Cf e a cor resultante, CS e a source color, CD e a cor de destino, S e D sao os factores de blendingde origem e destino. Estes factores sao configurados com a funcao:

glBlendFunc(int source_function , int destination_function );

Os valores possıveis para os factores estao enumerados na Tabela 6.1.

Function RGB Blend Factors Alpha Blend FactorGL ZERO (0, 0, 0) 0GL ONE (1, 1, 1) 1GL SRC COLOR (RS , GS , BS) AS

GL ONE MINUS SRC COLOR (1, 1, 1)–(RS , GS , BS) 1–AsGL DST COLOR (RD, GD, BD) AD

GL ONE MINUS DST COLOR (1, 1, 1)–(Rd,Gd,Bd) 1–AD

GL SRC ALPHA (AS , AS , AS) AS

GL ONE MINUS SRC ALPHA (1, 1, 1)–(As,As,As) 1–AS

GL DST ALPHA (Ad,Ad,Ad) AdGL ONE MINUS DST ALPHA (1, 1, 1)–(Ad,Ad,Ad) 1–AdGL CONSTANT COLOR (Rc,Gc,Bc) AcGL ONE MINUS CONSTANT COLOR (1, 1, 1)–(Rc,Gc,Bc) 1–AcGL CONSTANT ALPHA (Ac,Ac,Ac) AcGL ONE MINUS CONSTANT ALPHA (1, 1, 1)–(Ac,Ac,Ac) 1–AcGL SRC ALPHA SATURATE (f, f, f)f=min(AS ,1−AD) 1

Tabela 6.1: Factores de Blending do OpenGL

Como os valores RGBA sao floats (0 ; 1) as operacoes de soma e subtraccao continuam a gerar valoresvalidos.

Ao seleccionar uma das opcoes GL CONSTANT COLOR, GL ONE MINUS CONSTANT COLOR, GL CONSTANT ALPHA, eGL ONE MINUS CONSTANT ALPHA, podemos introduzir uma cor constante no blending. A cor inicialmente e black(rgba(0, 0, 0, 0)), para alterar essa cor utilizamos:

glBlendColor(float red , float green , float blue , float alpha );

Um exemplo comum de configuracao da funcao de blending poderia ser:

glBlendFunc(GL2.GL_SRC_ALPHA , GL2.GL_ONE_MINUS_SRC_ALPHA );

Neste caso a source color (RGBA) seria multiplicada pelo seu valor alpha (GL SRC ALPHA). A destinationcolor seria multiplicada por 1 menos o valor do seu alpha (GL ONE MINUS SRC ALPHA). O resultado final seria asoma das duas cores. Por exemplo:

CS = rgba(0, 0, 1, .5) ⇒ GL_SRC_ALPHA ⇒ S = 0.5

CD = rgba(1, 0, 0, 0) ⇒ GL_ONE_MINUS_SRC_ALPHA ⇒ D = 1 - 0.5

Como Cf = (CS ∗ S) + (CD ∗D) temos:

Cf = (Blue * 0.5) + (Red * 0.5)

Para o exemplo a cor final sera uma mistura das duas cores (vermelho + azul). Quanto maior for o valor S,maior sera o valor da source color na mistura.

O blending e normalmente utilizado para conseguir a ilusao de transparencia. Tal ilusao pode ser conseguida,ligando o blending ao desenhar o objecto transparente. O codigo em baixo utiliza a estrutura do Example0adicionando um segundo torus com blending:

// Limpar o fundo da janela com a cor definida

gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT );

gl.glMaterialfv(GL2.GL_FRONT , GL2.GL_SPECULAR , fBrightLight , 0);

gl.glPushMatrix ();

gl.glLightfv(GL2.GL_LIGHT0 , GL2.GL_POSITION , fLightPos.toArray(), 0);

59

Page 61: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

// Desenhar um Torus Verde

gl.glColor4f (0, 1f, 0, .5f);

drawWorld(gl);

// Desenhar um Torus Vermelho com Blending

gl.glPushMatrix ();

gl.glTranslatef (.1f, 0, .3f);

gl.glEnable(GL2.GL_BLEND );

gl.glBlendFunc(GL2.GL_SRC_ALPHA , GL2.GL_ONE_MINUS_SRC_ALPHA );

gl.glColor4f (1f, 0, 0, .5f);

drawWorld(gl);

gl.glDisable(GL2.GL_BLEND );

gl.glPopMatrix ();

gl.glColor4f (0.60f, .40f, .10f, .5f);

GlUtil.drawGround(FloorSize , 1f);

gl.glPopMatrix ();

O resultado do codigo em cima sera o da Figura 6.2.

Figura 6.2: Exemplo de Blending

Modificando ligeiramente o codigo anterior, podemos obter a sensacao de reflexao:

gl.glPushMatrix ();

// Desenhar a luz Invertida (mirror Y)

gl.glLightfv(GL2.GL_LIGHT0 , GL2.GL_POSITION , fLightPos.mirrorY (). toArray(), 0);

// Desenhar a reflexao do Torus

gl.glPushMatrix ();

// Ao utiliza y=-1 estamos a inverter a imagem

gl.glScalef (1f, -1f, 1f);

gl.glFrontFace(GL2.GL_CW ); // Estamos Invertidos

drawWorld(gl);

gl.glFrontFace(GL2.GL_CCW ); // Repor

gl.glPopMatrix ();

// Desenhar o Nosso chao , mas agora transparente

gl.glDisable(GL2.GL_LIGHTING );

gl.glEnable(GL2.GL_BLEND );

gl.glBlendFunc(GL2.GL_SRC_ALPHA , GL2.GL_ONE_MINUS_SRC_ALPHA );

gl.glColor4f (.5f, .5f, .5f, .5f);

GlUtil.drawGround(FloorSize , 1f);

60

Page 62: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

gl.glDisable(GL2.GL_BLEND );

gl.glEnable(GL2.GL_LIGHTING );

// Desenhar a luz no local correcto

gl.glLightfv(GL2.GL_LIGHT0 , GL2.GL_POSITION , fLightPos.toArray(), 0);

// Desenhar um Torus Verde

gl.glColor4f (0, 1f, 0, .5f);

drawWorld(gl);

gl.glPopMatrix ();

O codigo acima desenha inicialmente o torus debaixo do chao com a geometria invertida sobre o eixo-y(glScalef(0, -1f, 0)). Porque a geometria esta invertida e preciso redefinir a forma como e deterinhada aface dos polıgonos, utilizando glFrontFace(GL CW). Da mesma forma o nosso ponto de luz tem que ser colocadona posicao inversa, de forma a manter a iluminacao dos objectos coerentes. Seguidamente activamos o blendinge desenhamos o nosso chao com um alpha de .5f. Finalmente repomos a posicao da luz e desenhamos o toruscom a geometria em posicao. O resultado obtido e o da Figura 6.3.

Figura 6.3: Ilusao de Reflexao utilizando Blending

6.1.2 Alteracao da Equacao de Blending

A equacao mostrada anteriormente:

Cf = (CS ∗ S) + (CD ∗D)

e a queacao por omissao. Podemos, no entanto, escolher de entre um conjunto de equacoes possıveis para adeterminacao do blending, utilizando o seguinte codigo:

glBlendEquation(int equation );

As equacoes possıveis para a determinacao do blending sao as descritas na Tabela 6.2.

Mode FunctionGL FUNC ADD (default) Cf = (CS × S) + (CD ×D)GL FUNC SUBTRACT Cf = (CS × S)− (CD ×D)GL FUNC REVERSE SUBTRACT Cf = (CS ×D)− (CD × S)GL MIN Cf = min(CS , CD)GL MAX Cf = max(CS , CD)

Tabela 6.2: Factores de Blending do OpenGL

61

Page 63: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Da mesma forma que deifinimos a funcao de blending para os valores RGBA source e destination utilizandoglBlendFunc, podemos utilizar a funcao glBlendFuncSeparate para especificar funcoes diferentes tambem parao calculo dos factores alpha:

glBlendFuncSeparate(int srcRGB , int dstRGB , int srcAlpha , int dstAlpha );

Sendo o srcRGB a funcao para o source color, o dstRGB a funcao para o destination color. Os valoressrcAlpha e dstAlpha permitem definir as funcoes para o source e destination alpha respectivamente.

6.2 Antialiasing

Na maior parte dos casos, fragmentos individuais da nossa renderizacao, consistem de pixeis no ecra. Estespixeis sao quadrados (ou quase), podendo quebrar a sensacao de realismo. O OpenGL permite definir flags quemisturam as bordas de pontos, linhas e polıgonos com a vizinhanca, suavizando os contornos dos objectos.

Para tal, e preciso activar primeiro o blending e definir as funcoes para o source e destination color. Depoispodemos activar as flags : GL POINT SMOOTH (pontos), GL LINE SMOOTH (linhas) e GL POLYGON SMOOTH (polıgonos).A Figura 6.4 mostra dois circulos, sendo o de fora desenhado sem antialiasing e o de dentro desenhado comantialiasing.

(a) Circulos Com/Sem Antialiasing (b) Zoom

Figura 6.4: Antialiasing

O codigo para conseguir o resultado da Figura 6.4(a) poderia ser:

gl.glClear(GL2.GL_COLOR_BUFFER_BIT );

float x, y;

gl.glLineWidth (5f);

// Desenhar o Primeiro Circulo Sem Antialiasing

gl.glBegin(GL2.GL_LINE_LOOP );

for(float a=0; a < 2f * GlTools.GL_PI; a += .1f) {

x = (float) Math.sin(a) / 2f;

y = (float) Math.cos(a) / 2f;

gl.glVertex3f(x, y, 0);

}

gl.glEnd ();

// Activar o Blending/Antialiasing e Desenhar o Circulo de Dentro

gl.glEnable(GL2.GL_BLEND );

gl.glBlendFunc(GL2.GL_SRC_ALPHA , GL2.GL_ONE_MINUS_SRC_ALPHA );

// Suavizar as linhas

gl.glEnable(GL2.GL_LINE_SMOOTH );

62

Page 64: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

gl.glHint(GL2.GL_LINE_SMOOTH_HINT , GL2.GL_NICEST );

// Desenhar o Circulo de Dentro com Antialiasing

gl.glBegin(GL2.GL_LINE_LOOP );

for(float a=0; a < 2f * GlTools.GL_PI; a += .1f) {

x = (float) Math.sin(a) / 2.2f;

y = (float) Math.cos(a) / 2.2f;

gl.glVertex3f(x, y, 0);

}

gl.glEnd ();

gl.glDisable(GL2.GL_LINE_SMOOTH );

gl.glDisable(GL2.GL_BLEND );

O codigo em cima desenha um circulo sem antialiasing, depois activa o blending e activa o antialiasing paraas linhas (GL LINE SMOOTH) e desenha o circulo mais pequeno. Adicionalmente o algoritmo escolhido para oantialiasing foi o que tem melhor aspecto final utilizando glHint(GL NICEST). Os algoritmos disponıveis para ocalculo do antialiasing sao GL NICEST e GL FASTEST, sendo que o ultimo tem um resultado visual mais fracoainda que seja mais rapido.

6.2.1 Multisampling

Apesar do aspecto visual ser melhorado pela utilizacao de antialiasing, esta nao e a melhor escolha para tornaros objectos na cena mais realısticos. O GL POLYGON SMOOTH nao e suportado em todas as plataformas e comoutiliza o blending termiamos que desenhar todas as nossa primitivas da frente para tras.

Uma adicao ao OpenGL1 permite enderecar esta “problema”. O multisampling consiste num buffer adicional.Neste buffer os pixeis de cada primitiva sao amostrados2 varias vezes, sendo o resultado mostrado como umunico pixel.

Se o nosso contexto OpenGL suportar multisampling, podemos activa-lo utilizando:

glEnable(GL2.GL_MULTISAMPLE );

Figura 6.5: Normal vs Multisampling

6.3 Nevoeiro (Fog)

O OpenGL suporta a adicao de nevoeiro ao cenario. A tecnica utilizada pelo OpenGL para dar a sensacao defog consiste no blending de uma cor especıfica com a geometria no final de toda a computacao. A quantidadede blending dessa cor (alias: nevoeiro) com cada objecto do cenario depende da distancia desse objecto aoobservador.

A introducao de nevoeiro pode tornar ainda mais real a sensacao de profundidade, uma vez que a visibilidadedos objectos e menor a medida que se afastam, o que acontece no mundo real. Podemos activar o nevoeiroutilizando:

glEnable(GL2.GL_FOG );

1Para versoes > 1.32sampled

63

Page 65: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Figura 6.6: Nevoeiro

A configuracao do nevoeiro e feita utilizando uma das versoes da funcao glFog:

glFogi(int pname , int param );

glFogf(int pname , float param );

glFogiv(int pname , int[] params , int offset );

glFogfv(int pname , float[] params , int offset );

Onde o primeiro argumento (pname) escolhe a propriedade que estamos a alterar e o segundo argumentodefine o novo valor para a propriedade.

Para configurar o nevoeiro utilizando uma determinada cor, que comeca a afectar a geometria a distancia 1fdo observador, terminando em 30f e utilizando uma variacao linear utilizamos:

float [] fLowLight = { 0.25f, 0.25f, 0.25f, 1.0f };

...

// Definir a cor do Nevoeiro

gl.glFogfv(GL2.GL_FOG_COLOR , fLowLight , 0);

// A que distancia os objectos comecao a ser afectados

gl.glFogf(GL2.GL_FOG_START , 1.0f);

// Ponto onde o nevoeiro toma conta completamente

gl.glFogf(GL2.GL_FOG_END , 30.0f);

// Equacao do calculo do Nevoeiro

gl.glFogi(GL2.GL_FOG_MODE , GL2.GL_LINEAR)

Analisando em mais detalhe o codigo temos:

gl.glFogfv(GL2.GL_FOG_COLOR , fLowLight , 0);

No exemplo (Figura 6.6) podemos observar que o nevoeiro toma a cor do fundo. A cor do nevoeiro e definidaalterando o parametro GL FOG COLOR e fornecendo um array contendo os valores RGB.

// A que distancia os objectos comecao a ser afectados

gl.glFogf(GL2.GL_FOG_START , 1.0f);

// Ate onde vai o nevoeiro

gl.glFogf(GL2.GL_FOG_END , 30.0f);

O parametro GL FOG START especifica a que distancia do observador o nevoeiro comeca a ter efeito sobre osobjectos. O parametro GL FOG END define o ponto a partir do qual o nevoeiro toma completamente a cor dosobjectos.

// Equacao do calculo do Nevoeiro

gl.glFogi(GL2.GL_FOG_MODE , GL2.GL_LINEAR)

A transicao entre o GL FOG START e o GL FOG END e controlada pelo GL FOG MODE, que no exemplo estaconfigurada para GL LINEAR. A fog equation define o factor de nevoeiro entre 0 e 1, a medida que o objecto sedesloca entre o inicio e o fim do nevoeiro.

64

Page 66: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Fog Mode Fog EquationGL LINEAR f = end–c

end–startGL EXP f = e–d×c

GL EXP2 f = e–(d×c)2

Tabela 6.3: Fog Equations

A Tabela 6.4 descreve as equacoes para as varias equacoes possıveis.Onde c e a distancia ao observador, start e o valor de GL FOG START e end e o valor de GL FOG END. O valor

d e a densidade do nevoeiro, que pode ser configurada alterando o parametro GL FOG DENSITY:

glFogf(GL2.GL_FOG_DENSITY , 0.5f);

Para GL LINEAR o valor da densidade nao tem qualquer efeito, no entanto, para GL EXP e GL EXP2 este valoraltera o resultado final do nevoeiro.

A Figura 6.7 mostra a forma como cada equacao faz variar o nevoeiro entre o inicio e o fim para umadensidade de 0.5.

Figura 6.7: Equacoes da Densidade do Nevoeiro

O modo como o OpenGL determina a distancia a profundidade do nevoeiro para cada elemento no cenariopode ser alterada utilizando o parametro GL FOG COORD SRC. Dois valores podem ser utilizados:

• GL FRAGMENT DEPTH: Utiliza a profundidade do objecto como valor da distancia. Permite obter melhoresresultados.

• GL FOG COORD (valor por omissao): Faz a interpolacao do nevoeiro entre vertices, o que permite um calculomais rapido.

A alteracao deste parametro pode ser feita utilizando:

glFogi(GL2.GL_FOG_COORD_SRC , GL2.GL_FRAGMENT_DEPTH );

// ou

glFogi(GL2.GL_FOG_COORD_SRC , GL2.GL_FOG_COORD );

6.4 Accumulation Buffer

Em adicao aos buffers de cor, profundidade e stencil1, o OpenGL contem um buffer especial que nos permitearmazenar os valores do buffer de cor em vez de os enviar para o ecra. Um conjunto de operacoes permitemacumular varias iteracoes do buffer de cor, que pode entao ser mostrado no ecra.

O comportamento do buffer de acumulacao pode ser controlado pela funcao:

glAccum(int operation , float value);

O primeiro argumento especifica a operacao de acumulacao a realizar e o segundo valor especifica um factorde escala para a operacao. A operacoes possıveis estao enumeradas na Tabela ??.

Devido a quantidade de operacoes de memoria e processador necessarios para realizar este tipo de operacoes,poucas aplicacoes em tempo-real utilizam este buffer. No entanto, os efeitos visuais conseguidos podem ser deum realismo surpreendente. Por exemplo, e possıvel recriar varios tipos de blur que podem simular os efeitos deprofundidade encontrados nas camaras de vıdeo e fotograficas.

O efeito na Figura 6.8 pode ser conseguido utilizando:1A ser analisado futuramente

65

Page 67: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Operation DescriptionGL ACCUM Escala os valores actuais do buffer de cor e adiciona-os ao buffer de acumulacaoGL LOAD Escala os valores actuais do buffer de cor e substitui os valores actuais do buffer de acumulacaoGL MULT Escala os valores actuais do buffer e armazena-os no buffer de acumulacaoGL ADD Escala os valores actuais do buffer e adiciona os aos valores actualmente no buffer de acumulacaoGL RETURN Escala os valores actuais do buffer e armazena-os no buffer de cor

Tabela 6.4: Fog Equations

Figura 6.8: Efeito blur utilizando buffer de acumulacao

66

Page 68: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

float xoff = 0f;

// Desenhar os objectos 10x movendo -os progressivamente para a esquerda

for(int pass = 0; pass < 10; pass ++) {

xoff += .05f;

gl.glPushMatrix ();

gl.glTranslatef(xoff , 0, 0);

gl.glColor3f (0, 1f, 0);

drawWorld(gl);

gl.glPopMatrix ();

// Desenhar o chao

gl.glColor4f (0.60f, .40f, .10f, .5f);

GlUtil.drawGround(FloorSize , 1f);

if(pass == 0)

gl.glAccum(GL2.GL_LOAD , 0.5f); // Copiar buffer de cor

else

// Acumular o buffer de cor actual com o accum buffer

gl.glAccum(GL2.GL_ACCUM , 0.5f * (.5f / pass ));

}

// Despejar o buffer de acumulacao no buffer de cor

gl.glAccum(GL2.GL_RETURN , 1.0f);

67

Page 69: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Capıtulo 7

Imagens no OpenGL

7.1 Bitmaps

O aspecto visual de um bitmap nao e o ideal, ainda que seja perfeitamente possıvel identificar os objectos nelecontidos (Figura 7.1(a)). No OpenGL os bitmaps podem ser utilizados para mascaras (polygon stippling), fontes ecaracteres e dithering a duas cores.

(a) Bitmap (b) Pixmap

Figura 7.1: Imagem Bitmap

A imagem da Figura 7.1(b), contem 256 nıveis de cinzento, sendo denominada de pixmap.

Figura 7.2: Imagem Campfire

Podemos descrever a imagem utilizada anteriormente para o stippling de polıgonos (Figura 7.2), sob a formade um array de 4 bytes × 32 (32 × 32 bit). Os valores no array de bytes estao em hexadecimal. Como podemosobservar, os valores no array estao invertidos, ou seja, a primeira linha do array representa a ultima linha dobitmap.

68

Page 70: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

ByteBuffer fire = ByteBuffer.wrap(new byte[] {

(byte) 0x00 , (byte) 0x00 , (byte) 0x00 , (byte) 0x00 ,

(byte) 0x00 , (byte) 0x00 , (byte) 0x00 , (byte) 0x00 ,

(byte) 0x00 , (byte) 0x00 , (byte) 0x00 , (byte) 0x00 ,

(byte) 0x00 , (byte) 0x00 , (byte) 0x00 , (byte) 0x00 ,

(byte) 0x00 , (byte) 0x00 , (byte) 0x00 , (byte) 0x00 ,

(byte) 0x00 , (byte) 0x00 , (byte) 0x00 , (byte) 0x00 ,

(byte) 0x00 , (byte) 0x00 , (byte) 0x00 , (byte) 0xc0 ,

(byte) 0x00 , (byte) 0x00 , (byte) 0x01 , (byte) 0xf0 ,

(byte) 0x00 , (byte) 0x00 , (byte) 0x07 , (byte) 0xf0 ,

(byte) 0x0f , (byte) 0x00 , (byte) 0x1f , (byte) 0xe0 ,

(byte) 0x1f , (byte) 0x80 , (byte) 0x1f , (byte) 0xc0 ,

(byte) 0x0f , (byte) 0xc0 , (byte) 0x3f , (byte) 0x80 ,

(byte) 0x07 , (byte) 0xe0 , (byte) 0x7e , (byte) 0x00 ,

(byte) 0x03 , (byte) 0xf0 , (byte) 0xff , (byte) 0x80 ,

(byte) 0x03 , (byte) 0xf5 , (byte) 0xff , (byte) 0xe0 ,

(byte) 0x07 , (byte) 0xfd , (byte) 0xff , (byte) 0xf8 ,

(byte) 0x1f , (byte) 0xfc , (byte) 0xff , (byte) 0xe8 ,

(byte) 0xff , (byte) 0xe3 , (byte) 0xbf , (byte) 0x70 ,

(byte) 0xde , (byte) 0x80 , (byte) 0xb7 , (byte) 0x00 ,

(byte) 0x71 , (byte) 0x10 , (byte) 0x4a , (byte) 0x80 ,

(byte) 0x03 , (byte) 0x10 , (byte) 0x4e , (byte) 0x40 ,

(byte) 0x02 , (byte) 0x88 , (byte) 0x8c , (byte) 0x20 ,

(byte) 0x05 , (byte) 0x05 , (byte) 0x04 , (byte) 0x40 ,

(byte) 0x02 , (byte) 0x82 , (byte) 0x14 , (byte) 0x40 ,

(byte) 0x02 , (byte) 0x40 , (byte) 0x10 , (byte) 0x80 ,

(byte) 0x02 , (byte) 0x64 , (byte) 0x1a , (byte) 0x80 ,

(byte) 0x00 , (byte) 0x92 , (byte) 0x29 , (byte) 0x00 ,

(byte) 0x00 , (byte) 0xb0 , (byte) 0x48 , (byte) 0x00 ,

(byte) 0x00 , (byte) 0xc8 , (byte) 0x90 , (byte) 0x00 ,

(byte) 0x00 , (byte) 0x85 , (byte) 0x10 , (byte) 0x00 ,

(byte) 0x00 , (byte) 0x03 , (byte) 0x00 , (byte) 0x00 ,

(byte) 0x00 , (byte) 0x00 , (byte) 0x10 , (byte) 0x00

});

Os bitmaps sao desenhados no ecra recorrendo ao raster dos seus bits. Precisamos entao de dizer ao OpenGLqual sera a posicao em que deve ser feito o raster da nossa imagem, com recurso a funcao glRasterPos. A funcaoglRasterPos e pode receber 2 ou 3 argumentos, sendo que na primeira o eixo z toma o valor 0. O exemplomostra uma possıvel utilizacao da funcao:

gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT );

// Bitmap de cor Verde

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

for(int i=0; i < 16; i++) {

// Definir coordenadas do Raster

gl.glRasterPos3d(i - 5, 1, i - 5);

// Desenhar o bitmap 32x32 no array de bytes

gl.glBitmap (32, 32, 0f, 0f, 0, 0, fire);

}

gl.glColor3f (.5f, .5f, .5f);

GlUtil.drawGround(GL2.GL_LINE_STRIP , 20f, 1f);

No exemplo em cima, sao desenhados 16 bitmaps percorrendo uma diagonal que atravessa o ponto (0, 0, 0).O nosso bitmap e desenhado utilizando a funcao:

glBitmap(

int width , int height ,

float xorig , float yorig ,

float xmove , float ymove ,

ByteBuffer bitmap );

O width e height referem-se ao tamanho em bits do bitmap, no nosso caso 32×32, o xorig e o yorigreferem-se ao offset x e y em relacao a posicao raster, o xmove e o ymove definem a posicao de raster quandoo desenho terminar e o parametro bitmap contem os dados a desenhar. Os bits a 1 no nosso bitmap serao

69

Page 71: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

transformados em fragmentos (pixel) com a cor actualmente definida, os 0 nao afectaram as cores actualmenteno color buffer.

O resultado do codigo em cima pode ser visualizado na Figura 7.3.

Figura 7.3: Utilizacao de glBitmap/glRasterPos

As coordenadas da funcao glRasterPos sao afectadas pela projeccao e posicao do observador. Se quisermosque o nosso bitmap seja mostrado sempre na mesma posicao no ecra, independentemente do projeccao eobservador, devemos utilizar a funcao glWindowPos, por exemplo:

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

// colocar o raster o canto inferior esquerdo do ecra

gl.glWindowPos2i (10, 10);

gl.glBitmap (32, 32, 0f, 0f, 0, 0, fire);

7.2 Pixmaps

Os pixmaps sao de maior utilidade nos sistemas full-color. O seu layout na memoria e parecido ao dos bitmaps,no entanto, cada pixel pode conter mais do que um bit de informacao. Cada pixel pode conter informacao acercada intensidade (referida normalmente como luminance) ou acerca dos componentes de cor.

Um pixmap pode ser desenhado a partir da posicao actual do raster utilizando a funcao:

void glDrawPixels(

int width , int height ,

int format , int type ,

Buffer pixels)

Os primeiros dois argumentos (width/height) referem-se ao tamanho do pixmap em pixels. O argumentoformat refere-se a forma como a informacao esta disposta, normalmente referido como formato da imagem (verTabela B.1). O argumento type define o tipo de dados na informacao e o ultimo argumento contem a informacaoda imagem1. Ao contrario da funcao glBitmap, a posicao de raster nao e alterada.

Os formatos GL STENCIL INDEX e GL DEPTH COMPONENT, sao utilizados para ler e escrever informacao nosstencil e depth buffers.

O argumento type define o tipo de dados armazenados no nosso pixmap. Os valores possıveis para o tipo dedados estao descritos na Tabela B.22.

1No JOGL, em vez de arrays e recomendada a utilizacao de buffers - http://java.sun.com/developer/technicalArticles/

releases/nio/2Na tabela estao omissos os packed RGB value, para mais informacao consultar - http://www.opengl.org/registry/specs/

EXT/packed_pixels.txt

70

Page 72: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

O exemplo em baixo utiliza numa primeira instancia o ClassLoader1 do Java para ler um ficheiro e a classeTGAImage para utilizar o ficheiro como uma imagem (targa neste exemplo). Posteriormente o metodo getDatada classe TGAImage permite-nos obter uma referencia para a informacao (pixmap) contida na imagem sob aforma de um ByteBuffer.

class Pixmap implements GLEventListener {

private TGAImage img;

private ByteBuffer bb;

// ...

@Override

public void init(GLAutoDrawable drawable) {

GL2 gl = drawable.getGL (). getGL2 ();

// ...

try {

InputStream stream = getClass (). getResourceAsStream("fire.tga");

img = TGAImage.read(stream );

bb = img.getData ();

stream.close ();

} catch (IOException e) {

// Tratar do erro ...

}

}

// ...

}

O bloco try { ... } catch(Exception e) { ... } permite ao nosso programa estar preparado no casoda leitura do ficheiro nao ser bem sucedida. Este bloco e denominado de exception handling no Java2.

Dentro do try o nosso programa le o ficheiro fire.tga que devera estar contido no mesmo package da classePixmap.

Basta agora no metodo display() da nossa classe mostrar o pixmap de acordo com a posicao do raster.

// Definir a posicao do raster

gl.glRasterPos2i(img.getWidth ()*3/4 , img.getHeight ()*3/4);

// Redimensionar e inverter a imagem

gl.glPixelZoom (-.5f, -.5f);

// Desenhar a Imagem no ByteBuffer

gl.glDrawPixels(

img.getWidth(), img.getHeight(), // Tamanho da imagem

img.getGLFormat (), // Pixel Format

GL2.GL_UNSIGNED_BYTE , bb);

// Restaurar

gl.glPixelZoom (1f, 1f);

O resultado do codigo em cima, pode ser visualizado na Figura 7.4. A funcao glPixelZoom(float xzoom,float yzoom) permite alterar a escala utilizada para desenhar os pixels. Utilizando xzoom/yzoom negativos,estamos a inverter a ordem utilizada para desenhar os pixels, pelo que a posicao do raster tem que ser reajustada.

7.3 Operacoes com Pixels

Ate agora temos estado a escrever para os buffers (color, depth, . . . ), no entanto pode ser util ler a informacaocontida nestes buffers ou mesmo copia-la entre eles. A informacao para ler a informacao dos pixels funcionacomo a funcao glDrawPixels so que no sentido inverso.

glReadPixels(

int x, int y,

int width , int height ,

int format , int type ,

Buffer pixels)

1Ver detalhes em http://download.oracle.com/javase/6/docs/technotes/guides/lang/resources.html2Ver mais detalhes em http://download.oracle.com/javase/tutorial/essential/exceptions/

71

Page 73: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Figura 7.4: Utilizacao de glDrawPixels/glPixelZoom

Os argumentos x, y, width e height, definem o rectangulo a copiar1. O format e type sao o formato e otipo de dados utilizados para armazenar o conteudo do buffer na variavel de saıda pixels. Independentementeda forma como a informacao esta armazenada no color buffer, o OpenGL encarrega-se de fazer as conversoesnecessarias.

Pode ser util ainda copiar informacao dentro do mesmo buffer. Para tal definimos o canto inferior esquerdo(com glRasterPos/glWindowPos) da zona a copiar. A funcao para efectuar a copia e:

glCopyPixels(

int x, int y,

int width , int height ,

int type

);

Mais uma vez, o x, y, width e height, definem o rectangulo de origem. O argumento type diz o que estamosa copiar, podendo tomar o valor GL COLOR para copiar do color buffer, GL DEPTH para copiar do depth buffer ouGL STENCIL para copiar do stencil buffer.

Por omissao estas operacoes de copia realizam-se no back buffer em contextos com suporte para doublebuffering, ou no front buffer em contextos com single buffer. Para alterar a fonte ou destino para a copia,utilizamos:

glDrawBuffer(int destination );

glReadBuffer(int source );

O argumento destination da funcao glDrawBuffer, especifica onde os pixels sao escritos pelas operacoesglDrawPixels/glCopyPixels. O argumento source da funcao glReadBuffer especifica a fonte para os pixelslidos nas operacoes glReadPixels/glCopyPixels. Os valores possıveis para os argumentos source/destinationpoderao ser: GL NONE, GL FRONT, GL BACK, GL FRONT AND BACK, GL FRONT LEFT, GL FRONT RIGHT, . . .

Um caso pratico de utilizacao das operacoes com pixels seria, por exemplo, armazenar o conteudo do colorbuffer actual num ficheiro de imagem. A fim de ilustrar os conceitos explicados nesta seccao, exemplificamoscomo isso poderia ser feito:

// Ler o valor READ BUFFER actual

// (para repor mais tarde)

IntBuffer lastBuffer = IntBuffer.allocate (1);

gl.glGetIntegerv(GL2.GL_READ_BUFFER , lastBuffer );

// Vamos ler o FRONT BUFFER

1sendo x e y o canto inferior esquerdo

72

Page 74: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

gl.glReadBuffer(GL2.GL_FRONT );

// O ByteBuffer output ira armazenar temporariamente

// a nossa imagem

ByteBuffer output = ByteBuffer.allocate(width * height * 3); // RGB

gl.glReadPixels(

0, 0, // Canto inferior esquerdo

width , height , // Tamanho a ler

GL2.GL_BGR , // Formato Blue , Green , Red (targa)

GL2.GL_UNSIGNED_BYTE , // Tipo de dados unsigned byte

output

);

// Criar um TGA a partir do ByteBuffer

TGAImage img = TGAImage.createFromData(width , height , false , false , output );

try {

img.write("c:/my.tga"); // Guardar a imagem no disco

} catch (IOException e) {

// Falha ao escrever o ficheiro

}

// Restaurar o read buffer anterior

gl.glReadBuffer(lastBuffer.get (0));

A funcao glGet<Tipo>(int pname, ...)1 permite-nos obter informacao das variaveis do OpenGL (nestecaso o buffer de leitura actual - GL READ BUFFER). No JOGL a maior parte das funcoes que retornam valores,utilizam subclasses de Buffer (neste caso IntBuffer) para os armazenar. E importante no nosso codigoOpenGL, restaurarmos, na medida do possıvel, o estado anterior das coisas, daı obtermos o lastBuffer e serfeita a sua reposicao no fim do bloco de codigo, utilizando glReadBuffer(lastBuffer.get(0)). Seguidamenteespecificamos que o buffer para leitura sera o que se encontra visıvel (GL FRONT):

gl.glReadBuffer(GL2.GL_FRONT );

Inicializamos um ByteBuffer com o tamanho da janela (width×height) multiplicado por 3, uma vez quevamos armazenar as tres componentes de cor RGB, ficando entao width×height×3.

ByteBuffer output = ByteBuffer.allocate(width * height * 3);

Os ficheiros targa armazenam a informacao da cor na ordem BGR (Blue, Green, Red), pelo que o formatodos dadosm especificado e GL BGR. O seguinte codigo copia o conteudo do front buffer e coloca-o no nossoByteBuffer.

gl.glReadPixels(

0, 0, // Canto inferior esquerdo

width , height , // Tamanho a ler

GL2.GL_BGR , // Formato Blue , Green , Red (targa)

GL2.GL_UNSIGNED_BYTE , // Tipo de dados unsigned byte

output

);

Finalmente, criamos uma instancia de TGAImage com base no ByteBuffer output, utilizando a funcao:

TGAImage.createFromData(

int width , int height , // Tamanho da imagem

boolean hasAlpha , // Formato contem alpha

boolean topToBottom , // A imagem esta armazenada "ao contrario"

ByteBuffer output // ByteBuffer com os dados

);

Esta funcao e utilizada da seguinte forma:

TGAImage img = TGAImage.createFromData(width , height , false , false , output );

Finalmente para armazenar a nossa imagem no disco fazemos:

img.write("c:/my.tga")

A imagem my.tga ira conter o conteudo do nosso front buffer.

1http://www.opengl.org/sdk/docs/man/xhtml/glGet.xml

73

Page 75: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

7.4 Outras Operacoes com Imagens

Para alem das operacoes descritas, o OpenGL suporta ainda um conjunto de operacoes especiais aquando datransferencia da informacao dos pixels para e do color buffer.

Abaixo discutimos algumas das operacoes possıveis, bem como o codigo necessario para consegui-las (codigocompleto no Apendice C.2). O progama inicial para a demonstracao desta funcionalidade utiliza uma projeccaoortogonal configurada com a funcao:

glOrtho2D(

double left , double right ,

double bottom , double top

);

Em que left/right sao as coordenadas dos clipping planes verticais, e bottom/top sao as coordenadasdos clipping planes horizontais. Os valores de zNear/zFar especificados na funcao glOrtho tomam os valores0 e 1 respectivamente.

A nossa projeccao ortogonal ira coincidir com o tamanho da janela e do viewport. O metodo reshape(...)tera o seguinte aspecto:

public void reshape(GLAutoDrawable drawable , int x, int y, int width , int height) {

// Viewport coincide com a janela

gl.glViewport (0, 0, width , height );

gl.glMatrixMode(GL2.GL_PROJECTION );

gl.glLoadIdentity ();

// Configurar a projeccao ortogonal

glu.gluOrtho2D (0, width , 0, height );

// ...

}

A semelhanca do que aconteceu com o exemplo na seccao anterior, sera carregado o ficheiro horse.tga comrecurso ao ClassLoader do Java e a funcao TGAImage.read(...) para a variavel de classe img e lidos os bytespara um ByteBuffer (bb).

A imagem (Figura 7.5) sera mostrada no metodo display(...) utilizando:

gl.glDrawPixels(

img.getWidth(), img.getHeight(),

img.getGLFormat (),

GL2.GL_UNSIGNED_BYTE , bb);

Figura 7.5: Imaging.java mostranto horse.tga

Os blocos de codigo seguinte mostram como podemos implementar os efetios GaussianBlur, Sharpen, Emboss,Invert e Brighten. Alguns dos efeitos sao aplicados utilizando matrizes de convolucao, que permitem obter ovalor de cor de um pixel com base nos que se encontram nas suas imediacoes1.

O OpenGL permite aplicar este tipo de matrizes as imagens utilizando a funcao:

1Mais detalhes e exemplos em http://manual.gimp.org/en/plug-in-convmatrix.html

74

Page 76: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

glConvolutionFilter2D(

int target , int internalFormat ,

int width , int height ,

int format , int type ,

Buffer image );

Em que o target toma o valor GL2.GL CONVOLUTION 2D, o internalFormat indica o formato interno danossa matriz de convolucao (para o nosso caso GL2.GL RGB), width/height especificam o tamanho da matriz,format indica o formato dos pixels na imagem de destino, type especifica o tipo de dados da imagem e imagecontem a informacao da imagem.

Gaussian Blur

Para aplicar o efeito de gaussian blur (Figura 7.6) podemos utilizar a seguinte matriz de convolucao: 1 2 12 4 21 2 1

Para tal utilizamos o seguinte codigo:

// Matriz (convolution kernel) para efectuar gaussian blur

float norm = 16f; // normalizacao: somatorio dos valores da matriz

FloatBuffer mGaussian = FloatBuffer.wrap(new float [] {

1f/norm , 2f/norm , 1f/norm ,

2f/norm , 4f/norm , 1f/norm ,

1f/norm , 2f/norm , 1f/norm

});

// Aplicar a matriz

gl.glConvolutionFilter2D(

GL2.GL_CONVOLUTION_2D , GL2.GL_RGB , 3, 3,

GL2.GL_LUMINANCE , GL2.GL_FLOAT , mGaussian

);

// Activar convolucao 2D

gl.glEnable(GL2.GL_CONVOLUTION_2D );

// Mostrar

gl.glDrawPixels(

img.getWidth(), img.getHeight(),

img.getGLFormat (), GL2.GL_UNSIGNED_BYTE , bb);

// Desactivar convolucao 2D

gl.glDisable(GL2.GL_CONVOLUTION_2D );

Figura 7.6: Gaussian Blur

A forma de aplicar outras matrizes e semelhante. Apenas mudamos o ultimo argumento da funcaoglConvolutionFilter2D de mGaussian para a matriz criada. Como tal interessa apenas referir quais asmatrizes utilizadas e como foram inicializadas.

75

Page 77: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Emboss

A matriz utilizada para o efeito emboss (Figura 7.7) podera ser: 2 0 00 −1 00 0 −1

Inicializada com:

// Matriz (convolution kernel) para efectuar emboss

FloatBuffer mEmboss = FloatBuffer.wrap(new float [] {

2.0f, 0.0f, 0.0f,

0.0f, -1.0f, 0.0f,

0.0f, 0.0f, -1.0f

});

Figura 7.7: Emboss

Sharpen

A matriz utilizada para o efeito sharpen (Figura 7.8) podera ser: 0 −1 0−1 5 −10 −1 0

Inicializada com:

// Matriz (convolution kernel) para efectuar o sharpen

FloatBuffer mSharpen = FloatBuffer.wrap(new float [] {

0.0f, -1.0f, 0.0f,

-1.0f, 5.0f, -1.0f,

0.0f, -1.0f, 0.0f

});

Brighten

A operacao de brighten na imagem pode ser implementada de forma simples. Mudando para a matriz de corutilizando:

gl.glMatrixMode(GL2.GL_COLOR );

... podemos utilizar a funcao glScale uma vez que as transformacoes sao agora operadas na matriz de cor,como mostra o exemplo:

76

Page 78: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Figura 7.8: Sharpen

// Mudar para o matrix mode Color

gl.glMatrixMode(GL2.GL_COLOR );

// Aumentar todas as cores em 50%

gl.glScalef (2f, 2f, 2f);

// Voltar ao ModelView

gl.glMatrixMode(GL2.GL_MODELVIEW );

77

Page 79: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Capıtulo 8

Mapeamento de Texturas

Na computacao grafica convencional, cada elemento de um pixmaps corresponde a um elemento no ecra, daı onome de picture element (alias pixel). No entanto, quando mapeados a primitivas geometricas, raramente estespixmaps tem uma proporcao de 1 para 1.

Figura 8.1: Mapeamento de Texturas

A aplicacao de imagens a geometria e referida como texture ou texture mapping. A utilizacao de texturaspode aumentar dramaticamente o realismo e a qualidade dos nossos cenarios.

8.1 Carregamento de Texturas

O primeiro passo na aplicacao de texturas a nossa geometria, consiste no carregamento da imagem correspondentepara a memoria. Esta imagem passa a ser considerada o “estado actual” da textura. O carregamento de imagenssob a forma de texturas pode ser feito utilizando uma das tres versoes da funcao glTextImage:

glTexImage1D(

int target , int level , int internalFormat ,

int width , int border ,

int format , int type ,

Buffer pixels

);

glTexImage2D(

int target , int level , int internalformat ,

int width , int height , int border ,

int format , int type ,

Buffer pixels

);

glTexImage3D(

78

Page 80: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

int target , int level , int internalformat ,

int width , int height , int depth , int border ,

int format , int type ,

Buffer pixels

);

Estas tres funcoes permitem-nos dizer ao OpenGL tudo aquilo que ele precisa de saber relativamente a imagemcontida no array pixels. A funcao glTextImage carrega para a memoria, a imagem fornecida e torna-a atextura actual a ser aplicada na geometria. Este carregamento para a memoria pode ser dispendioso (alternativasdiscutidas mais a frente na Seccao 8.6).

O valor do target para cada uma das funcoes e respectivamente : GL TEXTURE 1D, GL TEXTURE 2D eGL TEXTURE 3D ou GL PROXY TEXTURE 1D, GL PROXY TEXTURE 2D ou GL PROXY TEXTURE 3D. Ao utilizar proxies,o OpenGL faz uma verificacao previa do que o sistema suporta em termos de compatibilidade, no caso de naohaver suporte, o estado da imagem e tornado invalido sem que qualquer tipo de erro seja reportado1.

O argumento level define o nıvel de mipmapping (discutido na Seccao 8.5.3), de momento utilizaremostexturas sem mipmapping, especificando o valor 0.

O argumento internalFormat, especifica quantos componentes de cor sao armazenados por texel, o espaconecessario ao armazenamento dos componentes e/ou se a textura e comprimida. A Tabela 8.1 lista os valoresmais comuns para este parametro.

Constante Armazenar os texels como:GL ALPHA Valores de alphaGL LUMINANCE Valores de luminanciaGL LUMINANCE ALPHA Valores de luminancia e alphaGL RGB Componentes de red, green e blueGL RGBA Componentes de red, green, blue e alpha

Tabela 8.1: Factores de Blending do OpenGL

Os valores de width, height e depth (apropriadamente) especificam as dimensoes da textura que estamosa carregar para a memoria. Estas dimensoes devem ser inteiros com base 2 (2x = 1, 2, 4, 8, . . . ), isto naoimplica que o mapeamento da textura seja quadrado, mas um valor nao 2x provovara que o mapeamento sejaimplicitamente desabilitado.

O argumento border especifica a largura da borda a volta da textura. Esta borda permite acrescentartexels adicionais a textura.

Os argumentos format, type, tem o mesmo objectivo que quando utilizados na funcao glDrawPixels. Oargumento pixels contem a informacao da imagem propriamente dita.

Para aplicarmos textura a nossa geometria temos que activar o seu estado apropriado. Para tal utilizamosas funcoes glEnable/glDisable com as constantes GL TEXTURE 1D, GL TEXTURE 2D e GL TEXTURE 3D2, comoilustra o exemplo:

glDisable(GL2.GL_TEXTURE_1D );

glEnable(GL2.GL_TEXTURE_2D );

8.1.1 Pipeline do Carregamento de Imagens

O carregamento de imagens no OpenGL (por ex.: utilizando glTexImage) obedece a um pipeline de processamentoa semelhanca do pipeline de transformacoes do OpenGL.

As operacoes de convolucao, pixel zoom, pixel packing, . . . (discutidas no capıtulo anterior) sao aplicadassegundo a Figura 8.2.

8.1.2 Utilizando o Color Buffer

E possıvel carregar texturas 1D e 2D a partir do color buffer, utilizando as seguintes funcoes:

glCopyTexImage1D(

int target , int level , int internalformat ,

int x, int y, int width ,

int border

);

1Para verificar se foi bem sucedido utiliza-se a funcao glGetTexParameter2E boa ideia desactivar os estados nao utilizados, uma vez que apenas um destes estados pode existir em simultaneo

79

Page 81: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Figura 8.2: Pipeline - Carregamento de Imagens

glCopyTexImage2D(

int target , int level , int internalformat ,

int x, int y, int width , int height ,

int border

);

O significado dos argumentos e semelhante aos argumentos da funcao glTexImage, mas neste caso o x, y,width e height especificam a area no color buffer a ler. O source buffer pode ser definido utilizando a funcaoglReadBuffer.

8.1.3 Actualizacao de Texturas

O carregamento repetido de texturas pode ser dispendioso em termos de processamento. Substituir umadeterminada textura pode ser mais rapido, na maior parte das vezes do que o carregamento utilizando glTexImage.Para tal utilizamos as funcoes:

glTexSubImage1D(

int target , int level ,

int xoffset ,

int width ,

int format , int type , Buffer data

);

glTexSubImage2D(

int target , int level ,

int xoffset , int yoffset ,

int width , int height ,

int format , int type , Buffer data

);

glTexSubImage3D(

int target , int level ,

int xoffset , int yoffset , int zoffset ,

int width , int height , int depth ,

int format , int type , Buffer data

);

Mais uma vez, os argumentos sao semelhantes aos utilizados em glTexImage. O xoffset, yoffset e zoffsetespecificam o local na textura actual para comecar a fazer a substituicao. O tamanho da textura no argumentodata e especificado pelos argumentos width, height e depth.

Finalmente um conjunto final de funcoes permite-nos substituir uma parte de uma textura utilizandoinformacao extraıda directamente do color buffer :

glCopyTexSubImage1D(

int target , int level ,

int xoffset ,

int x, GLint y,

int width

);

glCopyTexSubImage2D(

int target , int level ,

int xoffset , int yoffset ,

80

Page 82: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

int x, GLint y,

int width , int height

);

glCopyTexSubImage3D(

int target , int level ,

int xoffset , int yoffset , int zoffset ,

int x, GLint y,

int width

);

Podem ter reparado que nao existe uma funcao glCopyTexImage3D, isto deve-se ao facto do color bufferser bi-dimensional. No entanto podemos querer copiar informacao do color buffer para uma face (plano?) emespecıfico da nossa textura 3D, isso pode ser conseguido utilizando glCopyTexSubImage3D.

8.2 Mapeamento de Texturas a Geometria

Ao activar o mapeamento de texturas, o OpenGL permite-nos mapear qualquer textura a qualquer uma dasprimitivas. No entanto, e necessario fornecer ao OpenGL informacao acerca de como esse mapeamento e feito, oque e conseguido especificando uma coordenada na textura (texture coordinate) para cada vertice. Os texels1

nao sao especificados utilizando posicoes de memoria, tal como nos pixmaps, mas com um sistema de coordenadasmais abstracto. As coordenadas das texturas sao normalmente especificadas utilizando valores entre 0.0 e 1.0.

Os nomes das coordenadas sao s, t, r e q (semelhantes a coordenadas vectoriais x, y, z e w). A Figura 8.3mostra como os texels sao especificados com base em coordenadas 1D, 2D e 3D.

Figura 8.3: Coordenadas dos texels numa textura

O factor q representa um factor de escala da textura, a semelhanca do valor w dos vertices. Ou seja, osvalores das coordenadas das texturas sao realmente s/q, t/q e r/q. Por omissao q=1.0.

A coordenada na textura e especificada utilizando a funcao glTexCoord. Esta funcao tem um conjunto devariacoes para varios objectivos, a semelhanca das funcoes em geral do OpenGL. Algumas formas simples destasfuncoes sao:

glTexCoord1f(float s);

glTexCoord2f(float s, float t);

glTexCoord3f(float s, float t, float r);

A coordenada da textura e aplicada utilizando estas funcoes para cada um dos vertices. O OpenGL estica ouencolhe (alias stretching) a textura de forma a aplica-la na geometria especificada com base nas coordenadasespecıficadas. A forma como o stretching e feito depende do filtro da textura (texture filter) actual, discutidomais a frente. A Figura 8.4(a) mostra o exemplo de ume textura bi-dimensional aplicada a um GL QUAD. Noscantos do quad temos as coordenadas correspondentes da textura. A funcao glTexCoord tem que ser utilizadaantes de cada chamada a funcao glVertex.

Esta coincidencia entre geometria e textura e rara. Um exemplo mais comum sera o da Figura 8.4(b). Ascoordenadas da textura neste caso nao coinicidem com a forma da geometria.

1Um texel e um fragmento da textura, tal como o pixel de um pixmap

81

Page 83: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

(a) Textura bi-dimensional aplicada a umquad

(b) Textura bi-dimensional aplicada a umtriangulo

Figura 8.4: Aplicacao de textura bi-dimensional

Texture Matrix

A semelhanca da matriz MODELVIEW, PROJECTION e COLOR, e tambem possıvel operar transformacoes na matrizde coordenadas das texturas, podemos faze-lo passando para a texture matrix :

glMatrixMode(GL2.GL_TEXTURE );

Depois desta chamada todas as transformacoes sao operadas nas coordenadas da textura. No entanto,a stack de tranformacoes so tem dois nıveis de profundidade, o que implica que so podemos utilizar doisglPushMatrix/glPopMatrix encadeados.

8.3 Exemplo de Textura 2D

Existe um conjunto de conceitos ainda por adquirir relacionados com as texturas, tais como coordinate wrapping,texture filters e texture environment. A fim de os abordar utilizamos como plataforma um exemplo simples 2D,com configuracoes comuns destes parametros. O codigo fonte do exemplo Pyramid.java pode ser consultado noApendice C.3.

Figura 8.5: Exemplo pyramid

A Figura 8.5 ilustra a posicao dos cantos da piramide. A declaracao sera feita no metodo init() do nossoGLEventListener da seguinte forma:

// Cantos da Piramide

cTop = new GLVector (0.0f, .80f, 0.0f);

cBackLeft = new GLVector (-0.5f, 0.0f, -.50f);

cBackRight = new GLVector (0.5f, 0.0f, -0.50f);

cFrontRight = new GLVector (0.5f, 0.0f, 0.5f);

cFrontLeft = new GLVector (-0.5f, 0.0f, 0.5f);

Ainda no metodo init(), carregamos a imagem que ira servir para aplicar textura na nossa geometria, eactivamos o TEXTURE 2D:

82

Page 84: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

// ...

try {

InputStream stream = Imaging.class.getResourceAsStream("stone.tga");

img = TGAImage.read(stream );

bb = img.getData ();

stream.close ();

} catch (IOException e) {

e.printStackTrace ();

}

gl.glTexImage2D(GL2.GL_TEXTURE_2D , 0, GL2.GL_RGB ,

img.getWidth(), img.getHeight(),

0, img.getGLFormat (), GL2.GL_UNSIGNED_BYTE , bb);

// Activar as texturas

gl.glEnable(GL2.GL_TEXTURE_2D );

// ...

A face frontal tem que ser desenhada na ordem CCW para que a nossa textura seja aplicada correctamente.Assim a ordem de desenho correcta sera - cTop-cFrontLeft-cFrontRight. As coordenadas sao especificadas deforma semelhante as da Figura 8.4(b).

O codigo em baixo calcula o verctor normal a face frontal (vNormal), especifica as coordenadas da texturapara cada vertice (glTexCoord) e desenha-o1:

// Face da Frente

vNormal = GlTools.getNormalVector(cTop , cFrontLeft , cFrontRight );

gl.glNormal3fv(vNormal.toArray(), 0);

gl.glTexCoord2f (.5f, 1f);

cTop.draw ();

gl.glTexCoord2f (0f, 0f);

cFrontLeft.draw ();

gl.glTexCoord2f (1f, 0f);

cFrontRight.draw ();

O desenho das restantes faces do triangulo sao feitas de forma semelhante. A Figura 8.6 mostra o output doficheiro Pyramid.java.

Figura 8.6: Output do ficheiro Pyramid.java

1Por uma questao de conveniencia a class GLVector tem um metodo que desenha o vector actual utilizando a funcao glVertex

83

Page 85: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

8.4 Texture Environment

No exemplo Pyramid, a piramide e desenhada utilizando material de cor branca e a textura e aplicada de formaque as suas cores sao “escaladas” (scaled) segundo a cor da geometria (branca) (Figura 8.7).

Figura 8.7: Geometria Branca + Texture = Shaded Texture

A forma como a cor dos texels e combinada com a geometria subjacente e controlada pelo texture environment.A sua configuracao e feita utilizando a funcao glTexEnv:

glTexEnvi(int target , int pname , int param);

glTexEnvf(int target , int pname , float param);

glTexEnviv(int target , int pname , IntBuffer param);

glTexEnvfv(int target , int pname , FloatBuffer param);

Esta funcao pode ser usada de varias formas, e permite configurar parametros avancados das texturas. Noexemplo Pyramid, o environment mode e confiurado com o valor GL MODULATE:

gl.glTexEnvi(GL2.GL_TEXTURE_ENV , GL2.GL_TEXTURE_ENV_MODE , GL2.GL_MODULATE );

Com a opcao GL MODULATE, a cor do texel e multiplicada pela cor da geometria (depois do calculo das luzes).Ao especificar uma cor clara para a geometria (branca, no exemplo) a textura e afectada de forma igual ageometria. Isto permite com a mesma textura obter varias colorizacoes.

Utilizando GL REPLACE, podemos substituir completamente a cor da geometria pela cor do texel. Isto eliminatodos os efeitos aplicados a geometria subjacente. Se a textura tiver um alpha channel podemos utilizar estemodo para tornar zonas da geometria transparente se a imagem contiver blocos tambem transparentes, activandoo blending.

A opcao GL DECAL e semelhante a opcao GL REPLACE se a imagem nao tiver alpha channel. No caso de aimagem ter um alpha channel a cor da geometria transparece pela textura no valor do alpha, de forma que oobjecto parece ser blended com os fragmentos subjacentes.

Podemos tambem fazer o blending da geometria com uma cor fixa (Figura 8.8) utilizando:

gl.glTexEnvi(GL2.GL_TEXTURE_ENV ,

GL2.GL_TEXTURE_ENV_MODE , GL2.GL_BLEND );

gl.glTexEnvfv(GL2.GL_TEXTURE_ENV ,

GL2.GL_TEXTURE_ENV_COLOR , new float[] {1f, 0f, 0f, 0f}, 0);

Figura 8.8: Utilizando GL BLEND

Finalmente podemos fazer a adicao do valor da cor dos texels aos fragmentos da geometria, utilizando GL ADDcomo argumento. Os valores que ultrapassem 1.0 sao truncados, o que podera provocar saturacao das cores.

84

Page 86: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

8.5 Parametrizacao de Texturas

O texturing no OpenGL envolve mais do que o simples mapeamento de uma textura num dos lados de umtriangulo. Um conjunto de parametros afectam o compotamento e a renderizacao das texturas aplicadas. Estesparametros podem ser configurados com a funcao glTexParameter, utilizando uma das variantes:

glTexParameterf(int target , int pname , float param);

glTexParameteri(int target , int pname , int param);

glTexParameterfv(int target , int pname , FloatBuffer params );

glTexParameteriv(int target , int pname , IntBuffer params );

O argumento target, especifica o modo da textura para o parametro que estamos a configurar (GL TEXTURE 1D,GL TEXTURE 1D, GL TEXTURE 3D). O parametro a configurar e especificado em pname e o seu valor e definido noultimo argumento da funcao (param/params).

8.5.1 Filtering Basico

Proque raramente a geometria coincide com a textura em termos de pixels (ao contrario dos pixmaps), asimagens de textura sao normalmente “deformadas” para obedecer as coordenadas especificadas para a geometria.A imagem pode ser encolhida ou esticada, ou ambos na aplicacao a geometria.

O processo de calculo dos fragmentos de cor, quando uma textura esta a ser aplicada, e chamado defiltering. Podemos especificar os filtros utilizados na altura de encolher (minification) ou de esticar (magni-fication). Os parametros para a configuracao destes valores sao, respectivamente, GL TEXTURE MIN FILTER eGL TEXTURE MAG FILTER. Podemos especificar dois valores para este parametro:

(a) Filtering com GL NEAREST (b) Filtering com GL LINEAR

Figura 8.9: Aplicacao de textura bi-dimensional

• GL NEAREST: Simples e rapido. Sao apuradas as coordenadas de cada fragmento para cada texel, a corcorrespondente a essa coordenada e utilizada como a cor do fragmento da textura. A tecnica de nearestneighbour e caracterizada pelo aparecimento de blocos de uma so cor, quando a geometria e aumantada(Figura 8.9(a)). Pode ser configurado utilizando:

gl.glTexParameteri(GL2.GL_TEXTURE_2D ,

GL2.GL_TEXTURE_MAG_FILTER , GL2.GL_NEAREST );

gl.glTexParameteri(GL2.GL_TEXTURE_2D ,

GL2.GL_TEXTURE_MIN_FILTER , GL2.GL_NEAREST );

• GL LINEAR: Requer mais processamento, mas o resultado justifica. O custo de processamento do linearfiltering e, nos computadores actuais despresıvel. O valor da cor de cada fragmento da textura e conseguidopela interpolacao linear (media ponderada) dos texels que rodeiam a sua coordenada. Pode ser configuradoutilizando:

gl.glTexParameteri(GL2.GL_TEXTURE_2D ,

GL2.GL_TEXTURE_MAG_FILTER , GL2.GL_LINEAR );

gl.glTexParameteri(GL2.GL_TEXTURE_2D ,

GL2.GL_TEXTURE_MIN_FILTER , GL2.GL_LINEAR );

85

Page 87: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

8.5.2 Texture Wrap

Normalmente especificamos as coordenadas das texturas com valores entre 0.0 e 1.0 relativamente ao texturemap. A forma como sao tratados os valores que saem fora do intervalo [0.0, 1.0] e definida no parametro texturewrap. O valor deste parametro e definido individualmente para as coordenada s, t e r, utilizando a funcaoglTexParameteri com o pname - GL TEXTURE WRAP S, GL TEXTURE WRAP T, or GL TEXTURE WRAP R. Os modosdisponıveis para o wrapping sao:

• GL REPEAT: Neste modo a textura e repetida na direccao do valor que ultrapassou o intervalo. Isto permiteutilizar uma textura pequena para superfcıcies grandes. Se a imagem for bem escolhida podemos dar asensacao de uma textura muito maior a custa de uma porcao mais pequena.

• GL CLAMP: Os texels sao obtidos a partir da cor borda da imagem. Esta cor e especificada no parametroGL TEXTURE BORDER COLOR (configurado com glTexParameterfv).

• GL CLAMP TO EDGE: Faz com que os valores fora da borda nao sejam utilizados no calculo da interpolacaolinear.

• GL CLAMP TO BORDER: Utiliza os valores da borda quando as coordenadas da textura caem fora do intervalo[0.0, 1.0].

A escolha do tipo de wrapping influencia o modo como o filtering funciona, principalmente quando estamos ausar GL LINEAR. Como o valor do fragmento e calculado com base na vizinhanca, o calculo junto das bordas datextura pode representar um problema se nos limitarmos a fazer clamping. O problema pode ser resolvido deforma simples quando utilizamos GL REPEAT. Os novos texels sao obtidos a partir da linha/coluna adjacentes, queno repeat mode sao tirados a partir do outro extremo da imagem (como se juntassemos as duas arestas opostasda imagem). Isto funciona especialmente bem quando usamos texturas em que um lado encaixa perfeitamenteno outro (por ex.: esferas).

Uma aplicacao comum para o clamping pode ser vista no mapping de texturas que nao caberiam em memoriapelo seu tamanho. Em vez disso, sao utilizados “mosaicos”. No entanto, a nao utilizacao de GL CLAMP TO EDGEpode levar ao aparecimento de artefactos indesejados no texture mapping.

8.5.3 Mipmapping

O mipmapping e uma tecnica que permite melhorar a performance de renderizacao e a qualidade visual de umacena. O melhoramento e feito enderecando dois problemas comuns na aplicacao de textura a geometria:

1. Scintillation: Consiste de artefactos de aliasing que aparecem nas superfcıcies quando os objectos saomuito renderizados muito pequenos, comparados com a textura que lhes e aplicada. Este efeito e maisnotorio quando existe movimento na cena, ou quando o observador se encontra em movimento.

2. Performance: Uma grande quantidade de memoria deve ser carregada com texturas e processada (filtering)para renderizar um conjunto limitado (ou pequeno) de fragmentos no ecra. O que provoca um decrescimona performance a medida que a quantidade e tamanho das texturas aumenta.

Uma solucao para estes dois problemas poderia passar pela utilizacao de uma textura mais pequenta. Noentanto, quando nos aproximamos do objecto, essa textura sera inevitavelmente escalada, tornando as nossasmenos nıtidas ou cheias de artefactos.

A solucao deveras eficaz passa pela utilizacao de mipmapping1. O mipmapping consiste na utilizacao devarias imagens com diferentes tamanhos e resolucoes para a mesma textura. O OpenGL utiliza entao tiras dasimagens para aplicar a geometria de forma apropriada e com base num novo conjunto de filtros. Isto podera serfeito a custa de um pouco mais de memoria e/ou processamento.

Uma textura mipmapped consiste de um conjunto de imagens, onde cada uma e metade da anterior ate queatingem o tamanho 1x1 (Figura 8.10).

As imagens nao precisam de ser necessariamente quadradas, neste caso quando uma coordenada chega a 1 aoutra e dividida repetidamente ate que chega a 1x1.

A utilizacao de mipmapping podera ocupar ate 3× mais memoria de textura que a nao utilizacao.Os nıveis de mipmap para cada imagem sao especificados no segundo argumento (level) da funcao glTexImage

aquando do seu carregamento. O primeiro nıvel sera 0, depois 1, 2, 4 e por aı fora numa base 2x em que x e aiteracao da imagem. Quando o mipmapping nao esta a ser utilizado, a imagem especificada no valor 0 e tomadopor omissao.

1Palavra proveniente de multum in parvo - muitas coisas num local pequeno

86

Page 88: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Figura 8.10: Conjunto de imagens Mipmapped

Por omissao, para utilizar o mipmapping, temos que especificar uma imagem para cada nıvel de mip.Podemos, no entanto, definir qual o valor base e maximos utilizando os parametros GL TEXTURE BASE LEVEL eGL TEXTURE MAX LEVEL, como mostra o exemplo:

gl.glTexParameteri(GL2.GL_TEXTURE_2D , GL2.GL_TEXTURE_BASE_LEVEL , 0);

gl.glTexParameteri(GL2.GL_TEXTURE_2D , GL2.GL_TEXTURE_MAX_LEVEL , 4);

Desta forma, serao apenas utilizados os nıveis 0, 1, 2 e 4 de mipmapping para aplicar a nossa geometria.Podemos ainda especificar os valores mınimos e maximos de detalhe a ser utilizados alterandos os valores deGL TEXTURE MIN LOD e GL TEXTURE MAX LOD.

8.5.4 Mipmap Filtering

Com o mipmapping ganhamos um novo conjunto de modos de filtering de texturas. Estes novos modos estaodescritos na Tabela 8.2.

Constante DescricaoGL NEAREST Calcular com base no “vizinho mais proximo” no nıvel

de mip actualGL LINEAR Calcular com base na interpolacao linear da vizinhanca

no nıvel de mip actualGL NEAREST MIPMAP NEAREST Seleccionar o nıvel de mip mais proximo e operar filtro

nearestGL NEAREST MIPMAP LINEAR Interpolacao linear entre nıveis de mip e operar filtro

nearestGL LINEAR MIPMAP NEAREST Seleccionar o nıvel de mip mais proximo e operar filtra-

gem linearGL LINEAR MIPMAP LINEAR Interpolacao linear entre nıveis de mip e operar filtragem

linear (alias trilinear mipmapping)

Tabela 8.2: Mipmap Filtering

O simples facto de especificarmos o nıvel de mip na funcao glTexImage nao activa o mipmapping. Se o filtroda textura estiver configurado para GL LINEAR ou GL NEAREST, os nıveis de mip 6= 0 sao ignorados. Um dosfiltros de mipmapping deve ser especificado para que o mipmapping seja usado.

As constantes tomam a forma GL <FILTRO> MIPMAP <SELECTOR>, onde o FILTRO especifica o tipo de filtragemoperado no nıvel de mip seleccionado. O SELECTOR, como o nıvel de mip e seleccionado. Se seleccionarmosum modo de filtering que activa o mipmapping sem carregar os nıveis de mip correspondente, desactivamos omapping de texturas.

A escolha do filtro depende um pouco da aplicacao e dos requisitos de performance. Utilizando o filtroGL NEAREST MIPMAP NEAREST, conseguimos um desempenho melhor e um valor de scintillation reduzido, noentanto o aspecto visual final nao e o mais agradavel. O GL LINEAR MIPMAP NEAREST e utilizado normalmentepara acelerar jogos, mantendo um aspecto visual melhorado, ainda que a selecccao do nıvel de mip seja feita porproximidade.

A utilizacao de nearest para a selecccao do nıvel de mip, podera tambem conduzir ao aparecimento deartefactos indesejados. Quando vista de uma forma obliqua, e perceptıvel a transicao de um nıvel para o outrode mip. A utilizacao de uma seleccao LINEAR (GL * MIPMAP LINEAR) permite uma interpolacao adicional entrenıveis para eliminar esta zona de transicao, ainda que a custa de processamento adicional.

8.5.5 Geracao de nıveis de Mipmapping

Poderiamos chamar de forma reptida a funcao glTexImage para conseguirmos popular todos os nıveis de mip.No entanto, isto pode ser uma tarefa ardua, sendo que nem sempre o developer tem acesso a todos tamanhos da

87

Page 89: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

imagem da textura. A biblioteca GLU fornece um conjunto de funcoes que permitem convenientemente gerar osvarios nıveis para cada imagem. Estas funcoes carregam ainda a imagem automaticamente utilizando a funcaoglTexImage. As variantes da funcao sao:

gluBuild1DMipmaps(

int target , int internalFormat ,

int width ,

int format , int type ,

Buffer data

);

gluBuild2DMipmaps(

int target , int internalFormat ,

int width , int height ,

int format , int type ,

Buffer data

);

gluBuild3DMipmaps(

int target , int internalFormat ,

int width , int height , int depth ,

int format , int type ,

Buffer data

);

A utilizacao destas funcoes e semelhante a utilizacao da funcao glTexImage, no entanto, nao especificamos oargumento level uma vez que os nıveis de mip sao gerados de forma automatica. A imagem e redimensionadautilizando um box filter, que podera nao ter o mesmo efeito que utilizando um programa de desenho (como oPhotoshop).

Para o caso de querermos especificar o nıvel de mip a que uma imagem se refere1 aquando da geracao dosnıveis podemos ainda utilizar:

gluBuild1DMipmapLevels(

int target , int internalFormat ,

int width ,

int format , int type , int level ,

int base , int max , Buffer data

);

gluBuild2DMipmapLevels(

int target , int internalFormat ,

int width , int height ,

int format , int type , int level ,

int base , int max , Buffer data

);

gluBuild3DMipmapLevels(

int target , int internalFormat ,

int width , int height , int depth ,

int format , int type , int level ,

int base , int max , Buffer data

);

Aqui o level especifica o nıvel de mip a que a imagem (data) se refere e o base e max, definem o nıvelmınimo e maximo de mip. Estas funcoes sao utilizadas para gerar os nıveis dentre base e max.

8.5.6 Geracao de Mipmaps por Hardware

Se soubermos que queremos utilizar todos os nıveis de mipmapping, podemos utilizar a aceleracao de hardwaredo OpenGL para os gerar de forma rapida. Isto e conseguido fazendo:

gl.glTexParameteri(GL2.GL_TEXTURE_2D , GL2.GL_GENERATE_MIPMAP , GL2.GL_TRUE );

Quando o valor de GL GENERATE MIPMAP e GL TRUE, as chamadas subsequentes a glTexImage e glTexSubImageque actualizam o nıvel 0, actualizam de forma automatica todos os outros nıveis2. A utilizacao desta funcionalidadepermite um ganho em desempenho relativamente a utilizacao de gluBuildMipmaps.

1Por exemplo: temos a imagem para o nıvel 4 de mip e estamos a gerar do 0 ao 82Esta funcionalidade esta disponıvel apenas para versoes do OpenGL ≥ 1.4

88

Page 90: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

8.5.7 Level Of Detail (LOD) Bias

O OpenGL calcula o nıvel de mip a utilizar com base no numero de nıveis disponıveis no tamanho da geometriaa renderizar. Podemos, no entanto, dizer ao OpenGL para “polarizar” o valor do seu criterio (valores de mipmais baixos) ou diminuir essa polarizacao (valores mais altos de mip). O ajuste deste valor podera aumentar aperformance (utilizando os nıveis mais baixos de mip) ou aumentar a fidelidade das nossas texturas (utilizandonıveis mais altos de mip). O valor desta polarizacao pode ser configurado utilizando, por exemplo:

gl.glTexEnvf(GL2.GL_TEXTURE_FILTER_CONTROL , GL2.GL_TEXTURE_LOD_BIAS , -1.5);

No exemplo em cima, o detalhe das texturas e aumentado ligeiramente (nıvel de mip mais baixo), resultandonum cenario com aspecto melhorado, ainda que a custa de processamento adicional.

8.6 Texture Objects

O carregamento e gestao das texturas representam uma porcao importante no desenvolvimento de qualqueraplicacao 3D, tal como os jogos, em particular.

As funcoes glTexImage, glTexSubImage e gluBuildMipmaps, movem grandes quantidades de memoria, peloque a troca entre texturas seria uma operacao dispoendiosa, em termos de processamento.

Os texture objects permitem-nos carregar mais do que um estado de textura de cada vez e trocar entre elasde forma rapida. O estado das texturas e armazenado e rotulado com um identificador inteiro. A alocacao detexturas com identificadores e feita utilizando:

glGenTextures(int n, IntBuffer textures );

O argumento n especifica o numero de texturas que queremos armazenar e o argumento textures e umarray de inteiros (IntBuffer) que ira conter os identificadores gerados. Para fazer o bind de uma textura a umdestes estados fazemos:

glBindTexture(int target , int texture );

Mais uma vez o target pode tomar o valor GL TEXTURE 1D, GL TEXTURE 2D ou GL TEXTURE 3D. O argumentotexture e o identificador ao qual vamos fazer o bind. O carregamentos de texturas e parametrizacoes subsequentesafectaram apenas o estado da textura representado pelo identificador texture.

Para apagar um determinado estado utilizamos a funcao:

glDeleteTextures(int n, IntBuffer textures );

O significado dos argumentos e o mesmo da funcao glBindTexture.Podemos verificar se um determinado identificador contem um estado valido utilizando a funcao:

boolean glIsTexture(int texture );

O valor de retorno da funcao sera GL TRUE no caso de ter sido alocado um estado a este identificador.

89

Page 91: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Capıtulo 9

Mapeamento de Texturas: ConceitosAvancados

9.1 Cor Secundaria

Antes de aplicar as texturas a geometria, o OpenGL calcula os valores individuais de cada fragmento, incluindo acomponente de LIGHTING. O valor de cada fragmento e mais tarde combinado com os texels (depois do processode filtering) dando origem a textura.

Este processo diminui drasticamente a visibilidade da componente especular.A solucao para este problema passa pela aplicacao da componente especular da luz apenas apos ter sido

aplicada a textura. Esta tecnica e designada de secondary specular color. Apesar de poder ser aplicada de formamanual, o OpenGL contem ja um mecanismo que faz esse trabalho de forma automatica. Para tal basta-nosalterar o nosso light model, da seguinte forma:glLightModeli(GL2.GL_LIGHT_MODEL_COLOR_CONTROL , GL2.GL_SEPARATE_SPECULAR_COLOR );

As Figuras 9.1(a) e 9.1(b) mostram as diferencas sem e com a separacao da componente especular.

(a) Sem GL SEPARATE SPECULAR COLOR (b) Com GL SEPARATE SPECULAR COLOR

Figura 9.1: Utilizacao de Secondary Color

Para retomar o light model anterior podemos utilizar:glLightModeli(GL2.GL_LIGHT_MODEL_COLOR_CONTROL , GL2.GL_COLOR_SINGLE );

9.2 Anisotropic Filtering

Apesar de nao fazer parte da espeficicacao do OpenGL, a tecnica de Anisotropic Filtering e suportada pela maiorparte dos fabricantes. A sua utilizacao permite um melhoramento das operacoes de filtering das texturas.

90

Page 92: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

No processo de filtering, o OpenGL utiliza os texels na vizinhanca de uma determinada posicao para fazero sampling da textura1. Com este processo obtemos resultados perfeitos quando a textura e vista de frente(perpendicularmente a geometria), no entanto, quando a geometria e vista de forma oblıqua podemos observar aperda de informacao da imagem (como que uma desfocagem).

Para evitar este efeito a area da vizinhanca utilizada no filtering tem agora uma forma adequada a posicao doobservador (Figura 9.2). Isto implica que varios samples da imagem sejam feitos, relativamente ao observador,resultado numa imagem anisotropica.

Figura 9.2: Textura normal vs Anisotropic Filtering

Podemos aplicar o anisotropic filtering a texturas basicas e mipmapped. Para tal sao efectuados 3 passos:

1. Verificamos se a extensao para anisotropic filtering esta disponıvel:

GL2 gl = ...;

gl.isExtensionAvailable("GL_EXT_texture_filter_anisotropic");

2. Obtemos valor maximo de anisotpropia suportado:

// Array temporario de saida para a funcao glGetFloatv (...)

FloatBuffer out = FloatBuffer.allocate (1);

gl.glGetFloatv(GL2.GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT , out);

// Valor maximo de anisotropia esta na posicao 0 de out

float largest = out.get (0);

3. Finalmente definimos a quantidade de anisotropia utilizando:

gl.glTexParameterf(

GL2.GL_TEXTURE_2D ,

GL2.GL_TEXTURE_MAX_ANISOTROPY_EXT ,

largest

);

Quando maior o valor de anisotropia definido, maior sera a quantidade de texels que sao utilizados noprocesso de filtering.

Pegando no exemplo Tunnel.java dos capıtulos anteriores, as texturas serao carregadas da seguinte formano metodo init():

// ...

// Se afLargest se mantiver a 0 nao suporta anisotropic filtering

float afLargest = 0f;

// Se o anisotropic filtering for suportado obtemos o valor maximo

// e armazenamos em afLargest

if(gl.isExtensionAvailable("GL_EXT_texture_filter_anisotropic")) {

FloatBuffer out = FloatBuffer.allocate (1);

gl.glGetFloatv(GL2.GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT , out);

afLargest = out.get (0);

}

for (int i = 0; i < textureNames.size (); i++) {

1Utilizando por exemplo GL NEAREST e GL LINEAR

91

Page 93: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

// Fazer o bind do estado da textura ao identificador

gl.glBindTexture(GL2.GL_TEXTURE_2D , textures.get(i));

// Carregar e Ler a imagem para a nossa textura

TGAImage img = loadTexture(textureNames.get(i));

ByteBuffer bb = img.getData ();

glu.gluBuild2DMipmaps(GL2.GL_TEXTURE_2D , GL2.GL_RGBA ,

img.getWidth(), img.getHeight(), img.getGLFormat (),

GL2.GL_UNSIGNED_BYTE , bb);

// Parametros da textura (ignorar para ja)

gl.glTexParameteri(GL2.GL_TEXTURE_2D , GL2.GL_TEXTURE_MAG_FILTER ,

GL2.GL_LINEAR );

gl.glTexParameteri(GL2.GL_TEXTURE_2D , GL2.GL_TEXTURE_MIN_FILTER ,

GL2.GL_LINEAR_MIPMAP_LINEAR );

gl.glTexParameteri(GL2.GL_TEXTURE_2D , GL2.GL_TEXTURE_WRAP_S ,

GL2.GL_CLAMP_TO_EDGE );

gl.glTexParameteri(GL2.GL_TEXTURE_2D , GL2.GL_TEXTURE_WRAP_T ,

GL2.GL_CLAMP_TO_EDGE );

// Se afLargest for > 1f o anisotropic filtering e suportado

if(afLargest > 1f)

gl.glTexParameterf(GL2.GL_TEXTURE_2D ,

GL2.GL_TEXTURE_MAX_ANISOTROPY_EXT ,

afLargest );

}

As Figuras 9.3(a) e 9.3(b) ilustram a diferenca entre o filtering e sem e com utilizacao de anisotropic filtering.

(a) Sem Anisotropic Filtering (b) Com Anisotropic Filtering

Figura 9.3: Utilizacao de Anisotropic Filteing

9.3 Compressao de Texturas

A indiscutıvel melhoria introduzida pelas texturas e normalmente acompanhada por uma quantidade importantede memoria ocupada e algum overhead de processamento. No entanto, o mais preocupante e realmente o espacoocupado (normalmente na memoria grafica).

O OpenGL permite ao utilizador fazer o carregamento de texturas comprimidas1. Os dados da texturamantem-se comprimidos na memoria grafica, o que pode representar um ganho no desempenho aquando doswapping de texturas, bem como uma menor quantidade de memoria ocupada.

1Na maior parte das implementacoes

92

Page 94: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

As texturas carregadas nao precisam de estar inicialmente comprimidas. Na altura do carregamento destaspodemos solicitar a compressao ao OpenGL, alterando o internalFormat para um dos valores na Tabela 9.1.

Formato Comprimido Formato BaseGL COMPRESSED ALPHA GL ALPHAGL COMPRESSED LUMINANCE GL LUMINANCEGL COMPRESSED LUMINANCE ALPHA GL LUMINANCE ALPHAGL COMPRESSED INTENSITY GL INTENSITYGL COMPRESSED RGB GL RGBGL COMPRESSED RGBA GL RGBA

Tabela 9.1: Formatos de Texturas Comprimidas

Ao utilizar os formatos de texturas comprimidos, e adicionado um ligeiro overhead no carregamento inicialdas texturas. No entanto, este overhead e despresıvel face as melhorias na utilizacao da memoria.

Se por algum motivo a textura nao for carregada com o formato comprimido solicitado, o OpenGL alternapara o formato base correspondente (Tabela 9.1).

Quando utilizamos estes formatos para a compressao de texturas, o OpenGL tenta determinar a melhor formade comprimir a textura. Podemos dizer ao OpenGL para escolher um algortimo mais rapido ou com melhorqualidade utilizando a funcao glHint:

• Metodo mais rapido:

gl.glHint(GL2.GL_TEXTURE_COMPRESSION_HINT , GL2.GL_FASTEST );

• Metodo com melhor qualidade:

gl.glHint(GL2.GL_TEXTURE_COMPRESSION_HINT , GL2.GL_NICEST );

• Deixar o OpenGL decidir:

gl.glHint(GL2.GL_TEXTURE_COMPRESSION_HINT , GL2.GL_DONT_CARE );

9.4 Geracao de Coordenadas de Texturas

Como vimos no capıtulo anterior, a atribuicao das coordenadas das texturas a geometria e uma tarefa simplesquando estamos a lidar com superfıcies simples (triangulos, quadrados, etc. . . ). No entanto, para superfıciescomplexas, o calculo das coordenadas correctas pode ser uma tarefa complexa.

Ate certo ponto, o OpenGL consegue gerar automaticamente estas coordenadas das texturas para cada vertice.Para activar/desactivar a geracao das coordenadas (s, r, t e q), utilizamos as funcoes glEnable()/glDisable()com as flags - GL TEXTURE GEN S, GL TEXTURE GEN R, GL TEXTURE GEN T e GL TEXTURE GEN Q.

Quando a geracao de coordenadas esta activa, quaisquer chamadas subsequentes as funcoes glTextCoord saoignoradas.

A funcao utilizada pelo o OpenGL para o calculo destas coordenadas e definida utilizando uma das funcoes:

glTexGenf(int coord , int pname , float param);

glTexGenfv(int coord , int pname , FloatBuffer param);

O argumento coord pode tomar um dos valores - GL S, GL T, GL R ou GL Q. O argumento pname devera serum de - GL TEXTURE GEN MODE, GL OBJECT PLANE ou GL EYE PLANE. O argumento param define os valores paraa funcao utilizada no argumento pname.

Para exemplificar a utilizacao das funcoes de calculo das coordenadas foi criado o programa TexGen.java(ver Apendice C.4). O programa permite ao utilizador alterar a funcao de calculo em runtime, utilizando asteclas 1 = Object Linear, 2 = Eye Linear e 3 = Sphere Map.

9.4.1 Oject Linear Mapping

Quando a funcao para a geracao das texturas e GL OBJECT LINEAR, as coordenadas das texturas sao geradascom base na seguinte funcao:

CoordOLM = P1 × x+ P2 × y + P3 × z + P4 × w

93

Page 95: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Onde x, y, z e w sao as coordenadas dos vertices do objecto onde esta a ser aplicada a textura e os valoresPi (i = [1; 4]) sao os coeficientes de uma equacao do plano.

Nesta caso, as coordenadas da textura sao projectadas sobre a geometria, sob o ponto de vista do planodescrito pela equacao. O excerto de codigo em baixo do programa TexGen.java, projecta as coordenadas s e t,a partir do plano z = 0:

FloatBuffer zPlane = FloatBuffer.wrap(new float [] {0f, 0f, 1f, 0f});

gl.glTexGeni(GL2.GL_S , GL2.GL_TEXTURE_GEN_MODE ,

GL2.GL_OBJECT_LINEAR );

gl.glTexGeni(GL2.GL_T , GL2.GL_TEXTURE_GEN_MODE ,

GL2.GL_OBJECT_LINEAR );

gl.glTexGenfv(GL2.GL_S , GL2.GL_OBJECT_PLANE , zPlane );

gl.glTexGenfv(GL2.GL_T , GL2.GL_OBJECT_PLANE , zPlane );

De notar que e ainda possıvel definir funcoes diferentes para cada coordenada (neste caso s e t). Esta tecnicamapeia as coordenadas da texturas em coordenadas no objecto, independentemente das tranformacoes em curso.O resultado final pode ser observado na Figura 9.4. Na Figura e possıvel observar o objecto com a texturaaplicada e a textura propriamente dita.

Figura 9.4: Funcao Object Plange

9.4.2 Eye Linear Mapping

Quando a funcao de geracao das coordenadas e GL EYE LINEAR, as coordenadas sao geradas de forma semelhantea GL OBJECT LINEAR, mas neste caso os valores de x, y, z e w referem-se agora a localizacao do observador. Aequacao do plano tem tambem os seus coeficientes invertidos.

CoordELM = −P1 × xeye − P2 × yeye − P3 × zeye − P4 × weye

A textura parece deslizar sobre a geometria a medida que e afectada pelas transformacoes geometricas. Oexcerto do programa TexGen.java abaixo mostra como podemos utilizar o eye linear mapping para o mesmoplano z = 0:

FloatBuffer zPlane = FloatBuffer.wrap(new float [] {0f, 0f, 1f, 0f});

gl.glTexGeni(GL2.GL_S , GL2.GL_TEXTURE_GEN_MODE ,

GL2.GL_EYE_LINEAR );

gl.glTexGeni(GL2.GL_T , GL2.GL_TEXTURE_GEN_MODE ,

GL2.GL_EYE_LINEAR );

gl.glTexGenfv(GL2.GL_S , GL2.GL_EYE_PLANE , zPlane );

gl.glTexGenfv(GL2.GL_T , GL2.GL_EYE_PLANE , zPlane );

O resultado pode ser observado nas Figuras 9.5(a) e 9.5(b).

94

Page 96: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

(a) GL EYE LINEAR (b) GL EYE LINEAR apos ligeira rotacao

Figura 9.5: Funcao GL EYE LINEAR

9.4.3 Sphere Mapping

Ao utilizar o GL SPHERE MAP o OpenGL calcula as coordenadas das texturas de tal forma que ficamos coma impressao de que o objecto actual esta a reflectir a textura que lhe aplicamos. O excerto do programaTexGen.java em baixo exemplifica a utilizacao da funcao sphere mapping :

gl.glTexGeni(GL2.GL_S , GL2.GL_TEXTURE_GEN_MODE , GL2.GL_SPHERE_MAP );

gl.glTexGeni(GL2.GL_T , GL2.GL_TEXTURE_GEN_MODE , GL2.GL_SPHERE_MAP );

Para obter uma sensacao de reflexao convincente, uma textura e normalmente adquirida utilizando uma lentefish-eye.

Apesar de o sphere mapping ter sido substituıdo pelo cube mapping (Seccao 9.5), ainda se encontram algunscasos de uso, na medida em que apenas uma textura e necessaria, ao contrario do cube mapping onde saonecessarias 6 !. Se apenas queremos dar a sensacao de reflexao e nao realismo, o sphere mapping e uma boaescolha.

Um exemplo em que o sphere mapping faz um match perfeito, e o caso das superfıcies que nao reflectem oambiente de forma nao espelhada, como por exemplo uma peca de metal nao uniforme.

No programa TexGen.java foi utilizada a imagem de fundo (constante em todos os exemplos) para aplicarna textura com a funcao sphere map. Quando aplicamos transformacoes, o torus parece reflectir o ambiente(Figura 9.6).

9.5 Cube Mapping

Os ultimos dois modos de geracao de coordenadas sao o GL REFLECTCION MAP e o GL NORMAL MAP, ambos requerema utilizacao de um tipo especial de textura de ambiente (environment texture) - o cube map.

A Figura 9.7 mostra a disposicao das seis texturas nas faces do cube map utilizado no programa CubeMap.java(ver Apendice C.5).

Este mapa sera uma aproximacao das vistas (frente, tras, esquerda, direita, “tecto” e chao) de um cenarioreal. Utilizando o modo GL REFLECTION MAP, e possıvel criar uma reflexao bastante precisa.

9.5.1 Carregamento do Cube Map

O cube mapping adiciona 6 novos valores para o primeiro argumento da funcao glTexImage2D:

• GL TEXTURE CUBE MAP POSITIVE X

• GL TEXTURE CUBE MAP NEGATIVE X

• GL TEXTURE CUBE MAP POSITIVE Y

• GL TEXTURE CUBE MAP NEGATIVE Y

95

Page 97: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Figura 9.6: Sphere Map

Figura 9.7: Cube Map do programa CubeMap.java

96

Page 98: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

• GL TEXTURE CUBE MAP POSITIVE Z

• GL TEXTURE CUBE MAP NEGATIVE Z

As constantes representam a direccao no ambiente real para a textura que estamos a carregar. Por exemplopara definirmos a textura para a direccao x positiva, poderiamos utilizar a funcao glTexImage2D da seguinteforma:

TGAImage img = loadImage("facex.tga");

glTexImage2D(GL2.GL_TEXTURE_CUBE_MAP_POSITIVE_X , 0,

img.getGLFormat (), img.getWidth(), img.getHeight(), 0,

GL_RGBA , GL_UNSIGNED_BYTE , img.getData ());

O excerto de codigo em baixo pertence ao programa CubeMap.java, e ilustra a forma como as texturaspoderiam carregadas para o cube map:

// Obter os identificadores

IntBuffer textures = IntBuffer.allocate(NumTextures );

gl.glGenTextures(NumTextures , textures );

// ...

// Direccoes para as texuras do cubo

List <String > textureNames = new ArrayList <String >();

private static final int[] CubeDirection = {

GL2.GL_TEXTURE_CUBE_MAP_POSITIVE_X ,

GL2.GL_TEXTURE_CUBE_MAP_NEGATIVE_X ,

GL2.GL_TEXTURE_CUBE_MAP_POSITIVE_Y ,

GL2.GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ,

GL2.GL_TEXTURE_CUBE_MAP_POSITIVE_Z ,

GL2.GL_TEXTURE_CUBE_MAP_NEGATIVE_Z

};

// ...

// Texturas do Cube Map

textureNames.add("cubemap/right.tga");

textureNames.add("cubemap/left.tga");

textureNames.add("cubemap/up.tga");

textureNames.add("cubemap/down.tga");

textureNames.add("cubemap/backward.tga");

textureNames.add("cubemap/forward.tga");

// ...

// Carregar as texturas do Cubo

gl.glBindTexture(GL2.GL_TEXTURE_CUBE_MAP , textures.get(CubeStartIndex ));

// Parametros das texturas do cube map

gl.glTexParameteri(GL2.GL_TEXTURE_CUBE_MAP , GL2.GL_TEXTURE_MAG_FILTER ,

GL2.GL_LINEAR );

gl.glTexParameteri(GL2.GL_TEXTURE_CUBE_MAP , GL2.GL_TEXTURE_MIN_FILTER ,

GL2.GL_LINEAR );

gl.glTexParameteri(GL2.GL_TEXTURE_CUBE_MAP , GL2.GL_TEXTURE_WRAP_S , GL2.GL_REPEAT );

gl.glTexParameteri(GL2.GL_TEXTURE_CUBE_MAP , GL2.GL_TEXTURE_WRAP_T , GL2.GL_REPEAT );

gl.glTexParameteri(GL2.GL_TEXTURE_CUBE_MAP , GL2.GL_TEXTURE_WRAP_R , GL2.GL_REPEAT );

// Restantes texturas preenchem o cubo

for (int i = CubeStartIndex; i < textureNames.size (); i++) {

// Carregar e Ler a imagem para a nossa textura

TGAImage img = loadTexture(textureNames.get(i));

ByteBuffer bb = img.getData ();

gl.glTexImage2D(CubeDirection[i - CubeStartIndex], 0, GL2.GL_RGBA ,

img.getWidth(), img.getHeight(), 0, img.getGLFormat (),

GL2.GL_UNSIGNED_BYTE , bb);

}

97

Page 99: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

O valor utilizado no primeiro argumento das funcoes relacionadas com as texturas passa agora a serGL TEXTURE CUBE MAP. O mesmo valor e utilizado para activar o cube mapping :

gl.glEnable(GL2.GL_TEXTURE_CUBE_MAP );

No caso de GL TEXTURE CUBE MAP e GL TEXTURE 2D estarem activos simultaneamente, o cube map prevalece.De notar que a utilizacao do glTexParameter no cube map afecta as 6 texturas de uma so vez. Para todos osefeitos, os cube maps sao tratados como texturas 3D, com coordenadas s, t e r.

9.5.2 Utilizacao dos Cube Maps

A utilizacao mais comum para o cube map e a reflexao do ambiente. No exemplo CubeMap.java, a cena ecapturada mudando o ponto de vista 6 vezes utilizando um field of view de 90o.

Para conseguir o efeito de reflexao com a composicao das seis imagens, utilizamos:

gl.glTexGeni(GL2.GL_S , GL2.GL_TEXTURE_GEN_MODE , GL2.GL_REFLECTION_MAP );

gl.glTexGeni(GL2.GL_T , GL2.GL_TEXTURE_GEN_MODE , GL2.GL_REFLECTION_MAP );

gl.glTexGeni(GL2.GL_R , GL2.GL_TEXTURE_GEN_MODE , GL2.GL_REFLECTION_MAP );

Ao desenhar a nossa geometria (no exemplo um torus e uma sphere), desactivamos temporariamenteo GL TEXTURE 2D e activamos o GL TEXTURE CUBE MAP, activamos a geracao das coordenadas das texturas edesenhamos a geometria normalmente. Seguidamente restauramos o estado anterior reactivando o GL TEXTURE 2D:

// Desactivar temporariamente TEXTURE_2D

gl.glDisable(GL2.GL_TEXTURE_2D );

// Activar o Cube Map

gl.glEnable(GL2.GL_TEXTURE_CUBE_MAP );

gl.glBindTexture(GL2.GL_TEXTURE_CUBE_MAP , textures.get(CubeStartIndex ));

gl.glEnable(GL2.GL_TEXTURE_GEN_S );

gl.glEnable(GL2.GL_TEXTURE_GEN_T );

gl.glEnable(GL2.GL_TEXTURE_GEN_R );

// Desenhar a Geometria que reflecte o cube map

gl.glTranslatef (0, .5f, -.3f);

glut.glutSolidSphere (.15, 61, 37);

gl.glRotatef ((float) Math.toDegrees(torusRot), 0, 1f, 0);

glut.glutSolidTorus (.1f, .3f, 61, 37);

// Colocar tudo como estava

gl.glDisable(GL2.GL_TEXTURE_GEN_S );

gl.glDisable(GL2.GL_TEXTURE_GEN_T );

gl.glDisable(GL2.GL_TEXTURE_GEN_R );

gl.glDisable(GL2.GL_TEXTURE_CUBE_MAP );

gl.glEnable(GL2.GL_TEXTURE_2D );

O output do programa CubeMap.java pode ser analisado na Figura 9.8.

98

Page 100: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Figura 9.8: CubeMap.java

99

Page 101: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Capıtulo 10

Curvas e Superfıcies

10.1 Superfıcies Incorporadas no OpenGL

Disponıveis na biblioteca GLU1, estao disponıveis um conjunto de funcoes que renderizam superfıcies quadricas2.Sao suportados tres tipos de superfıcies quadricas - esferas, cilindros e discos. Para desenhar um cone, porexemplo, podemos utilizar um cilindro, tendo um dos lados raio=0. Os discos permitem especificar um buracono centro.

A Figura 10.1 mostra algumas formas conseguidas com recurso a estas superfıcies.

Figura 10.1: Formas Quadricas

Para conseguir formas mais complexas, podemos utilizar composicoes contendo as varias superfıcies quadricasdo OpenGL. Como por exemeplo, os eixos unitarios 3D (Figura 10.2), que sao construıdos com a ajuda de 1 esfera,3 cilindros e 3 cones.

Figura 10.2: Eixos unitarios (x, y, z) desenhados com quadricas

1OpenGL Utility Library2Conjunto dos pontos do espaco tridimensional cujas coordenadas formam um polinomio de segundo grau, com um maximo tres

variaveis → equacao cartesiana da superfıcie

100

Page 102: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Os eixos 3D servem de auxılio ao posicionamento e a visualizacao no sistema de coordenadas de um modogeral. Para desenhar os eixos pode ser utilizada a funcao GlUtil.drawUnitAxes() fornecida na biblioteca deapoio a cadeira de Computacao grafica.

10.1.1 Configuracao de Superfıcies Quadricas

O desenho de superfıcies quadricas fornece alguma flexibilidade no que respeita a normais, coordenadas detexturas e outros parametros. No entanto, a colocacao de todos estes parametros numa unica funcao tornariaa sua utilizacao pouco pratica. Em vez disso, e utilizada uma abordagem orientada a objectos. Um objectoquadrico e criado e os parametros de renderizacao sao definidos com um conjunto de funcoes, como mostra oexemplo:

GLU glu = new GLU ();

// Criar o objecto para a superficie quadrica

GLUquadric quad = glu.gluNewQuadric ();

// Configurar parametros

// Desenhar as superficies

// Apagar o objecto

glu.gluDeleteQuadric(quad);

A funcao GLU.gluNewQuadric() retorna um objecto do tipo GLUquadric sobre o qual vamos alterar aspreferencias. Depois de o objecto ser desenhado, podemos libertar o objecto anteriormente criado utilizando afuncao GLU.gluDeleteQuadric().

Existem quatro funcoes para alterar a forma com os quadrics sao desenhados. A primeira funcao e:

GLU.gluQuadricDrawStyle(GLUquadric quad , int drawStyle );

O primeiro parametro da funcao e o objecto criado previamente. O segundo parametro toma o valor de umadas constantes descritas na Tabela 10.1.

Constante DescricaoGLU.GLU FILL Quadrics desenhados como objectos solidosGLU.GLU LINE Quadrics desenhados como wireframesGLU.GLU POINT Quadrics desenhados como pontosGLU.GLU SILHOUETTE Parecido com o wireframe, mas faces adjacentes

dos polıgonos nao sao desenhadas

Tabela 10.1: Estilos de Desenho dos Quadrics

A funcao seguinte permite definir a forma como as normais sao criadas para a geometria:

GLU.gluQuadricNormals(GLUquadric quad , int normals );

Os valores possıveis para o parametro normals sao:

• GLU NONE - superfıcie desenhadas sem normais

• GLU SMOOTH - as normais sao calculadas para cada vertice, dando uma aparencia suave a superfıcie

• GLU FLAT - as normais sao calculadas com base no conjunto dos vertices de cada polıgono (triangulo)

A orientacao das normais pode ser especificada com:

GLU.gluQuadricOrientation(GLUquadric quad , int orientation );

Neste caso, o parametro orientation, pode tomar um dos valores GLU OUTSIDE ou GLU INSIDE. Por omissao,os quadrics sao desenhados com a face para fora (CCW).

Esta funcao e util para o caso de querermos alterar a face sobre a qual a luz incide, por exemplo, no interiorde uma esfera especificarıamos GLU INSIDE.

A ultima funcao permite activar a geracao de coordenadas para a superfıcie:

GLU.gluQuadricTexture(GLUquadric quad , boolean texture );

Neste caso quanto texture e true, e activada a geracao, caso contrario e desactivada. As esferas e cilindrossao “embrulhados” na textura, como se a textura os envolvesse. No caso dos discos, o centro da textura coinciecomo centro do disco e as bordas da textura coincidem com as bordas do disco.

101

Page 103: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

10.1.2 Desenho de Superfıcies Quadricas

Depois de um objecto ter sido configurado de forma satisfatoria, pode ser desenhado com uma unica funcao. Nocaso da esfera, utilizamos:

GLU.gluSphere(GLUQuadric quad , double radius , int slices , int stacks );

O argumento quad representa o nosso objecto GLUquadric previamente criado. O argumento radius defineo raio da esfera. A esfera e desenhada utilizando um conjunto de triangulos1 dispostos numa stack (pilha) desdeo fundo ate ao topo. O numero de elementos da pilha e definido no parametro stacks. O parametro slices,define o numero de triangulos (ou quads) utilizados para desenhar a volta da esfera (Figura 10.3).

Os valores sao semelhantes, conceptualmente, a latitude e longitude do globo terrestre.

Figura 10.3: Stacks e Slices

A esfera e desenhada com o centro na origem das coordenadas e com o eixo-z positivo a “sair” do topo daesfera.

Figura 10.4: Esfera desenhada com quadrics

O resultado da Figura 10.4 pode ser obtido com o codigo:

GlUtil.drawUnitAxes ();

GLUquadric quad = glu.gluNewQuadric ();

glu.gluQuadricDrawStyle(quad , GLU.GLU_LINE );

glu.gluSphere(quad , .75, 16, 16);

glu.gluDeleteQuadric(quad);

O cilindro e desenhado de forma semelhante a esfera. Um conjunto de stacks sao desenhadas ao longo doeixo-z positivo. A funcao para desenhar o cilindro e:

1Ou quads dependendo da implementacao da biblioteca GLU

102

Page 104: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

GLU.gluCylinder(

GLUquadric quad , double base ,

double top , double height ,

int slices , int stacks

);

Com esta funcao especificamos o raio da base e topo (base e top), sendo a base localizada na origem. Oparametro height define o coprimento do cilindro (Figura 10.5).

Figura 10.5: Cilindro desenhado com quadrics

Para desenhar um cone basta colocar o raio do topo (top) a 0 (Figura 10.6).

Figura 10.6: Cone desenhado com quadrics

A ultima superfıcie e o disco. Os discos sao desenhados com recurso a loops de trinangulos (ou quads)dispostos por varios slices. A funcao utilizada para desenhar um disco e:

gluDisk(

GLUquadric quad , double inner ,

double outer ,

int slices , int loops

);

Para desenhar o disco especificamos um raio interno (inner) e um raio exterior (outer) (Figura 10.7). Paraconseguir um disco solido, especificamos inner=0. Com um valor de inner diferente de 0 obtemos um disco comum orificio no meio.

103

Page 105: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

(a) inner=0 (b) inner=0.25

Figura 10.7: Disco desenhado com quadrics

O disco e desenhado no plano xy.A composicao de diferentes quadrics permite a criacao de objectos, tal como o exemplo Snowman.java da

Figura 10.8 (ver Apendice C.6).

Figura 10.8: Snowman.java

10.2 Curvas de Bezier e Superfıcies

Os quadrics fornecem um meio de desenhar superfıcies facilmente modeladas com equacoes algebricas. Noentanto, para desenhar superfıcies mais complexas, tais como curvas ou superfıcies nao lineares, onde nao existeuma especificacao matematica inicial, a tarefa nao e trivial.

Pierre Bezies, um designer da industria automovel, reconheceu esta dificuldade e criou uma forma de desenharcurvas com recurso a um conjunto de pontos de controlo (control points). Para alem da facilidade narepresentacao das curvas, os pontos de controlo representam uma forma interactiva de mudar a forma da curvaou superfıcie.

104

Page 106: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

10.2.1 Representacao Parametrica

Antes de passar ao desenho de curvas, convem estabelecer algum vocabulario e relembrar alguns conceitosmatematicos.

Se estivermos a pensar em linha recta, a representacao no plano-xy pode ser feita com recurso a equacao:

y = m · x+ b

O valor m representa a inclinacao da recta, enquanto que o valor b define a coordenada y onde a recta secruza com o eixo-y.

Outra forma de representar uma curva (ou recta), consiste na parametrizacao das suas coordenadas emfuncao de uma outra variavel que nao tem necessariamente a ver com o sistema de coordenadas. Por exemplo,podemos especificar a forma como as coordenadas variam, ao longo do tempo (t). Assim para cada coordenadateremos uma funcao que varia com o tempo:

x = f(t)

y = g(t)

z = h(t)

No OpenGL, as curvas sao definidas utilizando uma equacao parametrica. A curva e definida por um parametrou e pelo conjunto dos seus valores no domınio da curva. Para a definicao de superfıcies utilizamos um valoradicional v (Figura 10.9).

E importante reter que os valores u e v nao representam coordenadas reais da curva, sao antes valores deparametrizacao da mesma. Desta forma, uma curva sera definida com base nos seus domınios u e v1.

Figura 10.9: Representacao Parametrica de Curvas e Superfıcies

10.2.2 Pontos de Control (control points)

Uma curva pode ser representada por um conjunto de pontos de controlo que determinam o comportamento dacurva. O primeiro e ultimo pontos da curva pertencem as coordenadas da curva, no entanto, os restantes pontosestao fora da curva e representam uma especie de “pontos magneticos” que atraem a curva no seu percurso(Figura 10.10).

Figura 10.10: Pontos de Controlo

1Sendo um domınio, o conjunto dos valores possıveis para um parametro na curva em questao

105

Page 107: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

A curva da Figura 10.10b e uma curva quadratica (2 pontos de controlo) e a curva da Figura 10.10c e umacurva cubica (3 pontos de controlo). Estas ultimas sao as mais utilizadas.

10.2.3 Continuidade

Quando duas curvas lado-a-lado partilham um ponto (breakpoint), formam uma seccao curva (Figura 10.11). Aforma como as curvas se encontram define a continuidade da seccao. As categorias de continuidade sao:

• none - Quando as curvas nao se encontram de todo

• positional (C0) - As curvas encontram-se num ponto

• tangetial (C1) - As curvas partilham a mesma tangente no breakpoint

• curvature (C2) - Para alem de partilharem a mesma tangente, a aproximacao a tangente e semelhante nasduas curvas

Figura 10.11: Continuidade de Curvas

Os tipos de continuidade mais utilizados, quando estamos a juntar um grande conjunto de curvas, sao os tipotangential e curvature.

10.2.4 Evaluators

O OpenGL fornece uma forma simples de desenhar curvas e superfıcies de Bezier. Para tal, especificamos ospontos de controlo e o domınio dos valores parametrics u e v. Finalmente ao invocar o evaluator apropriado, oOpenGL gera os pontos que definem a curva ou superfıcie.

Uma curva 2D

O programa Bezier2D.java (ver Apendice C.7), mostra como pode ser desenhada uma curva de Bezier 2D.A melhor forma de explicar o programa passa pela explicacao de cada bloco de codigo.Comecamos por definir uma perspectiva ortogonal entre +10 e -10, a fim de facilitar a visualizacao:

gl.glMatrixMode(GL2.GL_PROJECTION );

gl.glLoadIdentity ();

glu.gluOrtho2D (-10f, 10f, -10f, 10f);

Criamos os pontos de controlo com recurso a classe GLVectorList:

// Definir Pontos de Controlo

ctrlPoints = new GLVectorList ();

ctrlPoints.add(-4f, 0f, 0f); // Start

ctrlPoints.add(-6f, 4f, 0f); // Control

106

Page 108: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

ctrlPoints.add(6f, -4f, 0f); // Control

ctrlPoints.add(4f, 0f, 0f); // End

Depois de limpar o color buffer, criamos o mapping para a curva utilizando a funcao glMap1f:

gl.glClear(GL2.GL_COLOR_BUFFER_BIT );

float umin = 0f; // Valor minimo do u

float umax = 100f; // Valor maximo do u

gl.glMap1f(

GL2.GL_MAP1_VERTEX_3 , // Tipo de dados gerados

umin , // Valor minimo do u

umax , // Valor maximo do u

3, // Distancia entre pontos

ctrlPoints.size(), // Numero de pontos de controlo

ctrlPoints.toFloatBuffer () // FloatBuffer contendo pontos de controlo

);

O primeiro argumento da funcao glMap1f define o tipo de evaluator a utilizar para gerar os vertices da linha.O segundo e terceiros argumentos definem o valor de u para o ponto inicial da curve e o valor de u para o pontofinal da curva. Os pontos intermedios representam uma posicao na curva1.

O terceiro argumento representa o numero de elementos em cada posicao do array contendo os pontos decontrolo (neste caso um FloatBuffer). Para o programa Bezier2D.java, estamos a utilizar as coordenadas x,y e z, daı o valor ser 3. O quarto argumento define o numero de pontos de controlo que pretendemos utilizar efinalmente o ultimo argumento e o buffer (ou array) contendo os pontos de controlo.

Por uma questao de conveniencia, foi criado o metodo toFloatBuffer() na classe GLVectorList que devolveum FloatBuffer contendo as posicoes x, y e z dos vectores adicionados (via add(x, y, z)).

No passo seguinte activamos o evaluator que utilizamos na funcao glMap1f e desenhamos os vertices geradoscom a ajuda da funcao glEvalCoord:

// Activar o Evaluator

gl.glEnable(GL2.GL_MAP1_VERTEX_3 );

// Desenhar os vertices da curva

gl.glColor3f (0f, 0f, 0f);

gl.glBegin(GL2.GL_LINE_STRIP );

for(float i=umin; i<umax; i++)

gl.glEvalCoord1f(i);

gl.glEnd ();

A fim de facilitar a compreensao dos pontos de controlo, desenhamo-los tambem:

// Desenhar Pontos de Controlo

gl.glPointSize (5.0f);

gl.glColor3f (1f, 0f, 0f);

gl.glBegin(GL2.GL_POINTS );

for(GLVector point : ctrlPoints)

point.draw ();

gl.glEnd ();

O resultado final do nosso programa Bezier2D pode ser visualizado na Figura 10.12.Por uma questao de eficiencia e a fim de tornar o codigo mais compacto, o OpenGL permite-nos desenhar a

curva utilizando apenas as 2 funcoes glMapGrid e glEvalMesh, de forma que o codigo:

gl.glBegin(GL2.GL_LINE_STRIP );

for(float i=umin; i<umax; i++)

gl.glEvalCoord1f(i);

gl.glEnd ();

Seria re-escrito da seguinte forma:

// Mapear uma grelha de 100 pontos com umin=0 e umax=100

gl.glMapGrid1d (100, umin , umax);

// Fazer o evaluate da grelha anterior utilizando linhas (GL_LINE)

gl.glEvalMesh1(GL2.GL_LINE , (int)umin , (int)umax);

1Neste caso, o valor 50 representa o ponto no meio da curva, o 25 a um quarto da curva, etc. . .

107

Page 109: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Figura 10.12: Curva de Bezier 2D

10.2.5 Superfıcies 3D

A forma de criar uma superfıcie de Bezier e muito semelhante a criacao das curvas. Adicionamos apenas oparametro v que corresponde a um segundo domınio. O codigo completo do exemplo seguinte pode ser consultadono Apendice C.8 referente ao programa Bezier3D.java.

A diferenca, a partida, em relacao ao exemplo Bezier2D, e que neste utilizamos 3 conjuntos de 3 pontos decontrolo cada.

Comecamos entao por definir os pontos de controlo, 3 na direccao de u por 3 na direccao de v:

// Definir Pontos de Controlo

ctrlPoints = new GLVectorList ();

// v0

ctrlPoints.add(-4f, 0f, 4f); // Start (u0)

ctrlPoints.add(-2f, 4f, 4f); // Control (u0)

ctrlPoints.add(4f, 0f, 4f); // End (u0)

// v1

ctrlPoints.add(-4f, 0f, 0f); // Start (u1)

ctrlPoints.add(-2f, 4f, 0f); // Control (u1)

ctrlPoints.add(4f, 0f, 0f); // End (u1)

// v2

ctrlPoints.add(-4f, 0f, -4f); // Start (u2)

ctrlPoints.add(-2f, 4f, -4f); // Control (u2)

ctrlPoints.add(4f, 0f, -4f); // End (u2)

Seguidamente geramos o mapa bidmimensional de pontos para a superfıcie, utilizando a funcao glMap2f como primeiro argumento tendo o valor GL2.GL MAP2 VERTEX 3, em vez da funcao glMap1f, da seguinte forma:

float umin = 0f; // Valor minimo do u

float umax = 10f; // Valor maximo do u

float vmin = 0f; // Valor minimo do v

float vmax = 10f; // Valor maximo do v

gl.glMap2f(

GL2.GL_MAP2_VERTEX_3 , // Tipo de dados gerados

umin , // Valor minimo do u

umax , // Valor maximo do u

108

Page 110: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

3, // Distancia entre pontos (dominio u)

3, // Numero de pontos de controlo (dominio u)

vmin , // Valor minimo do v

vmax , // Valor maximo do v

9, // Distancia entre pontos (dominio v)

3, // Numero de pontos de controlo (dominio v)

ctrlPoints.toFloatBuffer () // FloatBuffer contendo pontos de controlo

);

O segundo e terceiro argumentos definem os valores mınimo e maximo no domınio u. O quarto e quintoargumentos definem, respectivamente, o intervalo entre os pontos do domınio u no buffer de dados e o numerode pontos de controlo. O intervalo de dados para u e de 3 pela mesma razao do exemplo anterior. O numero depontos de controlo ao longo de u e de 3.

O sexto e setimo argumentos representam o valor mınimo e maximo do domınio v. O oitavo e nono argumentosrepresentam, respectivamente, o intervalo entre os pontos no domınio v e o numero de pontos de controlo. Ointervalo no caso do domınio v e de 9, uma vez que para cada iteracao de v existem 3 pontos em u (3× 3 = 9).O numero de pontos de controlo ao longo de v e igualmente de 3.

O ultimo argumento e o FloatBuffer contendo os pontos de controlo.Finalmente podemos desenhar a nossa superfıcie de forma semelhante a utilizada para o exemplo anterior:

// Desenhar os vertices da superficie

gl.glColor3f (0f, 0f, 0f);

// Mapear uma grelha de 10× 10 pontos com u entre umin e umax e v entre vmin e vmax

gl.glMapGrid2d (10, umin , umax , 10, vmin , vmax);

// Fazer o evaluate da grelha anterior utilizando linhas

gl.glEvalMesh2(GL2.GL_LINE , (int)umin , (int)umax , (int)vmin , (int) vmax);

O resultado final do programa Bezier3D pode ser analisado na Figura 10.13.

Figura 10.13: Superfıcie 3D de Bezier

10.2.6 Luzes e Vectores Normais

A fim de utilizar luzes com as nossas superfıcies basta-nos substituir o codigo:

gl.glEvalMesh2(GL2.GL_LINE , (int)umin , (int)umax , (int)vmin , (int) vmax);

Pelo codigo:

gl.glEvalMesh2(GL2.GL_FILL , (int)umin , (int)umax , (int)vmin , (int) vmax);

gl.glEnable(GL2.GL_AUTO_NORMAL );

O que produz o resultado da Figura 10.14, que pode ser conseguido correndo o programa BezierLighting.java(ver Apendice C.9).

109

Page 111: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Figura 10.14: Superfıcie de Bezier com Lighting

110

Page 112: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Capıtulo 11

Conceitos Avancados

11.1 Display Lists

Os comandos (funcoes) especificados no codigo do nosso programa em OpenGL, nao sao inconsequentes, saonormalmente compilados para um conjunto de instrucoes que sao colocadas num buffer. Quando apropriado, obuffer de comandos e enviado para o hardware.

Para cenarios geometricamente complexos, este processo pode ser reptido milhares de vezes, antes que umasimples imagem seja desenhada no ecra. Em varias situacoes, a geometria repete-se de frame para frame, o querepresenta um overhead desnecessario de processamento.

O OpenGL oferece a possibilidade de agregar um conjunto de comandos numa lista pre-processada. Esta listade comandos pode, mais tarde ser copiada para o command buffer, poupando o tempo da chamada e compilacaodos comandos.

Esta lista de comandos pre-processados e chamada de display list. O codigo necessario a criacao de displaylists podera ser:

int name = ...; // Identificador da lista

gl.glNewList(name , GL2.GL_COMPILE );

// Comandos OpenGL

gl.glEndList ();

A funcao glNewList cria a display list identificada pelo valor de name, armazenando os comandos ate que eencontrada a funcao glEndList. O parametro GL2.GL COMPILE, diz ao OpenGL para compilar esta lista. Esteprocesso e normalmente levado a cabo na inicializacao do nosso programa (funcao init()) e mais tarde a lista einvocada durante o processo de renderizacao.

O parametro name podera tomar qualquer valor inteiro (unsigned int). No caso de ser especificado duasvezes o mesmo valor ao invocar glNewList, a lista actualmente associada ao identificador, e substituıda pelanova especificacao.

A fim de evitar a substituicao acidental de uma lista previamente criada, podemos pedir ao OpenGL que gereum conjunto de identificadores (um para cada lista).

int NumLists = 3;

// ...

int first = gl.glGenLists(NumLists );

O codigo em cima gera os identificadors para 3 display lists consecutivas, onde first sera o valor do primeiroidentificador. Para especificarmos a lista de comandos para as listas recem-criadas, podemos escrever:

int first = gl.glGenLists(NumLists );

int second = first + 1;

int third = first + 2;

gl.glNewList(first , GL2.GL_COMPILE );

// Desenhar Geometria (1)

gl.glEndList ();

gl.glNewList(second , GL2.GL_COMPILE );

// Desenhar Geometria (2)

gl.glEndList ();

gl.glNewList(third , GL2.GL_COMPILE );

111

Page 113: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

// Desenhar Geometria (3)

gl.glEndList ();

Os comandos da lista, ou listas criadas durante o processo de inicializacao podem ser executados durante oprocesso de rendering (funcao display()), utilizando a funcao:

glCallLists(int listId );

Sendo o argumento listId o valor do identificador da lista.Quando as display lists nao estiverem a ser usadas, podemos libertar os recursos reservados para elas utilizando

a funcao glDeleteLists:

gl.glDeleteLists(first , NumLists );

Onde o primeiro argumento e o primeiro identificador da lista e o segundo argumento e o numero de listas aapagar. Este procedimento e normalmente levado a cabo no encerramento do programa (ex.: metodo dispose()).

11.1.1 Pros e Contras

A utilizacao de display lists representam, em hardwre da maior parte dos fabricantes, um aumento significativono desempenho. O seu uso e ideal para acelerar mudancas de estado (p.ex.: activar/desactivar lighting, etc. . . ).

O carregamento de texturas e a leitura do color buffer (ex.: glReadPixel e glTexImage2D) nao fazem muitosentido dentro de uma lista. Faz antes sentido a criacao de texture objects e a sua invocacao (com glBindTexture)dentro da lista.

Dentro de uma display list podemos ainda invocar a execucao de uma outra, nao sendo possıvel, no entanto,chamadas a (glNewList/glEndList) dentro de uma display list.

112

Page 114: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Apendice A

Exemplos

A.1 Exemplo Simples

public class OpenGL0 extends GLFrame {

public OpenGL0 () {

setSize (300, 300);

}

@Override

public void display(GLAutoDrawable drawable) {

}

@Override

public void init(GLAutoDrawable drawable) {

GLCanvas canvas = getCanvas ();

GLCapabilities cap = canvas.getChosenGLCapabilities ();

cap.setDoubleBuffered(false);

GL2 gl = drawable.getGL().getGL2 ();

gl.glClearColor (0.0f, 0.0f, 1.0f, 1.0f);

gl.glClear(GL.GL_COLOR_BUFFER_BIT);

gl.glFlush ();

}

public static void main(String [] args) {

new OpenGL0 ().setVisible(true);

}

}

113

Page 115: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Apendice B

Tabelas

B.1 Formato de Imagem (pixmap)

Tipo DescricaoGL RGB Cores representadas por red, green e blueGL RGBA Cores representadas por red, green, blue e alphaGL BGR / GL BGR EXT Cores representadas por blue, green e redGL BGRA / GL BGRA EXT Cores representadas por blue, green, red e alphaGL RED Cada pixel contem um unico componente de redGL GREEN Cada pixel contem um unico componente de greenGL BLUE Cada pixel contem um unico componente de blueGL ALPHA Cada pixel contem um unico componente de alphaGL LUMINANCE Cada pixel contem um unico componente de intensidade

(luminance)GL LUMINANCE ALPHA Cada pixel contem um componente de intensidade se-

guido por um componente de alphaGL STENCIL INDEX Cada pixel contem um unico valor de stencilGL DEPTH COMPONENT Cada pixel contem um unico valor de profundidade

(depth)

Tabela B.1: Formato de Imagem (pixmap)

114

Page 116: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

B.2 Tipo de Dados (pixmap)

Tipo DescricaoGL UNSIGNED BYTE Cada componente e um unsigned integer de 8-bitGL BYTE integer de 8-bitGL BITMAP Apenas bits, sem informacao de cor (equivaliente ao

glBitmap)GL UNSIGNED SHORT unsigned integer de 16-bitGL SHORT signed integer de 16-bitGL UNSIGNED INT unsigned integer de 32-bitGL INT signed integer de 32-bitGL FLOAT single precision floatGL UNSIGNED BYTE 3 2 2 Packed RGB valuesGL UNSIGNED BYTE 2 3 3 REV Packed RGB valuesGL UNSIGNED SHORT 5 6 5 Packed RGB valuesGL UNSIGNED SHORT 5 6 5 REV Packed RGB valuesGL UNSIGNED SHORT 4 4 4 4 Packed RGBA valuesGL UNSIGNED SHORT 4 4 4 4 REV Packed RGBA valuesGL UNSIGNED SHORT 5 5 5 1 Packed RGBA valuesGL UNSIGNED SHORT 1 5 5 5 REV Packed RGBA valuesGL UNSIGNED INT 8 8 8 8 Packed RGBA valuesGL UNSIGNED INT 8 8 8 8 REV Packed RGBA valuesGL UNSIGNED INT 10 10 10 2 Packed RGBA valuesGL UNSIGNED INT 2 10 10 10 REV Packed RGBA values

Tabela B.2: Tipo de Dados (pixmap)

115

Page 117: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

Apendice C

Codigo Fonte

C.1 Example0.java

package pt.ipb.esact.cg.examples;

import java.awt.BorderLayout;

import java.util.ArrayList;

import java.util.List;

import javax.media.opengl.GL2;

import javax.media.opengl.GLAutoDrawable;

import javax.media.opengl.GLEventListener;

import javax.media.opengl.awt.GLCanvas;

import javax.media.opengl.glu.GLU;

import javax.swing.JFrame;

import pt.ipb.esact.cg.gl.CGEngine;

import pt.ipb.esact.cg.gl.GLVector;

import pt.ipb.esact.cg.gl.tools.GlUtil;

import com.jogamp.opengl.util.FPSAnimator;

import com.jogamp.opengl.util.gl2.GLUT;

@SuppressWarnings("serial")

public class Example0 extends JFrame implements GLEventListener {

private GLU glu = new GLU ();

private GLUT glut = new GLUT ();

private GLCanvas canvas;

private GLVector fLightPos = new GLVector (-100f, 100f, 50f, 1f);

private float fNoLight [] = { 0.0f, 0.0f, 0.0f, 0.0f };

private float fLowLight [] = { 0.25f, 0.25f, 0.25f, 1.0f };

private float fBrightLight [] = { 1.0f, 1.0f, 1.0f, 1.0f };

private static final float FloorSize = 20f;

private static final int NumSpheres = 30;

private List <GLVector > spherePositions = new ArrayList <GLVector >();

public static void main(String [] args) {

new Example0 ();

}

116

Page 118: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

public Example0 () {

super("Modelo OpenGL");

setUndecorated(true);

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE );

setSize (600, 600);

canvas = new GLCanvas ();

add(canvas , BorderLayout.CENTER );

canvas.addGLEventListener(this);

GLVector location = new GLVector (0f, .5f, .5f);

new CGEngine(canvas , location );

setVisible(true);

canvas.requestFocus ();

FPSAnimator animator = new FPSAnimator(canvas , 25);

animator.start ();

}

public void dispose(GLAutoDrawable drawable) {

}

@Override

public void init(GLAutoDrawable drawable) {

GL2 gl = drawable.getGL (). getGL2 ();

// Grayish background

gl.glClearColor(fLowLight [0], fLowLight [1], fLowLight [2], fLowLight [3]);

// Cull backs of polygons

gl.glCullFace(GL2.GL_BACK );

gl.glFrontFace(GL2.GL_CCW );

gl.glEnable(GL2.GL_CULL_FACE );

gl.glEnable(GL2.GL_DEPTH_TEST );

spherePositions = GlUtil.generateRandomPositions(FloorSize , NumSpheres );

setupLight(gl);

}

private void setupLight(GL2 gl) {

// Setup light parameters

gl.glLightModelfv(GL2.GL_LIGHT_MODEL_AMBIENT , fNoLight , 0);

gl.glLightfv(GL2.GL_LIGHT0 , GL2.GL_AMBIENT , fLowLight , 0);

gl.glLightfv(GL2.GL_LIGHT0 , GL2.GL_DIFFUSE , fBrightLight , 0);

gl.glLightfv(GL2.GL_LIGHT0 , GL2.GL_SPECULAR , fBrightLight , 0);

gl.glEnable(GL2.GL_LIGHTING );

gl.glEnable(GL2.GL_LIGHT0 );

// Mostly use material tracking

gl.glEnable(GL2.GL_COLOR_MATERIAL );

gl.glColorMaterial(GL2.GL_FRONT , GL2.GL_AMBIENT_AND_DIFFUSE );

gl.glMateriali(GL2.GL_FRONT , GL2.GL_SHININESS , 128);

}

@Override

public void display(GLAutoDrawable drawable) {

GL2 gl = drawable.getGL (). getGL2 ();

gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT );

gl.glMaterialfv(GL2.GL_FRONT , GL2.GL_SPECULAR , fBrightLight , 0);

117

Page 119: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

gl.glPushMatrix ();

gl.glLightfv(GL2.GL_LIGHT0 , GL2.GL_POSITION , fLightPos.toArray(), 0);

// Desenhar um Torus Verde

gl.glColor3f (0, 1f, 0);

drawWorld(gl);

gl.glColor4f (0.60f, .40f, .10f, .5f);

GlUtil.drawGround(FloorSize , 1f);

gl.glPopMatrix ();

}

private void drawWorld(GL2 gl) {

// Desenhar o Torus

gl.glPushMatrix ();

gl.glTranslatef (0, .5f, 0);

glut.glutSolidTorus (.1f, .2f, 61, 37);

gl.glPopMatrix ();

// Desenhar esferas aleatoriamente

for(GLVector s : spherePositions) {

gl.glPushMatrix ();

gl.glTranslatef(s.x(), s.y(), s.z());

glut.glutSolidSphere(s.w(), 20, 10);

gl.glPopMatrix ();

}

}

@Override

public void reshape(GLAutoDrawable drawable , int x, int y, int width , int height) {

GL2 gl = drawable.getGL (). getGL2 ();

if (height == 0) height = 1;

gl.glViewport (0, 0, canvas.getSize ().width , canvas.getSize (). height );

gl.glMatrixMode(GL2.GL_PROJECTION );

gl.glLoadIdentity ();

float volume = 100f;

float fAspect = (float) width / (float) height;

glu.gluPerspective (100f, fAspect , .001f, volume * 5f);

}

}

C.2 Imaging.java

package pt.ipb.esact.cg.examples;

import java.awt.BorderLayout;

import java.awt.event.KeyAdapter;

import java.awt.event.KeyEvent;

import java.io.IOException;

import java.io.InputStream;

import java.nio.ByteBuffer;

import java.nio.FloatBuffer;

import java.nio.IntBuffer;

import javax.media.opengl.GL2;

import javax.media.opengl.GLAutoDrawable;

import javax.media.opengl.GLEventListener;

import javax.media.opengl.awt.GLCanvas;

import javax.media.opengl.glu.GLU;

import javax.swing.JFrame;

118

Page 120: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

import com.jogamp.opengl.util.FPSAnimator;

import com.jogamp.opengl.util.texture.spi.TGAImage;

@SuppressWarnings("serial")

public class Imaging extends JFrame implements GLEventListener {

private GLU glu = new GLU ();

private GLCanvas canvas;

private ByteBuffer bb;

private TGAImage img;

private RenderMode renderMode = RenderMode.Normal;

static enum RenderMode {

GaussianBlur , Sharpen , Emboss , Invert , Brighten , Normal

}

public static void main(String [] args) {

new Imaging ();

}

public Imaging () {

super("Modelo OpenGL");

setUndecorated(true);

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE );

setSize (512, 512);

canvas = new GLCanvas ();

add(canvas , BorderLayout.CENTER );

canvas.addGLEventListener(this);

canvas.addKeyListener(new KeyAdapter () {

@Override

public void keyReleased(KeyEvent e) {

switch (e.getKeyCode ()) {

case KeyEvent.VK_1: renderMode = RenderMode.Normal; break;

case KeyEvent.VK_2: renderMode = RenderMode.Brighten; break;

case KeyEvent.VK_3: renderMode = RenderMode.Invert; break;

case KeyEvent.VK_4: renderMode = RenderMode.Emboss; break;

case KeyEvent.VK_5: renderMode = RenderMode.Sharpen; break;

case KeyEvent.VK_6: renderMode = RenderMode.GaussianBlur; break;

case KeyEvent.VK_Q: // Sair

setVisible(false);

dispose ();

System.exit (0);

break;

default:

break;

}

}

});

setVisible(true);

canvas.requestFocus ();

FPSAnimator animator = new FPSAnimator(canvas , 25);

animator.start ();

}

public void dispose(GLAutoDrawable drawable) {

}

@Override

119

Page 121: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

public void init(GLAutoDrawable drawable) {

GL2 gl = drawable.getGL (). getGL2 ();

// Grayish background

gl.glClearColor (0f, 0f, 0f, 0f);

try {

InputStream stream = Imaging.class.getResourceAsStream("horse.tga");

img = TGAImage.read(stream );

bb = img.getData ();

stream.close ();

} catch (IOException e) {

e.printStackTrace ();

}

}

@Override

public void display(GLAutoDrawable drawable) {

GL2 gl = drawable.getGL (). getGL2 ();

// Clear the window with current clearing color

gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT );

// Armazena a informacao do viewPort lida com glGet

// Contem: (x, y, width , height)

IntBuffer iViewport = IntBuffer.allocate (4);

// Tabela de cores invertida (3 cores * 256 niveis)

ByteBuffer invertTable = ByteBuffer.allocate (256 * 3);

// Matriz (convolution kernel) para efectuar o sharpen

FloatBuffer mSharpen = FloatBuffer.wrap(new float [] {

0.0f, -1.0f, 0.0f,

-1.0f, 5.0f, -1.0f,

0.0f, -1.0f, 0.0f

});

// Matriz (convolution kernel) para efectuar o emboss

FloatBuffer mEmboss = FloatBuffer.wrap(new float [] {

2.0f, 0.0f, 0.0f,

0.0f, -1.0f, 0.0f,

0.0f, 0.0f, -1.0f

});

// Matriz (convolution kernel) para efectuar gaussian blur

/*

| 1 2 1 |

| 2 4 2 |

| 1 2 1 |

*/

float norm = 16f; // somatorio dos valores da matriz

FloatBuffer mGaussian = FloatBuffer.wrap(new float [] {

1f/norm , 2f/norm , 1f/norm ,

2f/norm , 4f/norm , 2f/norm ,

1f/norm , 2f/norm , 1f/norm

});

// Posicao do raster comeca no canto inferior esquerdo por omissao

gl.glRasterPos2i (0, 0);

// Ler o estado actual do viewport

gl.glGetIntegerv(GL2.GL_VIEWPORT , iViewport );

// Esticar a imagem para ficar do tamanho do viewport

120

Page 122: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

gl.glPixelZoom(

(float) iViewport.get(2) / (float) img.getWidth(),

(float) iViewport.get(3) / (float) img.getHeight ()

);

//

switch(renderMode) {

case Sharpen: // Sharpen

gl.glConvolutionFilter2D(

GL2.GL_CONVOLUTION_2D , GL2.GL_RGB , 3, 3,

GL2.GL_LUMINANCE , GL2.GL_FLOAT , mSharpen

);

gl.glEnable(GL2.GL_CONVOLUTION_2D );

break;

case Emboss: // Emboss

gl.glConvolutionFilter2D(

GL2.GL_CONVOLUTION_2D , GL2.GL_RGB , 3, 3,

GL2.GL_LUMINANCE , GL2.GL_FLOAT , mEmboss );

gl.glEnable(GL2.GL_CONVOLUTION_2D );

break;

case Invert: // Invert

for(int i = 0; i < 255; i++) {

invertTable.put(i * 3 + 0, (byte) (255 - i));

invertTable.put(i * 3 + 1, (byte) (255 - i));

invertTable.put(i * 3 + 2, (byte) (255 - i));

}

gl.glColorTable(

GL2.GL_COLOR_TABLE , GL2.GL_RGB , 256, GL2.GL_RGB ,

GL2.GL_UNSIGNED_BYTE , invertTable

);

gl.glEnable(GL2.GL_COLOR_TABLE );

break;

case Brighten: // Brighten

// Mudar para o matrix mode Color

gl.glMatrixMode(GL2.GL_COLOR );

// Aumentar todas as cores em 50%

gl.glScalef (2f, 2f, 2f);

// Voltar ao ModelView

gl.glMatrixMode(GL2.GL_MODELVIEW );

break;

case GaussianBlur: // Gaussian Blur

gl.glConvolutionFilter2D(

GL2.GL_CONVOLUTION_2D , GL2.GL_RGB , 3, 3,

GL2.GL_LUMINANCE , GL2.GL_FLOAT , mGaussian );

gl.glEnable(GL2.GL_CONVOLUTION_2D );

break;

case Normal: // Normal

default:

break;

}

// Desenhar a Imagem com as alteracoes efectuadas (ou nao)

gl.glDrawPixels(

img.getWidth(), img.getHeight(),

img.getGLFormat (),

GL2.GL_UNSIGNED_BYTE , bb);

121

Page 123: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

// Reverter as (possiveis) transformacoes efectuadas

// na matriz Color

gl.glMatrixMode(GL2.GL_COLOR );

gl.glLoadIdentity ();

// Voltar ao ModelView

gl.glMatrixMode(GL2.GL_MODELVIEW );

// Desactivar as alteracoes

gl.glDisable(GL2.GL_CONVOLUTION_2D );

gl.glDisable(GL2.GL_COLOR_TABLE );

}

@Override

public void reshape(GLAutoDrawable drawable , int x, int y, int width , int height) {

GL2 gl = drawable.getGL (). getGL2 ();

gl.glViewport (0, 0, width , height );

gl.glMatrixMode(GL2.GL_PROJECTION );

gl.glLoadIdentity ();

glu.gluOrtho2D (0, width , 0, height );

gl.glMatrixMode(GL2.GL_MODELVIEW );

gl.glLoadIdentity ();

}

}

C.3 Pyramid.java

package pt.ipb.esact.cg.examples;

import java.awt.BorderLayout;

import java.awt.Container;

import java.io.IOException;

import java.io.InputStream;

import java.nio.ByteBuffer;

import javax.media.opengl.GL2;

import javax.media.opengl.GLAutoDrawable;

import javax.media.opengl.GLEventListener;

import javax.media.opengl.awt.GLCanvas;

import javax.media.opengl.glu.GLU;

import javax.swing.JFrame;

import pt.ipb.esact.cg.gl.CGEngine;

import pt.ipb.esact.cg.gl.GLVector;

import pt.ipb.esact.cg.gl.tools.GlTools;

import pt.ipb.esact.cg.gl.tools.GlUtil;

import com.jogamp.opengl.util.FPSAnimator;

import com.jogamp.opengl.util.texture.spi.TGAImage;

@SuppressWarnings("serial")

public class Pyramid extends JFrame implements GLEventListener {

private GLU glu = new GLU ();

private GLCanvas canvas;

FPSAnimator animator;

122

Page 124: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

private GLVector lightPos = new GLVector (-10f, 5f, 5f, 1f);

private float whiteLight [] = { 0.05f, 0.05f, 0.05f, 1.0f };

private float sourceLight [] = { 0.25f, 0.25f, 0.25f, 1.0f };

private CGEngine e;

private TGAImage img;

private ByteBuffer bb;

private GLVector cTop;

private GLVector cBackLeft;

private GLVector cBackRight;

private GLVector cFrontRight;

private GLVector cFrontLeft;

public static void main(String [] args) {

new Pyramid ();

}

public Pyramid () {

super("Modelo OpenGL");

setUndecorated(true);

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE );

setSize (600, 600);

Container p = getContentPane ();

BorderLayout l = new BorderLayout (5, 5);

p.setLayout(l);

canvas = new GLCanvas ();

p.add(canvas , BorderLayout.CENTER );

canvas.addGLEventListener(this);

GLVector location = new GLVector (1f, 1f, 1f);

e = new CGEngine(canvas , location );

e.camera (). lookAt (0f, 1f, 0f);

setVisible(true);

canvas.requestFocus ();

animator = new FPSAnimator(canvas , 25);

animator.start ();

}

@Override

public void dispose(GLAutoDrawable drawable) {}

@Override

public void init(GLAutoDrawable drawable) {

GL2 gl = drawable.getGL (). getGL2 ();

// Fundo Preto

gl.glClearColor (0f, 0f, 0f, 1f);

gl.glEnable(GL2.GL_CULL_FACE ); // Nao calcular dentro dos objectos

gl.glFrontFace(GL2.GL_CCW ); // Poligonos CCW tem a face para fora

gl.glEnable(GL2.GL_DEPTH_TEST ); // Remocao de Superficies Escondidas

123

Page 125: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

// Activar as Luzes

gl.glEnable(GL2.GL_LIGHTING );

// Configurar e Activar a luz

gl.glLightModelfv(GL2.GL_LIGHT_MODEL_AMBIENT , whiteLight , 0);

gl.glLightfv(GL2.GL_LIGHT0 , GL2.GL_AMBIENT , sourceLight , 0);

gl.glLightfv(GL2.GL_LIGHT0 , GL2.GL_DIFFUSE , sourceLight , 0);

gl.glLightfv(GL2.GL_LIGHT0 , GL2.GL_POSITION , lightPos.toArray(), 0);

gl.glEnable(GL2.GL_LIGHT0 );

// Activar o Color Tracking

gl.glEnable(GL2.GL_COLOR_MATERIAL );

// Propriedades dos materiais obedecem ’a luz

gl.glColorMaterial(GL2.GL_FRONT , GL2.GL_AMBIENT_AND_DIFFUSE );

// Carregar e Ler a imagem para a nossa textura

try {

InputStream stream = Pyramid.class.getResourceAsStream("stone.tga");

img = TGAImage.read(stream );

bb = img.getData ();

stream.close ();

} catch (IOException e) {

e.printStackTrace ();

}

gl.glTexImage2D(GL2.GL_TEXTURE_2D , 0, GL2.GL_RGBA ,

img.getWidth(), img.getHeight(),

0, img.getGLFormat (), GL2.GL_UNSIGNED_BYTE , bb);

// Parametros da textura (ignorar para ja)

gl.glTexParameteri(GL2.GL_TEXTURE_2D ,

GL2.GL_TEXTURE_MIN_FILTER , GL2.GL_LINEAR );

gl. glTexParameteri(GL2.GL_TEXTURE_2D ,

GL2.GL_TEXTURE_MAG_FILTER , GL2.GL_LINEAR );

gl.glTexParameteri(GL2.GL_TEXTURE_2D ,

GL2.GL_TEXTURE_WRAP_S , GL2.GL_CLAMP_TO_EDGE );

gl.glTexParameteri(GL2.GL_TEXTURE_2D ,

GL2.GL_TEXTURE_WRAP_T , GL2.GL_CLAMP_TO_EDGE );

// Configuracao do Texture Environment

gl.glTexEnvi(GL2.GL_TEXTURE_ENV ,

GL2.GL_TEXTURE_ENV_MODE , GL2.GL_MODULATE );

// Activar as texturas

gl.glEnable(GL2.GL_TEXTURE_2D );

// Cantos da Piramide

cTop = new GLVector (0.0f, .80f, 0.0f);

cBackLeft = new GLVector (-0.5f, 0.0f, -.50f);

cBackRight = new GLVector (0.5f, 0.0f, -0.50f);

cFrontRight = new GLVector (0.5f, 0.0f, 0.5f);

cFrontLeft = new GLVector (-0.5f, 0.0f, 0.5f);

}

private float yRot = 0f;

@Override

public void display(GLAutoDrawable drawable) {

GL2 gl = drawable.getGL (). getGL2 ();

yRot += .1f;

if(yRot >= GlTools.GL_PI * 2f)

yRot = 0;

124

Page 126: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

GLVector vNormal;

// Limpar a cor de Fundo

gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT );

gl.glColor3f (.2f, .2f, .2f);

gl.glDisable(GL2.GL_TEXTURE_2D );

GlUtil.drawGround (20f, 1f);

gl.glEnable(GL2.GL_TEXTURE_2D );

gl.glPushMatrix ();

// Levantar um pouco do chao

gl.glTranslatef (0f, .5f, 0f);

gl.glRotatef ((float) Math.toDegrees(yRot), 0, 1f, 0);

// Desenhar a Piramide

gl.glColor3f (1f, 1f, 1f);

gl.glBegin(GL2.GL_TRIANGLES );

// Seccao do Fundo (2 triangulos)

gl.glNormal3f (0f, -1f, 0f); // Virada para baixo

// Bottom 0

gl.glTexCoord2f (1f, 1f);

cBackRight.draw ();

gl.glTexCoord2f (0f, 0f);

cFrontLeft.draw ();

gl.glTexCoord2f (0f, 1f);

cBackLeft.draw ();

// Bottom 1

gl.glTexCoord2f (1f, 1f);

cBackRight.draw ();

gl.glTexCoord2f (1f, 0f);

cFrontRight.draw ();

gl.glTexCoord2f (0f, 0f);

cFrontLeft.draw ();

// Face da Frente

vNormal = GlTools.getNormalVector(cTop , cFrontLeft , cFrontRight );

gl.glNormal3fv(vNormal.toArray(), 0);

gl.glTexCoord2f (.5f, 1f);

cTop.draw ();

gl.glTexCoord2f (0f, 0f);

cFrontLeft.draw ();

gl.glTexCoord2f (1f, 0f);

cFrontRight.draw ();

// Face da Esquerda

vNormal = GlTools.getNormalVector(cTop , cBackLeft , cFrontLeft );

gl.glNormal3fv(vNormal.toArray(), 0);

gl.glTexCoord2f (.5f, 1f);

cTop.draw ();

gl.glTexCoord2f (0f, 0f);

cBackLeft.draw ();

gl.glTexCoord2f (1f, 0f);

cFrontLeft.draw ();

// Face de Tras

vNormal = GlTools.getNormalVector(cTop , cBackRight , cBackLeft );

gl.glNormal3fv(vNormal.toArray(), 0);

gl.glTexCoord2f (.5f, 1f);

cTop.draw ();

125

Page 127: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

gl.glTexCoord2f (0f, 0f);

cBackRight.draw ();

gl.glTexCoord2f (1f, 0f);

cBackLeft.draw ();

// Face da Direita

vNormal = GlTools.getNormalVector(cTop , cFrontRight , cBackRight );

gl.glNormal3fv(vNormal.toArray(), 0);

gl.glTexCoord2f (.5f, 1f);

cTop.draw ();

gl.glTexCoord2f (0f, 0f);

cFrontRight.draw ();

gl.glTexCoord2f (1f, 0f);

cBackRight.draw ();

gl.glEnd ();

gl.glPopMatrix ();

}

@Override

public void reshape(GLAutoDrawable drawable , int x, int y, int width , int height) {

GL2 gl = drawable.getGL (). getGL2 ();

if (height == 0)

height = 1; // prevnir divisao por 0

// O meu viewport tera o tamanho da janela (width x height)

gl.glViewport (0, 0, canvas.getSize ().width , canvas.getSize (). height );

// Mudar para a matiz de PROJECTION

gl.glMatrixMode(GL2.GL_PROJECTION );

gl.glLoadIdentity ();

float volume = 100f;

float fAspect = (float) width / (float) height;

// Projeccao em Perspectiva

glu.gluPerspective (100f, fAspect , .001f, volume * 5f);

}

}

C.4 TexGen.java

package pt.ipb.esact.cg.examples;

import java.awt.BorderLayout;

import java.awt.Container;

import java.awt.event.KeyEvent;

import java.io.IOException;

import java.io.InputStream;

import java.nio.FloatBuffer;

import java.nio.IntBuffer;

import javax.media.opengl.GL2;

import javax.media.opengl.GLAutoDrawable;

import javax.media.opengl.GLEventListener;

import javax.media.opengl.awt.GLCanvas;

import javax.media.opengl.glu.GLU;

import javax.swing.JFrame;

126

Page 128: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

import pt.ipb.esact.cg.gl.CGEngine;

import pt.ipb.esact.cg.gl.GLKeyboardAdapter;

import pt.ipb.esact.cg.gl.GLVector;

import pt.ipb.esact.cg.gl.tools.GlTools;

import com.jogamp.opengl.util.FPSAnimator;

import com.jogamp.opengl.util.gl2.GLUT;

import com.jogamp.opengl.util.texture.spi.TGAImage;

@SuppressWarnings("serial")

public class TexGen extends JFrame implements GLEventListener {

private GLU glu = new GLU ();

private GLUT glut = new GLUT ();

private GLCanvas canvas;

FPSAnimator animator;

private float bgColor [] = { 0f, 0f, 0f, 0f };

private GLVector location = new GLVector (0f, 0f, 5f);

private GLVector lookAt = new GLVector (0f, 0f, 0f);

private IntBuffer textures = IntBuffer.allocate (2);

private CGEngine e;

// Identificadores das Texturas

public static final int Stripes = 0, Environment = 1;

public static final int ObjectLinear = 0, EyeLinear = 1, SphereMap = 2;

private int renderMode = SphereMap;

private TGAImage environment;

public static void main(String [] args) {

new TexGen ();

}

public TexGen () {

super("TexGen");

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE );

setSize (600, 600);

Container p = getContentPane ();

BorderLayout l = new BorderLayout (5, 5);

p.setLayout(l);

canvas = new GLCanvas ();

canvas.addGLEventListener(this);

p.add(canvas , BorderLayout.CENTER );

e = new CGEngine(canvas , location );

e.camera (). lookAt(lookAt );

setVisible(true);

canvas.requestFocus ();

animator = new FPSAnimator(canvas , 25);

animator.start ();

}

127

Page 129: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

@Override

public void dispose(GLAutoDrawable drawable) {

}

@Override

public void init(GLAutoDrawable drawable) {

GL2 gl = drawable.getGL (). getGL2 ();

gl.glClearColor(bgColor [0], bgColor [1], bgColor [2], bgColor [3]);

// Cull backs of polygons

gl.glFrontFace(GL2.GL_CCW );

gl.glEnable(GL2.GL_CULL_FACE );

gl.glEnable(GL2.GL_DEPTH_TEST );

gl.glEnable(GL2.GL_BACK );

// As texturas substitem o material da geometria

gl.glTexEnvi(GL2.GL_TEXTURE_ENV , GL2.GL_TEXTURE_ENV_MODE , GL2.GL_DECAL );

// 2 Texturas

gl.glGenTextures (2, textures );

/**

* Carregamento da textura stripes

*/

environment = loadTexture("environment.tga");

gl.glBindTexture(GL2.GL_TEXTURE_2D , textures.get(Environment ));

gl.glTexImage2D(GL2.GL_TEXTURE_2D , 0, GL2.GL_RGBA ,

environment.getWidth(), environment.getHeight (),

0, environment.getGLFormat (), GL2.GL_UNSIGNED_BYTE ,

environment.getData ());

gl.glTexParameterf(GL2.GL_TEXTURE_2D ,

GL2.GL_TEXTURE_MIN_FILTER , GL2.GL_LINEAR );

gl.glTexParameterf(GL2.GL_TEXTURE_2D ,

GL2.GL_TEXTURE_MAG_FILTER , GL2.GL_LINEAR );

gl.glTexParameterf(GL2.GL_TEXTURE_2D ,

GL2.GL_TEXTURE_WRAP_S , GL2.GL_REPEAT );

gl.glTexParameterf(GL2.GL_TEXTURE_2D ,

GL2.GL_TEXTURE_WRAP_T , GL2.GL_REPEAT );

/**

* Carregamento da textura de ambiente

*/

TGAImage sriptes = loadTexture("stripes.tga");

gl.glBindTexture(GL2.GL_TEXTURE_2D , textures.get(Stripes ));

gl.glTexImage2D(GL2.GL_TEXTURE_2D , 0, GL2.GL_RGBA ,

sriptes.getWidth(), sriptes.getHeight(),

0, sriptes.getGLFormat (), GL2.GL_UNSIGNED_BYTE ,

sriptes.getData ());

gl.glTexParameterf(GL2.GL_TEXTURE_2D ,

GL2.GL_TEXTURE_MIN_FILTER , GL2.GL_LINEAR );

gl.glTexParameterf(GL2.GL_TEXTURE_2D ,

GL2.GL_TEXTURE_MAG_FILTER , GL2.GL_LINEAR );

gl.glTexParameterf(GL2.GL_TEXTURE_2D ,

GL2.GL_TEXTURE_WRAP_S , GL2.GL_REPEAT );

gl.glTexParameterf(GL2.GL_TEXTURE_2D ,

GL2.GL_TEXTURE_WRAP_T , GL2.GL_REPEAT );

// Activar o Texture Mapping

128

Page 130: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

gl.glEnable(GL2.GL_TEXTURE_2D );

// Activar a Geracao de Coordenadas

gl.glEnable(GL2.GL_TEXTURE_GEN_S );

gl.glEnable(GL2.GL_TEXTURE_GEN_T );

// Por omissao utilizamos SphereMap

gl.glTexGeni(GL2.GL_S , GL2.GL_TEXTURE_GEN_MODE , GL2.GL_SPHERE_MAP );

gl.glTexGeni(GL2.GL_T , GL2.GL_TEXTURE_GEN_MODE , GL2.GL_SPHERE_MAP );

canvas.addKeyListener(new GLKeyboardAdapter(canvas) {

@Override

public void handleKey(GLAutoDrawable drawable , KeyEvent e) {

GL2 gl = drawable.getGL (). getGL2 ();

if(e.getKeyCode () == KeyEvent.VK_1)

setObjectLinear(gl);

if(e.getKeyCode () == KeyEvent.VK_2)

setEyeLinear(gl);

if(e.getKeyCode () == KeyEvent.VK_3)

setSphereMap(gl);

}

});

}

// Mudar para Object Linear Function

protected void setObjectLinear(GL2 gl) {

FloatBuffer zPlane = FloatBuffer.wrap(new float [] { 1f, 0f, 0f, 0f });

gl.glTexGeni(GL2.GL_S , GL2.GL_TEXTURE_GEN_MODE ,

GL2.GL_OBJECT_LINEAR );

gl.glTexGeni(GL2.GL_T , GL2.GL_TEXTURE_GEN_MODE ,

GL2.GL_OBJECT_LINEAR );

gl.glTexGenfv(GL2.GL_S , GL2.GL_OBJECT_PLANE , zPlane );

gl.glTexGenfv(GL2.GL_T , GL2.GL_OBJECT_PLANE , zPlane );

renderMode = ObjectLinear;

}

// Mudar para Eye Linear Function

protected void setEyeLinear(GL2 gl) {

FloatBuffer zPlane = FloatBuffer.wrap(new float [] {0f, 0f, 1f, 0f});

gl.glTexGeni(GL2.GL_S , GL2.GL_TEXTURE_GEN_MODE ,

GL2.GL_EYE_LINEAR );

gl.glTexGeni(GL2.GL_T , GL2.GL_TEXTURE_GEN_MODE ,

GL2.GL_EYE_LINEAR );

gl.glTexGenfv(GL2.GL_S , GL2.GL_EYE_PLANE , zPlane );

gl.glTexGenfv(GL2.GL_T , GL2.GL_EYE_PLANE , zPlane );

renderMode = EyeLinear;

}

protected void setSphereMap(GL2 gl) {

gl.glTexGeni(GL2.GL_S , GL2.GL_TEXTURE_GEN_MODE , GL2.GL_SPHERE_MAP );

gl.glTexGeni(GL2.GL_T , GL2.GL_TEXTURE_GEN_MODE , GL2.GL_SPHERE_MAP );

renderMode = SphereMap;

}

private TGAImage loadTexture(String name) {

TGAImage img = null;

try {

InputStream stream = Tunnel.class.getResourceAsStream(name);

img = TGAImage.read(stream );

stream.close ();

} catch (IOException e) {

e.printStackTrace ();

System.exit (0);

129

Page 131: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

}

return img;

}

@Override

public void display(GLAutoDrawable drawable) {

GL2 gl = drawable.getGL (). getGL2 ();

// Clear the window with current clearing color

gl.glClear(GL2.GL_COLOR_BUFFER_BIT );

// Desnhar a imagem de fundo (desactivando as texturas)

gl.glDisable(GL2.GL_TEXTURE_2D );

gl.glPixelZoom(

(float) drawable.getWidth () / (float) environment.getWidth(),

(float) drawable.getHeight () / (float) environment.getHeight ()

);

gl.glDrawPixels(environment.getWidth(), environment.getHeight (),

environment.getGLFormat (), GL2.GL_UNSIGNED_BYTE ,

environment.getData ());

gl.glEnable(GL2.GL_TEXTURE_2D );

gl.glClear(GL2.GL_DEPTH_BUFFER_BIT );

// May need to switch to stripe texture

if(renderMode == SphereMap)

gl.glBindTexture(GL2.GL_TEXTURE_2D , textures.get(Environment ));

else

gl.glBindTexture(GL2.GL_TEXTURE_2D , textures.get(Stripes ));

// Turn texgen and depth writing back on

gl.glEnable(GL2.GL_TEXTURE_GEN_S );

gl.glEnable(GL2.GL_TEXTURE_GEN_T );

// Save the matrix state and do the rotations

gl.glPushMatrix ();

gl.glRotatef (45f, 0f, 1f, 0f);

gl.glTranslatef (-1.5f, 0f, 0f);

// Draw the tours

GlTools.gltDrawTorus (1f, 0.4f, 61, 37);

// Restore the matrix state

gl.glPopMatrix ();

// Desenhar uma amostra da textura actual

gl.glPushMatrix ();

gl.glDisable(GL2.GL_TEXTURE_GEN_S );

gl.glDisable(GL2.GL_TEXTURE_GEN_T );

gl.glRotatef (-45f, 0f, 1f, 0f);

gl.glTranslatef (1.5f, 0f, 0f);

float quadSize = 1.2f;

gl.glBegin(GL2.GL_QUADS );

gl.glTexCoord2f (0f, 0f);

gl.glVertex2f(-quadSize , -quadSize );

gl.glTexCoord2f (1f, 0f);

gl.glVertex2f(quadSize , -quadSize );

gl.glTexCoord2f (1f, 1f);

gl.glVertex2f(quadSize , quadSize );

130

Page 132: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

gl.glTexCoord2f (0f, 1f);

gl.glVertex2f(-quadSize , quadSize );

gl.glEnd ();

gl.glPopMatrix ();

}

@Override

public void reshape(GLAutoDrawable drawable , int x, int y, int width , int height) {

GL2 gl = drawable.getGL (). getGL2 ();

if (height == 0)

height = 1; // prevnir divisao por 0

gl.glViewport (0, 0, canvas.getSize ().width , canvas.getSize (). height );

gl.glMatrixMode(GL2.GL_PROJECTION );

gl.glLoadIdentity ();

float volume = 100f;

float fAspect = (float) width / (float) height;

glu.gluPerspective (100f, fAspect , .001f, volume * 5f);

}

}

C.5 CubeMap.java

package pt.ipb.esact.cg.examples;

import java.awt.BorderLayout;

import java.awt.Container;

import java.io.IOException;

import java.io.InputStream;

import java.nio.ByteBuffer;

import java.nio.IntBuffer;

import java.util.ArrayList;

import java.util.List;

import javax.media.opengl.GL2;

import javax.media.opengl.GLAutoDrawable;

import javax.media.opengl.GLEventListener;

import javax.media.opengl.awt.GLCanvas;

import javax.media.opengl.glu.GLU;

import javax.swing.JFrame;

import pt.ipb.esact.cg.gl.CGEngine;

import pt.ipb.esact.cg.gl.GLVector;

import pt.ipb.esact.cg.gl.tools.GlTools;

import pt.ipb.esact.cg.gl.tools.GlUtil;

import com.jogamp.opengl.util.FPSAnimator;

import com.jogamp.opengl.util.gl2.GLUT;

import com.jogamp.opengl.util.texture.spi.TGAImage;

@SuppressWarnings("serial")

public class CubeMap extends JFrame implements GLEventListener {

private GLU glu = new GLU ();

private GLUT glut = new GLUT ();

private GLCanvas canvas;

FPSAnimator animator;

private GLVector fLightPos = new GLVector (-100f, 100f, 50f, 1f);

private float fNoLight [] = { 0.0f, 0.0f, 0.0f, 0.0f };

131

Page 133: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

private float fLowLight [] = { 0.25f, 0.25f, 0.25f, 1.0f };

private float fBrightLight [] = { 1.0f, 1.0f, 1.0f, 1.0f };

private static final float FloorSize = 20f;

private static final int NumSpheres = 30;

private List <GLVector > spherePositions = new ArrayList <GLVector >();

private List <String > textureNames = new ArrayList <String >();

private IntBuffer textures;

// Identificadores das texturas da Geometria

private static final int Earth = 0, Grass = 1;

// Numero total de texturas

private static final int NumTextures = 3;

// Identificadores das texturas do Cubo

private static final int CubeStartIndex = 2;

// Direccoes para as texuras do cubo

private static final int[] CubeDirection = {

GL2.GL_TEXTURE_CUBE_MAP_POSITIVE_X ,

GL2.GL_TEXTURE_CUBE_MAP_NEGATIVE_X ,

GL2.GL_TEXTURE_CUBE_MAP_POSITIVE_Y ,

GL2.GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ,

GL2.GL_TEXTURE_CUBE_MAP_POSITIVE_Z ,

GL2.GL_TEXTURE_CUBE_MAP_NEGATIVE_Z

};

public static void main(String [] args) {

new CubeMap ();

}

public CubeMap () {

super("Modelo OpenGL");

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE );

setSize (600, 600);

Container p = getContentPane ();

BorderLayout l = new BorderLayout (5, 5);

p.setLayout(l);

canvas = new GLCanvas ();

p.add(canvas , BorderLayout.CENTER );

canvas.addGLEventListener(this);

GLVector location = new GLVector (0f, .5f, .5f);

new CGEngine(canvas , location );

setVisible(true);

canvas.requestFocus ();

animator = new FPSAnimator(canvas , 25);

animator.start ();

}

@Override

public void dispose(GLAutoDrawable drawable) {

GL2 gl = drawable.getGL (). getGL2 ();

gl.glDeleteTextures(NumTextures , textures );

}

132

Page 134: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

@Override

public void init(GLAutoDrawable drawable) {

GL2 gl = drawable.getGL (). getGL2 ();

// Grayish background

gl.glClearColor(fLowLight [0], fLowLight [1], fLowLight [2], fLowLight [3]);

// Cull backs of polygons

gl.glCullFace(GL2.GL_BACK );

gl.glFrontFace(GL2.GL_CCW );

gl.glEnable(GL2.GL_CULL_FACE );

gl.glEnable(GL2.GL_DEPTH_TEST );

setupLight(gl);

spherePositions = GlUtil.generateRandomPositions(FloorSize , NumSpheres );

setupTextures(gl);

setupCubeMap(gl);

}

private TGAImage loadTexture(String name) {

TGAImage img = null;

try {

InputStream stream = Anisotropic.class.getResourceAsStream(name);

img = TGAImage.read(stream );

stream.close ();

} catch (IOException e) {

e.printStackTrace ();

System.exit (0);

}

return img;

}

private void setupTextures(GL2 gl) {

// Activar as texturas

gl.glEnable(GL2.GL_TEXTURE_2D );

// Obter os identificadores

textures = IntBuffer.allocate(NumTextures ); // 2 texturas + 1 cubo

gl.glGenTextures(NumTextures , textures );

// Configuracao do Texture Environment

gl.glTexEnvi(GL2.GL_TEXTURE_ENV , GL2.GL_TEXTURE_ENV_MODE , GL2.GL_MODULATE );

// Texturas da Geometria

textureNames.add("earth.tga"); // Para os circulos

textureNames.add("grass.tga");

// Texturas do Cube Map

textureNames.add("cubemap/right.tga");

textureNames.add("cubemap/left.tga");

textureNames.add("cubemap/up.tga");

textureNames.add("cubemap/down.tga");

textureNames.add("cubemap/backward.tga");

textureNames.add("cubemap/forward.tga");

// Carregar as texturas da Geometria

for (int i = 0; i < CubeStartIndex; i++) {

// Fazer o bind do estado da textura ao identificador

gl.glBindTexture(GL2.GL_TEXTURE_2D , textures.get(i));

133

Page 135: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

// Carregar e Ler a imagem para a nossa textura

TGAImage img = loadTexture(textureNames.get(i));

ByteBuffer bb = img.getData ();

// Carregar a textura (comprimida RGB)

gl.glTexParameteri(GL2.GL_TEXTURE_2D , GL2.GL_GENERATE_MIPMAP , GL2.GL_TRUE );

gl.glTexImage2D(GL2.GL_TEXTURE_2D , 0, GL2.GL_COMPRESSED_RGB ,

img.getWidth(), img.getHeight(), 0, img.getGLFormat (),

GL2.GL_UNSIGNED_BYTE , bb);

// Parametros da textura

gl.glTexParameteri(GL2.GL_TEXTURE_2D , GL2.GL_TEXTURE_MAG_FILTER ,

GL2.GL_LINEAR );

gl.glTexParameteri(GL2.GL_TEXTURE_2D , GL2.GL_TEXTURE_MIN_FILTER ,

GL2.GL_LINEAR_MIPMAP_LINEAR );

gl.glTexParameteri(GL2.GL_TEXTURE_2D , GL2.GL_TEXTURE_WRAP_S ,

GL2.GL_CLAMP_TO_EDGE );

gl.glTexParameteri(GL2.GL_TEXTURE_2D , GL2.GL_TEXTURE_WRAP_T ,

GL2.GL_CLAMP_TO_EDGE );

}

}

private void setupCubeMap(GL2 gl) {

// Carregar as texturas do Cubo

gl.glBindTexture(GL2.GL_TEXTURE_CUBE_MAP , textures.get(CubeStartIndex ));

gl.glTexParameteri(GL2.GL_TEXTURE_CUBE_MAP , GL2.GL_TEXTURE_MAG_FILTER ,

GL2.GL_LINEAR );

gl.glTexParameteri(GL2.GL_TEXTURE_CUBE_MAP , GL2.GL_TEXTURE_MIN_FILTER ,

GL2.GL_LINEAR );

gl.glTexParameteri(GL2.GL_TEXTURE_CUBE_MAP , GL2.GL_TEXTURE_WRAP_S ,

GL2.GL_REPEAT );

gl.glTexParameteri(GL2.GL_TEXTURE_CUBE_MAP , GL2.GL_TEXTURE_WRAP_T ,

GL2.GL_REPEAT );

gl.glTexParameteri(GL2.GL_TEXTURE_CUBE_MAP , GL2.GL_TEXTURE_WRAP_R ,

GL2.GL_REPEAT );

// Restantes texturas preenchem o cubo

for (int i = CubeStartIndex; i < textureNames.size (); i++) {

// Carregar e Ler a imagem para a nossa textura

TGAImage img = loadTexture(textureNames.get(i));

ByteBuffer bb = img.getData ();

gl.glTexImage2D(CubeDirection[i - CubeStartIndex], 0, GL2.GL_RGBA ,

img.getWidth(), img.getHeight(), 0, img.getGLFormat (),

GL2.GL_UNSIGNED_BYTE , bb);

}

gl.glTexGeni(GL2.GL_S , GL2.GL_TEXTURE_GEN_MODE , GL2.GL_REFLECTION_MAP );

gl.glTexGeni(GL2.GL_T , GL2.GL_TEXTURE_GEN_MODE , GL2.GL_REFLECTION_MAP );

gl.glTexGeni(GL2.GL_R , GL2.GL_TEXTURE_GEN_MODE , GL2.GL_REFLECTION_MAP );

}

private void setupLight(GL2 gl) {

// Setup light parameters

gl.glLightModelfv(GL2.GL_LIGHT_MODEL_AMBIENT , fNoLight , 0);

gl.glLightModeli(GL2.GL_LIGHT_MODEL_COLOR_CONTROL ,

GL2.GL_SEPARATE_SPECULAR_COLOR );

gl.glLightfv(GL2.GL_LIGHT0 , GL2.GL_AMBIENT , fLowLight , 0);

gl.glLightfv(GL2.GL_LIGHT0 , GL2.GL_DIFFUSE , fBrightLight , 0);

gl.glLightfv(GL2.GL_LIGHT0 , GL2.GL_SPECULAR , fBrightLight , 0);

gl.glEnable(GL2.GL_LIGHTING );

134

Page 136: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

gl.glEnable(GL2.GL_LIGHT0 );

// Utilizar color tracking

gl.glEnable(GL2.GL_COLOR_MATERIAL );

gl.glColorMaterial(GL2.GL_FRONT , GL2.GL_AMBIENT_AND_DIFFUSE );

gl.glMateriali(GL2.GL_FRONT , GL2.GL_SHININESS , 128);

}

private float torusRot = 0, earthRot = 0;

@Override

public void display(GLAutoDrawable drawable) {

GL2 gl = drawable.getGL (). getGL2 ();

torusRot += .1f;

if(torusRot > 2f * GlTools.GL_PI)

torusRot = 0f;

earthRot += .05f;

if(earthRot > 2f * GlTools.GL_PI)

earthRot = 0f;

// Clear the window with current clearing color

gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT );

// Componente Especular

gl.glMaterialfv(GL2.GL_FRONT , GL2.GL_SPECULAR , fBrightLight , 0);

// Cor do Material Branca

gl.glColor3f (1f, 1f, 1f);

gl.glPushMatrix ();

// Colocar a Luz

gl.glLightfv(GL2.GL_LIGHT0 , GL2.GL_POSITION , fLightPos.toArray(), 0);

// Desenhar o Chao

GlUtil.drawTexturedGround(textures.get(Grass), FloorSize , 1f);

// Desenhar o nosso mundo de novo

drawWorld(gl);

gl.glPopMatrix ();

}

private void drawWorld(GL2 gl) {

// Desenhar esferas aleatoriamente

gl.glBindTexture(GL2.GL_TEXTURE_2D , textures.get(Earth ));

for(GLVector s : spherePositions) {

gl.glPushMatrix ();

gl.glTranslatef(s.x(), s.y(), s.z());

gl.glRotatef ((float) Math.toDegrees(earthRot), 0f, 1f, 0f);

GlTools.gltDrawSphere (.2f, 20, 10);

gl.glPopMatrix ();

}

// Desenhar o Torus

gl.glPushMatrix ();

// Desactivar temporariamente TEXTURE_2D

gl.glDisable(GL2.GL_TEXTURE_2D );

// Activar o Cube Map

gl.glEnable(GL2.GL_TEXTURE_CUBE_MAP );

135

Page 137: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

gl.glBindTexture(GL2.GL_TEXTURE_CUBE_MAP , textures.get(CubeStartIndex ));

gl.glEnable(GL2.GL_TEXTURE_GEN_S );

gl.glEnable(GL2.GL_TEXTURE_GEN_T );

gl.glEnable(GL2.GL_TEXTURE_GEN_R );

// Desenhar a Geometria que reflecte o cube map

gl.glTranslatef (0, .5f, -.3f);

glut.glutSolidSphere (.15, 61, 37);

gl.glRotatef ((float) Math.toDegrees(torusRot), 0, 1f, 0);

glut.glutSolidTorus (.1f, .3f, 61, 37);

// Colocar tudo como estava

gl.glDisable(GL2.GL_TEXTURE_GEN_S );

gl.glDisable(GL2.GL_TEXTURE_GEN_T );

gl.glDisable(GL2.GL_TEXTURE_GEN_R );

gl.glDisable(GL2.GL_TEXTURE_CUBE_MAP );

gl.glEnable(GL2.GL_TEXTURE_2D );

gl.glPopMatrix ();

}

@Override

public void reshape(GLAutoDrawable drawable , int x, int y, int width , int height) {

GL2 gl = drawable.getGL (). getGL2 ();

if (height == 0)

height = 1; // prevenir divisao por 0

gl.glViewport (0, 0, canvas.getSize ().width , canvas.getSize (). height );

gl.glMatrixMode(GL2.GL_PROJECTION );

gl.glLoadIdentity ();

float volume = 100f;

float fAspect = (float) width / (float) height;

glu.gluPerspective (100f, fAspect , .001f, volume * 5f);

}

}

C.6 SnowMan.java

package pt.ipb.esact.cg.examples.c9;

import java.awt.BorderLayout;

import java.awt.Container;

import javax.media.opengl.GL2;

import javax.media.opengl.GLAutoDrawable;

import javax.media.opengl.GLEventListener;

import javax.media.opengl.awt.GLCanvas;

import javax.media.opengl.glu.GLU;

import javax.media.opengl.glu.GLUquadric;

import javax.swing.JFrame;

import pt.ipb.esact.cg.gl.CGEngine;

import pt.ipb.esact.cg.gl.GLVector;

import com.jogamp.opengl.util.FPSAnimator;

@SuppressWarnings("serial")

public class SnowMan extends JFrame implements GLEventListener {

136

Page 138: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

private GLU glu = new GLU ();

private GLCanvas canvas;

FPSAnimator animator;

private GLVector fLightPos = new GLVector (-100f, 100f, 50f, 1f);

private float fNoLight [] = { 0.5f, 0.5f, 0.5f, 1.0f };

private float fLowLight [] = { 0.25f, 0.25f, 0.25f, 1.0f };

private float fBrightLight [] = { 1.0f, 1.0f, 1.0f, 1.0f };

private GLVector lookAt = new GLVector (0f, 0f, 0f);

private CGEngine e;

public static void main(String [] args) {

new SnowMan ();

}

public SnowMan () {

super("Modelo OpenGL");

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE );

setSize (600, 600);

Container p = getContentPane ();

BorderLayout l = new BorderLayout (5, 5);

p.setLayout(l);

canvas = new GLCanvas ();

p.add(canvas , BorderLayout.CENTER );

GLVector location = new GLVector (1f, .5f, 1f);

e = new CGEngine(canvas , location );

e.camera (). lookAt(lookAt );

canvas.addGLEventListener(this);

setVisible(true);

canvas.requestFocus ();

animator = new FPSAnimator(canvas , 25);

animator.start ();

}

@Override

public void dispose(GLAutoDrawable drawable) {

}

@Override

public void init(GLAutoDrawable drawable) {

GL2 gl = drawable.getGL (). getGL2 ();

// Grayish background

gl.glClearColor(fLowLight [0], fLowLight [1], fLowLight [2], fLowLight [3]);

// Cull backs of polygons

gl.glCullFace(GL2.GL_BACK );

gl.glFrontFace(GL2.GL_CCW );

gl.glEnable(GL2.GL_CULL_FACE );

gl.glEnable(GL2.GL_DEPTH_TEST );

setupLight(gl);

137

Page 139: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

}

private void setupLight(GL2 gl) {

// Setup light parameters

gl.glLightModelfv(GL2.GL_LIGHT_MODEL_AMBIENT , fNoLight , 0);

gl.glLightModeli(GL2.GL_LIGHT_MODEL_COLOR_CONTROL ,

GL2.GL_SEPARATE_SPECULAR_COLOR );

gl.glLightfv(GL2.GL_LIGHT0 , GL2.GL_AMBIENT , fLowLight , 0);

gl.glLightfv(GL2.GL_LIGHT0 , GL2.GL_DIFFUSE , fBrightLight , 0);

gl.glLightfv(GL2.GL_LIGHT0 , GL2.GL_SPECULAR , fBrightLight , 0);

gl.glEnable(GL2.GL_LIGHTING );

gl.glEnable(GL2.GL_LIGHT0 );

// Utilizar color tracking

gl.glEnable(GL2.GL_COLOR_MATERIAL );

gl.glColorMaterial(GL2.GL_FRONT , GL2.GL_AMBIENT_AND_DIFFUSE );

gl.glMateriali(GL2.GL_FRONT , GL2.GL_SHININESS , 128);

}

@Override

public void display(GLAutoDrawable drawable) {

GL2 gl = drawable.getGL (). getGL2 ();

// Clear the window with current clearing color

gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT );

// Componente Especular

gl.glMaterialfv(GL2.GL_FRONT , GL2.GL_SPECULAR , fBrightLight , 0);

// Posicao da Luz

gl.glLightfv(GL2.GL_LIGHT0 , GL2.GL_POSITION , fLightPos.toArray(), 0);

// Cor do Material Branca

gl.glColor3f (0f, 0f, 0f);

GLUquadric quad = glu.gluNewQuadric (); // Criar o quadric

gl.glPushMatrix ();

glu.gluQuadricNormals(quad , GLU.GLU_SMOOTH );

// Corpo

gl.glPushMatrix ();

// Bola do Fundo

gl.glColor3f (1.0f, 1.0f, 1.0f);

glu.gluSphere(quad , .40f, 26, 13);

// Bola do Corpo

gl.glTranslatef (0.0f, .550f, 0.0f);

glu.gluSphere(quad , .3f, 26, 13);

// Bola da Cabeca

gl.glTranslatef (0.0f, 0.45f, 0.0f);

glu.gluSphere(quad , 0.24f, 26, 13);

// Olhos

gl.glColor3f (0.0f, 0.0f, 0.0f);

gl.glTranslatef (0.1f, 0.1f, 0.21f);

glu.gluSphere(quad , 0.02f, 26, 13);

gl.glTranslatef (-0.2f, 0.0f, 0.0f);

glu.gluSphere(quad , 0.02f, 26, 13);

138

Page 140: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

// Nariz

gl.glColor3f (1.0f, 0.3f, 0.3f);

gl.glTranslatef (0.1f, -0.12f, 0.0f);

glu.gluCylinder(quad , 0.04f, 0.0f, 0.3f, 26, 13);

gl.glPopMatrix ();

// Chapeu

gl.glPushMatrix ();

gl.glColor3f (0.0f, 0.0f, 0.0f);

gl.glTranslatef (0.0f, 1.17f, 0.0f);

gl.glRotatef (-90.0f, 1.0f, 0.0f, 0.0f);

glu.gluCylinder(quad , 0.17f, 0.17f, 0.4f, 26, 13);

// Hat brim

gl.glDisable(GL2.GL_CULL_FACE ); // Pintar ambos os lados

glu.gluDisk(quad , 0.17f, 0.28f, 26, 13);

gl.glEnable(GL2.GL_CULL_FACE );

gl.glTranslatef (0.0f, 0.0f, 0.40f);

glu.gluDisk(quad , 0.0f, 0.17f, 26, 13);

gl.glPopMatrix ();

gl.glPopMatrix ();

}

@Override

public void reshape(GLAutoDrawable drawable , int x, int y, int width , int height) {

GL2 gl = drawable.getGL (). getGL2 ();

if (height == 0)

height = 1; // prevenir divisao por 0

gl.glViewport (0, 0, canvas.getSize ().width , canvas.getSize (). height );

gl.glMatrixMode(GL2.GL_PROJECTION );

gl.glLoadIdentity ();

float volume = 100f;

float fAspect = (float) width / (float) height;

glu.gluPerspective (100f, fAspect , .001f, volume * 5f);

}

}

C.7 Bezier2D.java

package pt.ipb.esact.cg.examples.c9;

import java.awt.BorderLayout;

import java.awt.Container;

import javax.media.opengl.GL2;

import javax.media.opengl.GLAutoDrawable;

import javax.media.opengl.GLEventListener;

import javax.media.opengl.awt.GLCanvas;

import javax.media.opengl.glu.GLU;

import javax.swing.JFrame;

import pt.ipb.esact.cg.gl.GLVector;

import pt.ipb.esact.cg.gl.GLVectorList;

import com.jogamp.opengl.util.FPSAnimator;

@SuppressWarnings("serial")

139

Page 141: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

public class Bezier2D extends JFrame implements GLEventListener {

private GLU glu = new GLU ();

private GLCanvas canvas;

FPSAnimator animator;

private GLVectorList ctrlPoints;

public static void main(String [] args) {

new Bezier2D ();

}

public Bezier2D () {

super("Modelo OpenGL");

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE );

setSize (600, 600);

Container p = getContentPane ();

BorderLayout l = new BorderLayout (5, 5);

p.setLayout(l);

canvas = new GLCanvas ();

p.add(canvas , BorderLayout.CENTER );

canvas.addGLEventListener(this);

setVisible(true);

canvas.requestFocus ();

animator = new FPSAnimator(canvas , 25);

animator.start ();

}

@Override

public void dispose(GLAutoDrawable drawable) {

}

@Override

public void init(GLAutoDrawable drawable) {

GL2 gl = drawable.getGL (). getGL2 ();

// Grayish background

gl.glClearColor (.5f, .5f, .5f, .5f);

// Definir Pontos de Controlo

ctrlPoints = new GLVectorList ();

ctrlPoints.add(-4f, 0f, 0f); // Start

ctrlPoints.add(-6f, 4f, 0f); // Control

ctrlPoints.add(6f, -4f, 0f); // Control

ctrlPoints.add(4f, 0f, 0f); // End

}

public void display(GLAutoDrawable drawable) {

GL2 gl = drawable.getGL (). getGL2 ();

gl.glClear(GL2.GL_COLOR_BUFFER_BIT );

float umin = 0f; // Valor minimo do u

float umax = 100f; // Valor maximo do u

gl.glMap1f(

GL2.GL_MAP1_VERTEX_3 , // Tipo de dados gerados

umin , // Valor minimo do u

umax , // Valor maximo do u

3, // Distancia entre pontos

140

Page 142: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

ctrlPoints.size(), // Numero de pontos de controlo

ctrlPoints.toFloatBuffer () // FloatBuffer contendo pontos de controlo

);

// Activar o Evaluator

gl.glEnable(GL2.GL_MAP1_VERTEX_3 );

// Desenhar os vertices da curva

/*

gl.glColor3f (0f, 0f, 0f);

gl.glBegin(GL2.GL_LINE_STRIP );

for(float i=umin; i<umax; i++)

gl.glEvalCoord1f(i);

gl.glEnd ();

*/

gl.glColor3f (0f, 0f, 0f);

gl.glMapGrid1d (100, umin , umax);

gl.glEvalMesh1(GL2.GL_LINE , (int)umin , (int)umax);

// Desenhar Pontos de Controlo

gl.glPointSize (5.0f);

gl.glColor3f (1f, 0f, 0f);

gl.glBegin(GL2.GL_POINTS );

for(GLVector point : ctrlPoints)

point.draw ();

gl.glEnd ();

}

@Override

public void reshape(GLAutoDrawable drawable , int x, int y, int width , int height) {

GL2 gl = drawable.getGL (). getGL2 ();

if (height == 0)

height = 1; // prevenir divisao por 0

gl.glViewport (0, 0, canvas.getSize ().width , canvas.getSize (). height );

gl.glMatrixMode(GL2.GL_PROJECTION );

gl.glLoadIdentity ();

glu.gluOrtho2D (-10f, 10f, -10f, 10f);

gl.glMatrixMode(GL2.GL_MODELVIEW );

gl.glLoadIdentity ();

}

}

C.8 Bezier3D.java

package pt.ipb.esact.cg.examples.c9;

import java.awt.BorderLayout;

import java.awt.Container;

import javax.media.opengl.GL2;

import javax.media.opengl.GLAutoDrawable;

import javax.media.opengl.GLEventListener;

import javax.media.opengl.awt.GLCanvas;

import javax.media.opengl.glu.GLU;

import javax.swing.JFrame;

import pt.ipb.esact.cg.gl.CGEngine;

import pt.ipb.esact.cg.gl.GLVector;

141

Page 143: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

import pt.ipb.esact.cg.gl.GLVectorList;

import com.jogamp.opengl.util.FPSAnimator;

@SuppressWarnings("serial")

public class Bezier3D extends JFrame implements GLEventListener {

private GLU glu = new GLU ();

private GLCanvas canvas;

FPSAnimator animator;

private GLVectorList ctrlPoints;

private GLVector lookAt = new GLVector (0f, .5f, 0f);

private CGEngine e;

public static void main(String [] args) {

new Bezier3D ();

}

public Bezier3D () {

super("Modelo OpenGL");

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE );

setSize (600, 600);

Container p = getContentPane ();

BorderLayout l = new BorderLayout (5, 5);

p.setLayout(l);

canvas = new GLCanvas ();

p.add(canvas , BorderLayout.CENTER );

canvas.addGLEventListener(this);

GLVector location = new GLVector (5f, .5f, 5f);

e = new CGEngine(canvas , location );

e.camera (). lookAt(lookAt );

setVisible(true);

canvas.requestFocus ();

animator = new FPSAnimator(canvas , 25);

animator.start ();

}

@Override

public void dispose(GLAutoDrawable drawable) {

}

@Override

public void init(GLAutoDrawable drawable) {

GL2 gl = drawable.getGL (). getGL2 ();

// Grayish background

gl.glClearColor (.5f, .5f, .5f, .5f);

// Definir Pontos de Controlo

ctrlPoints = new GLVectorList ();

// v0

ctrlPoints.add(-4f, 0f, 4f); // Start (u0)

ctrlPoints.add(-2f, 4f, 4f); // Control (u0)

ctrlPoints.add(4f, 0f, 4f); // End (u0)

142

Page 144: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

// v1

ctrlPoints.add(-4f, 0f, 0f); // Start (u1)

ctrlPoints.add(-2f, 4f, 0f); // Control (u1)

ctrlPoints.add(4f, 0f, 0f); // End (u1)

// v2

ctrlPoints.add(-4f, 0f, -4f); // Start (u2)

ctrlPoints.add(-2f, 4f, -4f); // Control (u2)

ctrlPoints.add(4f, 0f, -4f); // End (u2)

}

public void display(GLAutoDrawable drawable) {

GL2 gl = drawable.getGL (). getGL2 ();

gl.glClear(GL2.GL_COLOR_BUFFER_BIT );

float umin = 0f; // Valor minimo do u

float umax = 10f; // Valor maximo do u

float vmin = 0f; // Valor minimo do v

float vmax = 10f; // Valor maximo do v

gl.glMap2f(

GL2.GL_MAP2_VERTEX_3 , // Tipo de dados gerados

umin , // Valor minimo do u

umax , // Valor maximo do u

3, // Distancia entre pontos (dominio u)

3, // Numero de pontos de controlo (dominio u)

vmin , // Valor minimo do v

vmax , // Valor maximo do v

9, // Distancia entre pontos (dominio v)

3, // Numero de pontos de controlo (dominio v)

ctrlPoints.toFloatBuffer () // FloatBuffer contendo pontos de controlo

);

// Activar o Evaluator

gl.glEnable(GL2.GL_MAP2_VERTEX_3 );

// Desenhar os vertices da superficie

gl.glColor3f (0f, 0f, 0f);

gl.glMapGrid2d (10, umin , umax , 10, vmin , vmax);

gl.glEvalMesh2(GL2.GL_LINE , (int)umin , (int)umax , (int)vmin , (int) vmax);

// Desenhar Pontos de Controlo

gl.glPointSize (5.0f);

gl.glColor3f (1f, 0f, 0f);

gl.glBegin(GL2.GL_POINTS );

for(GLVector point : ctrlPoints)

point.draw ();

gl.glEnd ();

gl.glPopMatrix ();

}

@Override

public void reshape(GLAutoDrawable drawable , int x, int y, int width , int height) {

GL2 gl = drawable.getGL (). getGL2 ();

if (height == 0)

height = 1; // prevenir divisao por 0

gl.glViewport (0, 0, canvas.getSize ().width , canvas.getSize (). height );

gl.glMatrixMode(GL2.GL_PROJECTION );

gl.glLoadIdentity ();

float volume = 100f;

float fAspect = (float) width / (float) height;

143

Page 145: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

glu.gluPerspective (100f, fAspect , .001f, volume * 5f);

}

}

C.9 BezierLighting.java

package pt.ipb.esact.cg.examples.c9;

import java.awt.BorderLayout;

import java.awt.Container;

import javax.media.opengl.GL2;

import javax.media.opengl.GLAutoDrawable;

import javax.media.opengl.GLEventListener;

import javax.media.opengl.awt.GLCanvas;

import javax.media.opengl.glu.GLU;

import javax.swing.JFrame;

import pt.ipb.esact.cg.gl.CGEngine;

import pt.ipb.esact.cg.gl.GLVector;

import pt.ipb.esact.cg.gl.GLVectorList;

import pt.ipb.esact.cg.gl.tools.GlTools;

import com.jogamp.opengl.util.FPSAnimator;

@SuppressWarnings("serial")

public class BezierLighting extends JFrame implements GLEventListener {

private GLU glu = new GLU ();

private GLCanvas canvas;

FPSAnimator animator;

private GLVector fLightPos = new GLVector (100f, 100f, 50f, 1f);

private float fNoLight [] = { 0.0f, 0.0f, 0.0f, 0.0f };

private float fLowLight [] = { 0.25f, 0.25f, 0.25f, 1.0f };

private float fBrightLight [] = { .5f, .5f, .5f, 1.0f };

private GLVectorList ctrlPoints;

private GLVector lookAt = new GLVector (0f, .5f, 0f);

private CGEngine e;

public static void main(String [] args) {

new BezierLighting ();

}

public BezierLighting () {

super("Modelo OpenGL");

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE );

setSize (600, 600);

Container p = getContentPane ();

BorderLayout l = new BorderLayout (5, 5);

p.setLayout(l);

canvas = new GLCanvas ();

p.add(canvas , BorderLayout.CENTER );

canvas.addGLEventListener(this);

144

Page 146: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

GLVector location = new GLVector (5f, .5f, 5f);

e = new CGEngine(canvas , location );

e.camera (). lookAt(lookAt );

setVisible(true);

canvas.requestFocus ();

animator = new FPSAnimator(canvas , 25);

animator.start ();

}

@Override

public void dispose(GLAutoDrawable drawable) {

}

@Override

public void init(GLAutoDrawable drawable) {

GL2 gl = drawable.getGL (). getGL2 ();

// Grayish background

gl.glClearColor (0f, 0f, 0f, 0f);

// Cull backs of polygons

gl.glCullFace(GL2.GL_BACK );

gl.glFrontFace(GL2.GL_CCW );

gl.glEnable(GL2.GL_DEPTH_TEST );

setupLight(gl);

// Definir Pontos de Controlo

ctrlPoints = new GLVectorList ();

updateControlPoints ();

// Activar a geracao automatica de normais

gl.glEnable(GL2.GL_AUTO_NORMAL );

}

private float a0 = 0, a1 = GlTools.GL_PI / 4, a2 = GlTools.GL_PI / 2;

private void updateControlPoints () {

ctrlPoints.clear ();

a0 += .1f;

if(a0 >= GlTools.GL_PI)

a0 = 0;

a1 += .1f;

if(a1 >= GlTools.GL_PI)

a1 = 0;

a2 += .1f;

if(a2 >= GlTools.GL_PI)

a2 = 0;

// v0

ctrlPoints.add(-4f, 0f, 4f); // Start (u0)

ctrlPoints.add(-2f, (float) (Math.sin(a0) * 8f - 4f), 4f); // Control (u0)

ctrlPoints.add(4f, 0f, 4f); // End (u0)

// v1

ctrlPoints.add(-4f, 0f, 0f); // Start (u1)

ctrlPoints.add(-2f, (float) (Math.sin(a1) * 8f - 4f), 0f); // Control (u1)

145

Page 147: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

ctrlPoints.add(4f, 0f, 0f); // End (u1)

// v2

ctrlPoints.add(-4f, 0f, -4f); // Start (u2)

ctrlPoints.add(-2f, (float) (Math.sin(a2) * 8f - 4f), -4f); // Control (u2)

ctrlPoints.add(4f, 0f, -4f); // End (u2)

}

private void setupLight(GL2 gl) {

// Setup light parameters

gl.glLightModelfv(GL2.GL_LIGHT_MODEL_AMBIENT , fNoLight , 0);

gl.glLightModeli(GL2.GL_LIGHT_MODEL_COLOR_CONTROL ,

GL2.GL_SEPARATE_SPECULAR_COLOR );

gl.glLightfv(GL2.GL_LIGHT0 , GL2.GL_AMBIENT , fLowLight , 0);

gl.glLightfv(GL2.GL_LIGHT0 , GL2.GL_DIFFUSE , fBrightLight , 0);

gl.glLightfv(GL2.GL_LIGHT0 , GL2.GL_SPECULAR , fBrightLight , 0);

gl.glEnable(GL2.GL_LIGHTING );

gl.glEnable(GL2.GL_LIGHT0 );

// Utilizar color tracking

gl.glEnable(GL2.GL_COLOR_MATERIAL );

gl.glColorMaterial(GL2.GL_FRONT , GL2.GL_AMBIENT_AND_DIFFUSE );

gl.glMateriali(GL2.GL_FRONT , GL2.GL_SHININESS , 128);

}

public void display(GLAutoDrawable drawable) {

GL2 gl = drawable.getGL (). getGL2 ();

gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT );

updateControlPoints ();

// Componente Especular

gl.glMaterialfv(GL2.GL_FRONT , GL2.GL_SPECULAR , fBrightLight , 0);

// Posicao da Luz

gl.glLightfv(GL2.GL_LIGHT0 , GL2.GL_POSITION , fLightPos.toArray(), 0);

float umin = 0f; // Valor minimo do u

float umax = 10f; // Valor maximo do u

float vmin = 0f; // Valor minimo do v

float vmax = 10f; // Valor maximo do v

gl.glMap2f(

GL2.GL_MAP2_VERTEX_3 , // Tipo de dados gerados

umin , // Valor minimo do u

umax , // Valor maximo do u

3, // Distancia entre pontos (dominio u)

3, // Numero de pontos de controlo (dominio u)

vmin , // Valor minimo do v

vmax , // Valor maximo do v

9, // Distancia entre pontos (dominio v)

3, // Numero de pontos de controlo (dominio v)

ctrlPoints.toFloatBuffer () // FloatBuffer contendo pontos de controlo

);

// Activar o Evaluator

gl.glEnable(GL2.GL_MAP2_VERTEX_3 );

// Desenhar os vertices da superficie

gl.glColor3f (0f, 0f, 1f);

gl.glMapGrid2d (10, umin , umax , 10, vmin , vmax);

gl.glEvalMesh2(GL2.GL_FILL , (int)umin , (int)umax , (int)vmin , (int) vmax);

// Desenhar Pontos de Controlo

146

Page 148: Computa˘c~ao Gr a ca Manual de Apoio 2010ellobo/sebenta-2010.pdf · 2012-01-10 · 1.2 Efeitos 3D Uma palavra a ter em mente na computa˘c~ao gr a ca e rendering. Rendering consiste

gl.glPointSize (5.0f);

gl.glColor3f (1f, 0f, 0f);

gl.glBegin(GL2.GL_POINTS );

for(GLVector point : ctrlPoints)

point.draw ();

gl.glEnd ();

gl.glPopMatrix ();

}

@Override

public void reshape(GLAutoDrawable drawable , int x, int y, int width , int height) {

GL2 gl = drawable.getGL (). getGL2 ();

if (height == 0)

height = 1; // prevenir divisao por 0

gl.glViewport (0, 0, canvas.getSize ().width , canvas.getSize (). height );

gl.glMatrixMode(GL2.GL_PROJECTION );

gl.glLoadIdentity ();

float volume = 100f;

float fAspect = (float) width / (float) height;

glu.gluPerspective (100f, fAspect , .001f, volume * 5f);

}

}

147