KLEBER LOPES DA SILVA
ILUMINAÇÃO EM JOGOS 3D UMA ABORDAGEM UTILIZANDO OPENGL
Londrina 2006
KLEBER LOPES DA SILVA
ILUMINAÇÃO EM AMBIENTES 3D
Trabalho de Conclusão de Curso como requisito parcial à obtenção do título de Bacharel no curso de Ciência da Computação. Orientador: Prof. Dr. Alan Salvany Felinto.
Londrina 2006
KLEBER LOPES DA SILVA
ILUMINAÇÃO EM AMBIENTES 3D
Trabalho de Conclusão de Curso como requisito parcial à obtenção do título de Bacharel no curso de Ciência da Computação. Orientador: Prof. Dr. Alan Salvany Felinto.
COMISSÃO EXAMINADORA
________________________________ Prof. Dr. Alan Salvany Felinto
____________________________________ Prof. Ms. Márcio Shimoda
____________________________________ Prof. Dra. Cinthyan Renata Sachs C. de Barbosa
Londrina, 1º de dezembro de 2006
DEDICATÓRIA Dedicados a todos aqueles que sempre gostaram de jogos e que um dia perceberam que gostam mais de fazê-los de que jogá-los.
AGRADECIMENTO
Agradeço a Deus, por sua invisível, constante, porém indispensável ajuda, e às pessoas que sempre estiveram ao meu lado, meus pais, meus amigos (incluindo professores), me incentivando e me ajudando a ultrapassar todos os obstáculos que já passei.
RESUMO
Com o crescente desenvolvimento da programação de jogos, torna-se indispensável aos futuros desenvolvedores o estudo sobre técnicas referentes a este campo. Um dos estudos de maior importância neste ramo é o da iluminação, que contribui maciçamente para o bom visual de um jogo. A área de computação gráfica e iluminação em tempo real é bastante vasta, complexa e interessante, por isso, os estudos aqui contidos servem apenas como alavanca para os mais interessados em prosseguir na área. Palavras-chave: Jogos; OpenGL; iluminação; Sombras; Reflexos.
ABSTRACT
With the increasing development of the gamming programming, the study of the techniques about this area becomes indispensable to the developers of the future. One of the studies of major importance in this branch is the illumination, that contributes massively for the good appearance of a game. The area of graphical computation and illumination in real time is vast, complex and interesting, therefore, the studies contained here only serve as handspike for continuing in the study in this area. Key words: Games; OpenGL; illumination; shadows; reflex.
LISTA DE FIGURAS
Figura 1: Espectro óptico..........................................................................................13 Figura 2: Refração de um raio de luz. ......................................................................14 Figura 3: Reflexão especular....................................................................................15 Figura 4: Reflexão difusa. ........................................................................................15 Figura 5: Projeção da sombra de um objeto opaco numa superfície plana..............15 Figura 6: Sistema Aditivo RGB.................................................................................18 Figura 7: Sistema subtrativo CMYK..........................................................................18 Figura 8: Imagem dividida nos canais do Sistema CMYK. .......................................20 Figura 9: Cubo de cores RGB simplificado com corte central. .................................20 Figura 10: Imagem dividida nos canais do Sistema RGB.........................................21 Figura 11: Cone de cores do Sistema HSV. .............................................................22 Figura 12: Duplo cone de cores do Sistema HLS.....................................................23 Figura 13: Estrutura de um comando de OpenGL....................................................25 Figura 14: Superfícies reflexivas. .............................................................................26 Figura 15: Luz incidente nas superfícies. .................................................................27 Figura 16: Luz incidente nas superfícies formando uma imagem de computador....28 Figura 17: Interações luz-material.. ..........................................................................29 Figura 18: Uma fonte de luz. ....................................................................................29 Figura 19: Holofote (spotlight). .................................................................................32 Figura 20: Atenuação de um holofote.......................................................................32 Figura 21: Expoente do holofote...............................................................................33 Figura 22: Luz distante incidindo paralelamente em uma superfície. .......................33 Figura 23: Os vetores utilizados no modelo de Phong. ............................................34 Figura 24: Ampliação de uma superfície difusa........................................................36 Figura 25: Luz do sol incidindo sobre uma superfície. .............................................37 Figura 26: Lei de Lambert. .......................................................................................37 Figura 27: Ampliação de uma superfície especular..................................................38 Figura 28: Efeito do coeficiente de brilho. ................................................................39 Figura 29: Determinação do vetor h (halfway vector). ..............................................40 Figura 30: Uma superfície dividida em polígonos.....................................................41 Figura 31: Flat shading aplicado a uma superfície. ..................................................42 Figura 32: Faixas Mach (Mach bands). ....................................................................43 Figura 33: Normais dos polígonos e do vértice central segundo Gouraud. ..............44 Figura 34: Gourauge Shading. .................................................................................44 Figura 35: Matriz de sombreamento.........................................................................46 Figura 36: Volume de sombra. Fonte: McREYNOLDS, BLYTHE, 2005...................48 Figura 37: Etapas para realização do efeito de reflexo ............................................50 Figura 38: Aplicação de múltiplas texturas a uma mesma face................................51 Figura 39: Figura de um environment mapping........................................................52 Figura 40: Textura lente olho-de-peixe.....................................................................53
SUMÁRIO
1. INTRODUÇÃO ..................................................................................................................11 2. ASPECTOS TEÓRICOS ...................................................................................................12 2.1. A Luz Segundo a Física..................................................................................12 2.1.1. Aspectos Físicos ......................................................................................12 2.1.2. Fenômenos relacionados à luz ................................................................13 2.1.3. Refração e Reflexão.................................................................................13 2.1.4. Sombra.....................................................................................................15 2.2. Cores ..............................................................................................................16 2.2.1. Aspectos Físicos ......................................................................................16 2.2.2. Percepção Humana das Cores ................................................................16 2.2.3. Sistemas de Cores ...................................................................................17 2.2.4. O Sistema de Cores CMYK......................................................................19 2.2.5. O Sistema de Cores RGB ........................................................................20 2.2.6. Os Sistemas de Cores HSV e HLS ..........................................................22 3. ASPECTOS COMPUTACIONAIS ..................................................................................24 3.1. A biblioteca gráfica OpenGL ...........................................................................24 3.1.1. Formação dos Comandos em OpenGL....................................................24 3.1.2. Máquina de Estados.................................................................................25 3.2. Luzes e Materiais............................................................................................26 3.3. Fontes de Luz .................................................................................................29 3.3.1. Fontes de Cores.......................................................................................30 3.3.2. Luz Ambiente ...........................................................................................30 3.3.3. Fontes Pontuais .......................................................................................31 3.3.4. Holofotes (Spotlights) ...............................................................................32 3.3.5. Fontes Distantes de Luz...........................................................................33 3.4. Modelo de Reflexão de Phong (Phong Reflection Model) ..............................34 3.4.1. Reflexão Ambiente ...................................................................................36 3.4.2. Reflexão Difusa ........................................................................................36 3.4.3. Reflexão Especular ..................................................................................38 3.4.4. O Modelo de Phong Modificado (Modelo Blinn-Phong)............................40 3.5. Sombreamento Poligonal (Polygonal Shading) ..............................................41 3.5.1. Sombreamento Plano (Flat Shading) .......................................................42 3.5.2. Sombreamento Suave/Gouraud (Smooth/Gouraud Shading) ..................43 3.5.3. Sombreamento de Phong (Phong Shading).............................................44 3.6. Sombras .........................................................................................................45 3.6.1. Sombras Projetadas (Projective Shadows) ..............................................45 3.6.2. Volumes de Sombras (Shadow Volumes)................................................47 3.7. Reflexos..........................................................................................................49 3.7.1. Reflexos Através do Método de Reflexão por Texturas ...........................51 3.7.2. Multi-texturas............................................................................................51 3.7.3. Environment Mapping ..............................................................................52 3.8. Reflexos Utilizando Objetos Virtuais ...............................................................53 4. CONCLUSÃO.....................................................................................................................58
10
BIBLIOGRAFIA ....................................................................................................................59
11
1. INTRODUÇÃO
Há alguns anos, quando os jogos eletrônicos começaram a existir, o hardware dos computadores que os suportava era o que mais limitava a evolução destes jogos. Porém, com o avanço rápido das tecnologias computacionais como o aumento do processamento, de memória, das placas gráficas, os programadores de jogos se viram em um mundo de possibilidades, onde agora o limite é a criatividade das empresas desenvolvedoras. Ao se programar um jogo, dependendo da sua ambientação e de seu público-alvo, uma das principais preocupações pode ser o nível de realidade reservado a ele. Um nível alto de detalhamento é exigido para os modelos utilizados no jogo, nos cenários e nos efeitos. Porém, nada disso será tão próximo do real se não houver uma preocupação especial com a iluminação destes elementos. É nela, nos efeitos que ela causa e nos modelos em si que se deve concentrar boa parte dos esforços para tornar o jogo satisfatório aos olhos dos jogadores. Pensando neste aspecto, foi desenvolvido este trabalho para o estudo de técnicas de iluminação e de implementação de efeitos referentes a ela, como sombras, reflexos, etc., baseando-se na biblioteca gráfica OpenGL, uma das mais utilizadas na área de jogos. Este trabalho é dividido em duas partes: A primeira, onde são estudados os aspectos teóricos sobre a luz e seus principais efeitos como a sombra e o reflexo. A segunda parte, que trata de aspectos computacionais, se divide também em duas partes: uma que se concentra em entender o funcionamento das luzes em OpenGL e a outra focando na utilização da própria OpenGL para a criação de efeitos visuais.
12
2. ASPECTOS TEÓRICOS Neste capítulo serão abordados os aspectos teóricos dos assuntos englobados por este trabalho. Os temas aqui discutidos serão sucintos e limitados à utilização dos mesmos no contexto abordado pelo trabalho. 2.1. A LUZ SEGUNDO A FÍSICA A misteriosa natureza da luz sempre foi tema de fascínio para os maiores cientistas da história, despertando controvérsias, polêmicas e interpretações conceituais duvidosas que, ao longo do tempo, foram sendo adaptadas, reformuladas ou mesmo refutadas pela comunidade científica. Este capítulo tem como objetivo discutir superficialmente o que se sabe hoje sobre a luz e os fenômenos relacionados a ela: refração, reflexão e sombra. 2.1.1. Aspectos Físicos A luz, segundo a física, é um fenômeno capaz de incitar e sensibilizar os olhos de quem a vê. É o elemento que faz uma cena ser visível, pois é ela quem se choca com os objetos e é refletida para os olhos do observador. Mais detalhadamente, a luz é uma radiação eletromagnética cujo olho humano é sensível. Ela é formada por fótons (PHOTONS ..., 2006) e possui três dimensões básicas (LIGHT..., 2006): •
Intensidade (ou amplitude): que é a luminosidade da luz e está relacionado com a amplitude da onda eletromagnética que a forma (INTENSITY..., 2006). Quanto maior sua amplitude, mais intensa a luz parece. Isto está relacionado também com a percepção humana de brilho;
•
Freqüência (ou comprimento de onda): é a quantidade de vezes que a onda se repete num período determinado de tempo (FREQUENCY..., 2006). É percebida pelo olho humano como sendo a coloração da luz;
•
Polarização
(ou
eletromagnéticas
ângulo que
de
vibração):
descreve
a
uma
direção
propriedade da
oscilação
das da
ondas onda
13
(POLARIZATION..., 2006). É um fenômeno percebido por algumas pessoas diante de circunstâncias particulares. A teoria aceita hoje pelos estudiosos é de que o fenômeno da luz é tanto uma onda quanto um conjunto de partículas, o que lhe confere características particulares, como o choque entre dois feixes de luz não resultar em um desvio. O espectro visível (ou espectro óptico) é a parte do espectro eletromagnético que é visível ao olho humano e é chamado de luz visível (VISIBLE..., 2006). Este espectro vai de aproximadamente 400nm a 700nm de comprimento de onda. A variação deste comprimento caracteriza as cores visíveis, como mostra a Figura 1.
Figura 1: Espectro óptico. Ondas eletromagnéticas com comprimentos de onda menores (ultravioleta, raios-x e raios gama) ou maiores (infravermelho, microondas e ondas de rádio) que as do espectro óptico não são visíveis ao olho humano. 2.1.2. Fenômenos relacionados à luz A luz apresenta alguns fenômenos relacionados a ela, tanto por ela ser uma onda quanto por ela ser um conjunto de partículas. Aqui, vamos discutir alguns mais interessantes aos estudos deste trabalho. 2.1.3. Refração e Reflexão Dois dos mais importantes fenômenos que estão relacionados às propriedades da luz visível (e também a alguns outros tipos de ondas) são a refração e a reflexão. Refração é o fenômeno que ocorre quando a luz (ou qualquer tipo de onda) atravessa dois meios transparentes pelos quais ela se propaga em
14
velocidades diferentes, acarretando no desvio da onda (REFRACTION..., 2006), como ilustrado na Figura 2.
Figura 2: Refração de um raio de luz. Reflexão é o fenômeno que muda a direção de uma onda quando ela incide em uma superfície. A reflexão da onda de luz pode ser de duas formas 1 (REFLECTION..., 2006): •
Especular: a reflexão especular é o fenômeno que ocorre com superfícies lisas (como um espelho), onde os raios de luz que incidem nelas são refletidos de maneira regular, formando muitas vezes uma imagem bem nítida (SPECULAR..., 2006) (Figura 3);
•
Difusa: A reflexão dispersa ou difusa acontece em superfícies que possuem irregularidades e, portanto, refletem a luz de maneira irregular. Esse fenômeno é responsável pela aparência de cor de um objeto, pois quando a luz incide sobre um objeto que possui cor, a parte da luz que é refletida de maneira dispersa possui o comprimento de onda correspondente a cor do objeto (DIFFUSE..., 2006) (Figura 4).
1
Há outros tipos de reflexão como a retro reflexão, porém fogem do escopo deste trabalho.
15
Figura 3: Reflexão especular.
Figura 4: Reflexão difusa.
2.1.4. Sombra Sombra é a região escura formada pela ausência parcial da luz. Ela ocupa a parte de trás de um objeto opaco que é iluminado por uma fonte de luz na sua parte da frente. Além disso, ela também é a projeção escura que forma uma silhueta bidimensional e invertida na superfície onde o objeto opaco se encontra (SHADOW..., 2006). A opacidade do objeto e a intensidade da fonte de luz determinam a luminosidade da sombra (SOMBRA..., 2006). Além disso, quanto mais perto de 90° o ângulo da fonte está em relação ao objeto (θ na Figura 5), maior será a sombra projetada.
Figura 5: Projeção da sombra de um objeto opaco numa superfície plana. Fisicamente, a sombra é formada pela umbra e pela penumbra. A umbra é a parte mais escura, cujo, do ponto de vista da fonte de luz, não é possível se ver, ou seja, a umbra não recebe luz da fonte. A penumbra é a região onde a sombra recebe um pouco de luz da fonte, por isso forma uma silhueta não tão escura quanto a umbra.
16
2.2. CORES Juntamente com a luz, as cores são o que dão vida a uma cena, tanto que suas definições se confundem. As cores são formadas a partir da decomposição da própria luz branca, dependendo do comprimento de onda da luz, tem-se uma cor diferente. As próximas seções discutem a formação da cor em objetos reais, a maneira como os seres humanos a percebem e os sistemas de cores, com alguns exemplos mais importantes. 2.2.1. Aspectos Físicos A cor é um fenômeno ótico que ocorre no contato dos fótons que formam a luz visível (Figura 1) com as células fotossensíveis localizadas no olho do observador. As cores e seus nomes estão associados aos seus respectivos comprimentos de onda (COR..., 2006). As categorias de cores e suas especificações físicas estão relacionadas também com os objetos, materiais que os formam, fontes de luz, etc., baseados nas propriedades físicas de absorção, reflexão e emissão (COLOR..., 2006). A luz que incide em objetos opacos é refletida especularmente (como num espelho), dispersa (refletida) irregularmente, absorvida ou qualquer combinação destes três fenômenos. Objetos opacos que não apresentam reflexão especular, têm sua cor determinada pelo comprimento de onda da luz que ele dispersa mais, sendo todas as outras absorvidas. Objetos que dispersam todas as cores parecem brancos, e os que absorvem todas elas, parecem pretos (COLOR..., 2006). 2.2.2. Percepção Humana das Cores Quando as cores que são refletidas por objetos e incidem nos olhos do observador, células especializadas em sua captação de luz entram em ação. Estas células são chamadas de células fotossensíveis e estão localizadas na retina do olho humano.
17
Dois tipos de células são fotossensíveis dentro do olho humano: os bastonetes, que são especializados em captação da pouca luz, penumbra e luz noturna e os cones (ou células-cone), que são responsáveis pela captação da luz mais clara, das cores e do contraste (TEORIA..., 2006). Segundo a teoria dos três estímulos (Tristimulus Color Theory) proposta por Young e Helmholtz (1802, 1850), a percepção humana é baseada em três picos de percepção de cores principais. As cores de longo comprimento de onda (long-wavelenght, com pico a 564nm, vermelho), o de médio comprimento de onda (medium-wavelenght, com pico a 534nm, verde) e o de curto comprimento de onda (short wave-lenght, com pico a 420nm, azul) (CONE..., 2006). Baseando-se nessa teoria, as células-cone podem ser classificadas em três grupos, dependendo de qual comprimento de onda elas captam preferencialmente: •
células-cone que respondem às luzes vermelhas e alaranjadas (de longo comprimento de onda), classificados como grupo R (red - vermelho);
•
células-cone que respondem às luzes verdes e amarelas (de médio comprimento de onda), classificados como grupo G (green - verde);
•
e células-cone que respondem às luzes azuis e violetas (de curto comprimento de onda), classificados como grupo B (blue - azul). As células-cone estão distribuídas de maneira desequilibrada dentro do olho humano. 94% delas pertencem aos grupos G e B, enquanto que apenas 4% são do tipo R. A presença deste terceiro grupo de células-cone pode ser relacionado à evolução, pois, apenas os primatas o possuem, os demais mamíferos, somente os dois primeiros (TEORIA..., 2006). 2.2.3. Sistemas de Cores Os sistemas de cores são métodos matemáticos abstratos que descrevem as propriedades ou comportamentos das cores num contexto particular. Neles, as cores são representadas por tuplas de números, geralmente com duas, três ou quatro componentes (COLOR MODELS..., 2006). Essas componentes são associadas às cores primárias do sistema, os quais serão explicados mais adiante. Infelizmente, pelo fato da resposta do olho humano aos estímulos espectrais não ser linear, não existe um sistema de cores que explique todos os
18
aspectos relacionados à cor. Por isso são usados sistemas de cores diferentes para propósitos diferentes. RGB, CMYK, HSV e HLS são alguns exemplos de sistemas de cores mais usados que descrevem seus respectivos universos de cores de maneira diferente entre si (TRAINA, 2006). Os sistemas de cores são geralmente formados por duas ou três cores primárias (algumas vezes com uma cor adicional), que são utilizadas para formar o domínio de todas as cores que o sistema pode descrever, que é chamado de color space (ou color gamut) (TRAINA, 2006). A mistura das máximas intensidades de duas cores primárias forma o que é chamado de cor secundária. A formação de uma cor num determinado sistema de cores se dá pela combinação de uma ou mais cores primárias em quantidades específicas ou variando sua coloração através do brilho, contraste, saturação, etc., formando assim a cor em particular. A combinação de todas as combinações possíveis de misturas de cores primárias do sistema forma o seu color space (COLOR ..., 2006). Os sistemas de cores podem ser classificados em dois grupos: os aditivos e os subtrativos. Nos aditivos, as cores primárias são consideradas como sendo focos de luz colorida, cuja soma resulta na luz branca. Um exemplo é o sistema de cores RGB (Figura 6). Já nos subtrativos, as cores são consideradas pigmentos, que, se somadas, resultam na cor preta. O sistema de cores CMYK (Figura 7) é subtrativo.
Figura 6: Sistema Aditivo RGB
Figura 7: Sistema subtrativo CMYK.
A seguir serão discutidos três sistemas de cores dos mais importantes para exemplificar a diferença básica entre eles.
19
2.2.4. O Sistema de Cores CMYK O Sistema de cores CMYK, (C - Cyan (Ciano), M - Magenta (Magenta), Y - Yellow (Amarelo) K – Back (Preto) ou Key (Chave)) é utilizado em impressoras e programas especializados. Suas cores primárias são o ciano, o magenta e o amarelo. O preto não é uma cor primária 2 , pois é gerado somando-se as que são primárias, porém ele foi adicionado ao sistema por motivos particulares, como (CMYK..., 2006): •
Na prática, a mistura de ciano, magenta e amarelo não resultam na cor preta pura, mas apenas numa cor escura, isso poderia tirar um pouco dos detalhes de figuras mais escuras;
•
Na impressão de figuras, misturar as três tintas para obter a preta, fazia com que o papel ficasse muito úmido, o que era um problema para impressoras mais velozes, pois o papel precisava estar seco para que a próxima folha não fosse manchada;
•
Textos geralmente são impressos na cor preta, e fontes com detalhes maiores (serifas 3 ), exigiam que as três imagens geradas pelo sistema fossem extremamente precisas;
•
Usar o preto ao invés de três cores para formá-lo pode significar um barateamento nos custos da impressão. Como mencionado, o sistema CMYK, como todo sistema de cores subtrativo, trata as cores como sendo pigmentos de tinta (ou as cores que a tinta não absorve). Este sistema de cores é mias utilizado na indústria gráfica, que necessita saber com precisão quais as cores que serão impressas, visto que os pigmentos de tintas das impressoras também o utilizam. Antes de uma imagem ser impressa, quatro imagens são formadas, cada uma impressa somente com uma das cores primárias. Estas imagens são chamadas de canais e estão representadas na Figura 8.
2
Apesar de a cor preta não ser uma cor primária, neste contexto ela será referenciada como uma. Pequenos traços e prolongamentos presentes em algumas letras. Por exemplo: a letra “T” sem serifa: “T” e a mesma letra com serifa: “T”.
3
20
Figura 8: Imagem dividida nos canais do Sistema CMYK. 2.2.5. O Sistema de Cores RGB O Sistema RGB (R - Red (Vermelho), G - Green (Verde), B - Blue (Azul)) é um sistema de cores aditivo baseado na teoria dos três estímulos de Young-Helmholtz (ver seção 2.2.2 Percepção Humana das Cores) de que o olho humano tem picos de percepção em três cores principais: vermelho, verde e azul, que são justamente suas cores primárias (RGB, 2006). O color space do sistema RGB pode ser representado num gráfico como sendo um cubo unitário, onde cada uma das direções do gráfico representa a intensidade de uma cor respectiva, variando de 0 a 1.
Figura 9: Cubo de cores RGB simplificado com corte central. Na Figura 9, o eixo x representa a componente vermelha do sistema de cores, y a componente verde e z a azul. Cada um dos vértices do cubo representa uma cor primária, secundária, branco ou preto, como representado na tabela 1. As arestas do cubo mostram as escalas entre as cores dos respectivos vértices que as formam. A diagonal que une os vértice (0, 0, 0) e (1, 1, 1) no cubo forma a escala de cinza.
21
tabela 1: Vértices do cubo de cores RGB Vértice (x, y, z) Cor Tipo da cor 0, 0, 0 Preto 1, 0, 0 Vermelho Primária 0, 1, 0 Verde Primária 0, 0, 1 Azul Primária 1, 1, 0 Amarelo Secundária 1, 0, 1 Magenta Secundária 0, 1, 1 Ciano Secundária 1, 1, 1 Branco Este sistema é o utilizado na fabricação de monitores de computador e de televisão, não importando qual a tecnologia (CRT 4 , LCD 5 ou plasma 6 ). Cada um dos pixels 7 é mapeado com um determinada cor RGB, o que forma a imagem da tela. RGB e CMYK formam a dupla de sistemas de cores mais utilizadas atualmente para propósitos gerais. Uma propriedade interessante entre o RGB e o CMYK é o fato de que as cores primárias num sistema são secundárias no outro. Por exemplo, misturando-se as cores vermelho e azul, primárias no RGB, obtém-se o magenta, cor primária no CMYK (Figura 6). O mesmo ocorre quando misturadas as cores amarela e ciano no CMYK (Figura 7), resultando no verde. Da mesma maneira que no Sistema CMYK, as imagens no Sistema RGB podem ser subdivididas em canais de cores primárias, é o que mostra a Figura 10.
Figura 10: Imagem dividida nos canais do Sistema RGB.
4
CRT - Cathode Ray Tube (Tubo de Raios Catódicos): Tecnologia de fabricação de monitores mais antiga, porém ainda muito utilizada. Consiste de um tubo de vidro com um canhão na parte traseira que atira elétrons numa tela de fósforo localizada na parte fronteira do tubo onde as imagens são exibidas [P2]. 5 LCD - Liquid Crystal Display (Tela de Cristal Líquido): Tecnologia recente de fabricação de monitores em que a imagem do dispositivo é projetada em um cristal líquido. 6 Plasma: Tecnologia recente de fabricação de monitores, em que a imagem é projetada num líquido gelatinoso. 7 Pixel: unidade mínima de uma imagem em um monitor.
22
2.2.6. Os Sistemas de Cores HSV e HLS Além dos Sistemas RGB e CMYK que têm suas definições voltadas para o uso técnico, existem outros sistemas que utilizam conceitos mais intuitivos que a mistura de cores para sua definição de color space. Os Sistemas HSV/HSB (Hue - Matiz, Saturation - Saturação, Value/Brightness - Valor/Brilho) (HSV..., 2006) e HLS (Hue - Matiz, Lightness Luminosidade, Saturation - Saturação) (HLS..., 2006) são exemplos deste grupo de Sistemas de cores. Como não utilizam combinações de cores, não podem ser classificados nem como aditivos nem como subtrativos. O Sistema HSV é formado pelas três componentes (HSV..., 2006): •
Hue (Matiz): é a cor (comprimento de onda) predominante (HUE..., 2006);
•
Saturation (Saturação): também conhecida como pureza, é a vivacidade da cor. Uma cor com muita saturação parece mais "viva", ou pura. Com pouca saturação, a cor fica acinzentada (SATURATION..., 2006);
•
Value/Brightness (Valor/Brilho): a luminosidade em uma cor, basicamente a quantidade de branco e preto adicionados à cor. Essas componentes e suas variações podem ser representadas em um cone, onde sua base representa a variação da matiz, a distância da cor do centro do cone é a saturação e a altura é o brilho, como mostra a Figura 11.
Figura 11: Cone de cores do Sistema HSV. O Sistema HLS trabalha como o HSV e especifica suas cores nas componentes Hue (Matiz), Lightness (Luminosidade) e Saturation (Saturação) e pode ser representado como o duplo cone (HLS..., 2006) mostrado na Figura 12. O ângulo em relação ao eixo central determina a matiz, o eixo vertical corresponde à luminosidade e a saturação é determinada pela distância da cor do centro (TRAINA, 2006).
23
Figura 12: Duplo cone de cores do Sistema HLS. Os Sistemas HSV e HLS permitem que se pense em cores mais "claras" ou mais "escuras", simplesmente variando sua saturação, brilho ou luminosidade (TRAINA, 2006).
24
3. ASPECTOS COMPUTACIONAIS 3.1. A BIBLIOTECA GRÁFICA OPENGL A
biblioteca
gráfica
OpenGL
é
uma
API
própria
para
o
desenvolvimento de aplicações gráficas altamente portável e rápida. Ela trabalha entre o hardware e a aplicação provendo uma interface entre eles. Possui uma gama bastante variada de funções de alto e baixo nível que incorporam todas as funcionalidades básicas de qualquer placa gráfica moderna. A OpenGL foi criada pela Silicon Graphics, Inc. (SGI) e hoje é mantida por diversas empresas que formam a OpenGL Arquitechture Review Board (ARB), cujos fundadores são a SGI, a Digital Equipment Corporation, IBM, Intel e Microsoft. A OpenGL foi escolhida como base deste trabalho devido a sua versatilidade, robustez e por estar sendo muito utilizada na área de jogos eletrônicos, o foco deste trabalho. Há muito que aprender sobre OpenGL, porém, as explicações aqui contidas, limitar-se-ão ao simples entendimento do escopo deste trabalho. 3.1.1. Formação dos Comandos em OpenGL Algo que se pode notar desde os primeiros comandos que são vistos em OpenGL é uma padronização na nomenclatura dos comandos. Tal nomenclatura não é somente utilizada pela OpenGL, mas seguida por suas extensões
e
bibliotecas auxiliares como a GLU e a GLUT. A formação dos comandos é feita da seguinte maneira: <prefixo gl> <nome da função> , como mostrado a seguir, onde temos a função glVertex, que desenha um vértice numa posição especificada pelos seus parâmetros:
25
gl Vertex 3 f v prefixo 'gl' proveniente do nome da biblioteca nome da função quantidade de parâmetros que a função aceita tipo dos parâmetros indica vetor de parâmetros Figura 13: Estrutura de um comando de OpenGL. Onde o tipo dos parâmetros pode ser ‘f’ para o tipo float, ‘d’, para double, ‘i’ para int ou ‘s’ para short. O sufixo ‘v’ indica que o parâmetro passado é um vetor de variáveis do tipo e tamanho especificado no nome da função. 3.1.2. Máquina de Estados Uma importante informação é que a OpenGL pode ser associada a uma máquina de estados, por isso, primeiramente, configura-se os estados em que ela deve estar e depois se renderizam (ou desenham) as cenas nos devidos estados, conseguindo assim, a cena desejada. Outra
propriedade
importante
é
que
OpenGL
trabalha
completamente em cima de matrizes e de teorias da álgebra que as definem. No exemplo a seguir, podemos ver a utilização do salvamento dos estados atuais da matriz de renderização e a impressão de um triângulo deslocado: // uma das funções de salvamento de estado glPushMatrix(); // mudança de estado: toda renderização feita a partir deste comando // era feita em relação ao ponto (5, 5, 0) glTranslatef (5.f, 5.f, 0.f); // mudança de estado: a partir deste comando, a cada três vértices // fornecidos para serem renderizados, um triângulo será formado glBegin(GL_TRIANGLES); // mudança de estado: todos os vértices desenhados terão // a partir deste comando a cor branca (1.f, 1.f, 1.f) glColor3f (1.f, 1.f, 1.f);
26
glVertex3f (0.f, 0.f, 0.f);
// desenha um vértice
glVertex3f (1.f, 1.f, 0.f); glVertex3f (0.f, 1.f, 0.f); glEnd();
// sai do estado de desenho
glPopMatrix();
// retorna ao estado antes de glPushMatrix()
Neste fragmento de código, o que vai acontecer é que ao invés do triângulo ser desenhado nas coordenadas (0, 0, 0), (1, 1., 0), (0, 1, 0), ele será desenhado em (5, 5, 0), (6, 6, 0), (0, 6, 0) por causa do comando glTranslatef(), que configura os estados da OpenGL para desenhar com referência ao ponto passado por parâmetro, no caso (5, 5, 0). 3.2. LUZES E MATERIAIS Quando olhamos para um ponto em um objeto, a cor que vemos é resultado de múltiplas interações entre a fonte de luz e todas as superfícies reflexivas ao seu redor. Essas interações podem ser vistas num processo recursivo. Por exemplo, considere a Figura 14. A fonte emite luz na direção dos objetos A e B. Parte da luz que alcança o objeto A é refletida. Parte desta luz refletida alcança o objeto B, que, por sua vez, também reflete parte desta luz e da proveniente da fonte, que alcança o objeto A e assim por diante.
Figura 14: Superfícies reflexivas. Matematicamente, processos recursivos resultam em integrais, neste caso, gera a chamada equação da renderização. Infelizmente, esta equação não pode ser resolvida analiticamente e métodos numéricos não são rápidos o suficiente para cálculos em tempo real. Há vários outros métodos para aproximação do resultado, como os métodos ray tracing e radiosity (ANGEL, 2006), métodos bastante complexos, mas que apresentam uma aproximação excelente com os resultados esperados. Um dos mais simples, eficientes e eficazes é o método
27
baseado no modelo de reflexão de Phong 8 (ANGEL, 2006), que apresenta resultados satisfatórios. Ao invés de olharmos o problema com uma perspectiva global (como é feito nos modelos ray tracing e radiosity), nós seguiremos os raios provenientes de uma fonte de luz e modelaremos o que acontece localmente com estes raios quando eles interceptam superfícies reflexivas. Este funcionamento é parecido com o do ray tracing, mas ao invés de computarmos todas as interações recursivamente, calculase apenas a interações feitas entre os raios da fonte de luz e o objeto. Este
método
é
dividido
em
duas
partes
independentes:
primeiramente devemos modelar as fontes de luz da cena e depois construir o modelo de reflexão de acordo com as interações entre os materiais de que são feitas as superfícies e a luz. Começamos acompanhando um raio de luz que sai da fonte e chega aos olhos do observador como mostra a Figura 15. Se o raio atinge os olhos do observador diretamente da fonte de luz, então ele vê a cor da fonte. Se o raio atinge uma superfície visível pelo observador, então ele vê a cor resultante da interação entre a cor da luz e o material de que é feita a superfície (ANGEL, 2006).
Figura 15: Luz incidente nas superfícies. Computacionalmente, o observador é substituído pelo chamado plano de projeção (projection plane), um retângulo que compreende a tela do monitor e determina o que é visível ou não dentro da cena, como mostra a Figura 16.
8
Bui Tuong Phong, em sua dissertação Illumination for Computer Generated Pictures (Iluminação para Figuras Geradas por Computador) de 1973, descreve seu modelo de reflexão (Phong reflection model) e de sombreamento (Phong shadding), modelos muito utilizados no campo da computação gráfica.
28
Figura 16: Luz incidente nas superfícies formando uma imagem de computador. Precisamos considerar apenas os raios que saem da fonte e atingem os olhos do observador, tanto diretamente quanto indiretamente (interagindo com superfícies). No caso do computador, são excluídos ainda os raios que estão fora do alcance do retângulo que forma o plano de projeção. Isso desconsidera grande parte dos cálculos para a iluminação (ANGEL, 2006). Quando raios de luz atingem uma superfície, parte destes raios é refletida e parte é absorvida, como discutido na Seção 2.1. Se uma superfície é opaca, todos os raios são refletidos ou absorvidos. Caso ela seja translúcida, parte dos raios a atravessa e emerge para interação com outros objetos. Esta interação depende do comprimento de onda dos raios que atravessaram a superfície. Além disso, uma superfície iluminada por luz branca parece vermelha (por exemplo) por absorver todas as luzes que incidem nela exceto as de comprimento de onda perto da cor vermelha. As interações luz-material podem ser classificadas em três grupos básicos segundo as superfícies em que as luzes incidem, como mostra a Figura 17 (ANGEL, 2006): •
Superfícies especulares (specular surfaces): estas parecem brilhantes por que a maior parte dos raios de luz é refletida em ângulos muito próximos do ângulo de reflexão. Espelhos são superfícies perfeitamente especulares, pois todos os raios de luz são refletidos no mesmo ângulo (o ângulo de reflexão);
•
Superfícies difusas (diffuse surfaces): são superfícies que refletem para todos os lados os raios que incidem sobre elas. Superfícies perfeitamente difusas refletem as luzes igualmente em todas as direções;
29
•
Superfícies translúcidas (translucent surfaces): permitem que alguns raios de luz as penetrem e reapareçam em outros pontos no objeto. Exemplos destas superfícies são a água e o vidros. Parte da luz também pode ser refletida.
Figura 17: Interações luz-material. (a) Superfície especular. (b) Superfície difusa. (c) Superfície translúcida. 3.3. FONTES DE LUZ A luz pode sair de uma superfície de duas maneiras: por emissão própria ou reflexão. Uma fonte de luz não apenas emite luz, mas também reflete a luz que incide sobre sua superfície. Considere por exemplo a Figura 18, onde é mostrada uma lâmpada incandescente como uma fonte de luz. Cada um dos pontos (x, y, z) da superfície da lâmpada pode emitir luz que é caracterizada pela direção da emissão (θ, Φ) e a intensidade λ. Portanto, a iluminação do ponto pode ser descrita em uma função de seis variáveis I(x, y, z, θ, Φ, λ). Da perspectiva de uma superfície sendo iluminada por esta fonte de luz, obtém-se a contribuição total da fonte de luz integrando cada um dos pontos da fonte com suas respectivas funções de iluminação e distância de cada um dos pontos da superfície iluminada. Essa integração é bastante dispendiosa e difícil tanto com métodos analíticos quanto com métodos numéricos. Ao invés disso, é mais fácil modelar as fontes de luz como polígonos, cada um deles trabalhando como uma pequena fonte.
Figura 18: Uma fonte de luz.
30
Quatro tipos básicos de iluminação são considerados: iluminação ambiente (ambient light), fontes pontuais (point sources), holofotes (spotlights) e luzes distantes (distant lights). Estes tipos básicos são suficientes para a maioria das aplicações. Em OpenGL todos estes tipos de luz são possíveis (ANGEL, 2006). 3.3.1. Fontes de Cores As fontes de luz não apenas emitem quantidades de luz em diferentes freqüências, mas a direção dos raios pode variar de acordo com essas freqüências também. Isso pode gerar cálculos bastante complexos se é desejado um modelo fisicamente perfeito. Entretanto, a percepção visual humana é baseada em três estímulos (ver Seção 2.2.2), três cores primárias que podem descrever uma grande parte das luzes visíveis: vermelho, verde e azul (sistema RGB). Descrevemos a luz então como sendo uma combinação de quantidades destas três cores. Portanto a matriz de intensidade de cor, em OpenGL pode ser expressa como a matriz:
Ir I = Ig Ib Cada
uma
destas
componentes
representa
a
quantidade
independente de cada uma das cores que forma a luz em questão. 3.3.2. Luz Ambiente A luz ambiente pode ser descrita como sendo uma luz que incide igualmente em todas as superfícies de uma cena e reflete de maneira homogênea em todas as direções. Uma simulação deste tipo de iluminação poderia ser criada, distribuindo fontes de luz por toda a cena e integrando a iluminação de cada fonte com cada uma das superfícies da cena. Porém isso teria um custo computacional muito grande, o que deixaria inviável esse tipo de iluminação para cenas renderizadas em tempo real. Ao invés disso, podemos inserir uma luz que age uniformemente sobre todos os pontos da cena. Representando a intensidade da luz ambiente como Ia, podemos descrevê-la em OpenGL como sendo a matriz:
31
I ar Ia = Iag Iab Para simplificação na denotação de funções matemáticas, usaremos Ia para representar qualquer componente da matriz Ia. 3.3.3. Fontes Pontuais Uma fonte pontual é uma fonte sem espessura, largura ou altura que emite luz para todas as direções. Uma fonte pontual localizada na posição P0 é caracterizada pela matriz:
I r (P0 ) I(P0 ) = Ig (P0 ) Ib(P0 ) A intensidade de iluminação recebida por uma fonte pontual é o inverso do quadrado da distância entre o ponto luminoso e o ponto iluminado. Portanto, num ponto arbitrário P de uma superfície, a intensidade de iluminação pode ser calculada através da matriz formada por:
i(P, P0 ) =
1 I(P0 ) 2 |P - P0 |
Como feito com a luz ambiente, usaremos I(P0) para representar qualquer componente da matriz I(P0). O uso de pontos de luz na maioria das aplicações é devido a sua facilidade de uso e não por sua proximidade com a luz real. Cenas que possuem apenas pontos de luz tender a ter um alto contraste, distinguindo-se bem áreas claras de áreas escuras. Cenas reais possuem escalas de cores mais complexas. Para amenizar esse problema, pode-se utilizar de luzes ambientes, diminuindo o contraste. Na prática, ao invés de se utilizar o inverso do quadrado da distância dos pontos, para melhor aproximação com cenas reais, utiliza-se (a + bd + cd2)-1, onde d é a distância entre os pontos luminoso e iluminado e as constantes a, b e c podem ser escolhidos para suavizar a iluminação.
32
3.3.4. Holofotes (Spotlights) Holofotes ou spotlights são caracterizados por possuírem apenas um pequeno ângulo por onde a luz é emitida. Um simples holofote é conseguido facilmente limitando-se os raios emitidos por uma fonte pontual a um determinado ângulo. Para representar um holofote, podemos usar um cone com seu ápice em Ps (o ponto onde a luz é emitida) apontando para uma direção ls e com sua largura definida pelo ângulo θ formado entre o centro e um lado do cone, como mostra a Figura 19. Se o ângulo θ é 180°, o holofote se torna uma fonte de luz pontual.
Figura 19: Holofote (spotlight). Holofotes mais realistas possuem uma distribuição disforme da luz, geralmente com o centro do cone mais luminoso que suas bordas. Portanto, a intensidade pode ser descrita em função do ângulo Φ formado entre a direção l da luz (o centro do cone) e o vetor s, formado entre o ponto luminoso e um ponto iluminado da superfície. Quanto mais próximo de zero este ângulo, maior a intensidade de iluminação, como mostra a Figura 20. intensidade
−θ
φ
θ
Figura 20: Atenuação de um holofote. Apesar de esta função poder ser definida de várias maneiras, é usualmente implementada como coseΦ. Onde o expoente e determina quão rapidamente a luminosidade do holofote se dispersa do centro para as bordas (Figura 21).
33
intensidade
−θ
φ
θ
Figura 21: Expoente do holofote. 3.3.5. Fontes Distantes de Luz Quando calculamos a intensidade da luminosidade sobre uma superfície, levamos em consideração a direção dos raios de luz que incidem sobre cada ponto dela. Durante a renderização, tudo deve ser calculado para cada ponto repetidamente. Uma computação que representa uma parte significativa da modelagem de iluminação. Porém, se a fonte está distante da superfície, a direção da luz não muda muito em pontos próximos. Como mostra a Figura 22, o ponto de luz, que está distante da superfície, foi transformado em um feixe de raios paralelos, ou uma fonte paralela (parallel source).
Figura 22: Luz distante incidindo paralelamente em uma superfície. Na prática, o cálculo para fontes distantes é similar a projeções paralelas, substitui-se a localização da fonte de luz pela direção da mesma. Assim, em coordenadas homogêneas, um ponto de luz na posição P0 é representado internamente como a matriz coluna de quatro dimensões:
x y P0 = z 0 Os cálculos para as luzes distantes são muito mais simples e rápidos do que para luzes próximas ou com distâncias relevantes. Porém, as cenas renderizadas nos dois métodos são diferentes.
34
3.4. MODELO DE REFLEXÃO DE PHONG (PHONG REFLECTION MODEL) Embora possamos aproximar as interações entre iluminação e materiais através de complexos modelos físicos, o método que será estudado aqui será mais simples, porém satisfatório para a maioria das aplicações, pois une uma boa proximidade dos métodos físicos e eficiência computacional. O modelo em questão é o introduzido por Bui Tuong Phong, em sua dissertação Illumination for Computer Generated Pictures (Iluminação para Figuras Geradas por Computador) em 1973 e mais tarde modificado por James F. Blinn. O modelo de Phong (o modelo de Phong-Blinn foi escolhido por ser o padrão das renderizações de iluminação efetuadas pela biblioteca OpenGL) utiliza os quatro vetores mostrados na Figura 23 para calcular a cor para cada um dos vértices de uma superfície. Na figura, P é o ponto que se deseja calcular a cor, n é o vetor normal no ponto P, v é a direção do observador em relação a P, l a direção do ponto de luz (ou um ponto arbitrário da fonte de luz) e r é a direção onde o raio que incide de l reflete perfeitamente.
Figura 23: Os vetores utilizados no modelo de Phong. O modelo de Phong suporta os três tipos de interação luz-material: ambiente, difusa e especular. Supondo que temos um grupo de pontos de luz, cada um destes pontos pode possuir separadamente componentes ambiente, difusa e especular para cada uma das três cores primárias (RGB). Precisamos, portanto, de uma matriz que caracterize estes nove temos para cada ponto P de uma superfície, que pode ser definida como a matriz 3x3 a seguir, para o i-ésimo ponto de luz:
L ira L iga L iba L i = L ird L igd L ibd L irs L igs L ibs
35
A primeira linha da matriz especifica as intensidades de vermelho (r), verde (g) e azul (b) para a componente ambiente (a) da fonte de luz i. A segunda especifica as intensidades para a componente difusa (d) e a terceira para a componente especular (s). Na construção do modelo, foi assumido que é possível se calcular o quanto dos raios de luz incidente são refletidos no ponto P em questão, ou seja, para a cor vermelha da componente difusa da fonte de luz i, Lird, é possível se encontrar o termo de reflexão Rird. O termo Rird depende das propriedades do material, da orientação da superfície, da direção da luz e da distância entre o observador e a fonte de luz. Com isso, é construída uma matriz de nove elementos semelhante à anterior, a matriz de reflexão:
Rira Riga Riba Ri = Rird Rigd Ribd Rirs Rigs Ribs Podemos então calcular a contribuição de cada fonte de cor adicionando as componentes ambiente, difusa e especular. Por exemplo, a intensidade de cor azul que se pode ver no ponto P proveniente da fonte de luz i é:
Iib = Liba Riba
+
Libd Ribd
+
Libs Ribs
= I iba + I ibd + I ibs Para obtermos a contribuição total da cor azul proveniente de todos os pontos de luz na cena sobre um ponto P numa superfície, inclusive da luz ambiente, calculamos:
Ib =
∑ ( Iiba + Iibd + Iibs ) + Iab i
Onde Iab é a cor azul proveniente da luz ambiente. Podemos simplificar a notação se repararmos que estes cálculos são os mesmos para cada uma das cores primárias. Elas se diferenciam apenas quando estamos tratando das componentes ambiente, difusa e especular, possibilitando a omissão das letras r, g e b.
I = Ia + Id + Is = La Ra + Ld Rd + Ls Rs
36
Como este cálculo será feito para todas as cores primárias e para todas as fontes de luz, o termo ambiente pode ser adicionado no final. 3.4.1. Reflexão Ambiente A intensidade da luz ambiente La é uniforme e aplicada sobre todos os pontos da cena. Parte desta luz é absorvida e parte refletida. A parte refletida é dada pelo coeficiente de reflexão do ambiente Ra = ka, pois é constante. Segue então que:
Ia = ka La Onde La pode ser a luminosidade de uma fonte de luz qualquer na cena ou pode o ser o termo global de iluminação ambiente. Lembrando as superfícies possuem os três coeficientes para a componente ambiente: kar, kag e kab. 3.4.2. Reflexão Difusa Uma superfície apresenta reflexão perfeitamente difusa quando ela reflete raios de luz para todos os lados de maneira uniforme, tanto que a iluminação parece a mesma de todos os ângulos em que pode ser vista. Entretanto, a grau de reflexão difusa de um ponto depende tanto do material (já que ele determina quanto da luz será absorvida) quanto da posição da fonte de luz em relação à superfície. Reflexões difusas são caracterizadas por superfícies irregulares, como a mostrada na Figura 24, que representa uma ampliação de um pedaço de uma superfície irregular. Superfícies que apresentam reflexão perfeitamente difusa são tão irregulares que não possuem um ângulo predominante de reflexão. Tais superfícies são chamadas de superfícies Lambetianas (Lambertian surfaces) por poderem ser modeladas matematicamente através da lei de Lambert.
Figura 24: Ampliação de uma superfície difusa.
37
Considere a superfície difusa da Figura 25 iluminada pelo sol. Quando os raios solares a atingem ao meio-dia ela parece mais clara que quando ela é iluminada por ele à tarde (ou de manhã). Isso ocorre, segundo a lei de Lambert, devido aos olhos humanos enxergarem apenas a componente vertical da luz incidente. Uma maneira de entender esta lei é observando a Figura 26. Quando uma área d de raios de solares ilumina uma superfície ao meio dia, uma área d da superfície é coberta por estes raios. Durante a tarde, a mesma área d dos raios solares cobre uma área maior.
Figura 25: Luz do sol incidindo sobre uma superfície. Figura 26: Lei de Lambert. A lei de Lambert é definida como:
Rd α cosθ Onde α é o coeficiente de reflexão do material da superfície e θ é o ângulo entre a normal n do ponto em questão e o vetor l da direção da fonte de luz. Se n e l forem vetores normalizados, então o co-seno de θ pode ser expresso como sendo o produto interno entre l e n:
cosθ = l . n Adicionando o coeficiente de reflexão kd (coeficiente de reflexão difusa), que representa a fração de raios a serem refletidos (dependente do material), temos a componente de reflexão difusa:
Id = kd (l . n) Ld Se ainda quisermos incorporar a distância d percorrida pelos raios de luz até a superfície, teremos:
Id =
kd (l . n) Ld a + bd + cd 2
38
Um problema ocorre quando há uma fonte de luz abaixo da linha do horizonte (θ > 180°), o que não é interessante. Na prática, é usado zero ao invés de valores negativos, resultando finalmente em:
Id =
kd max(0, (l . n) Ld) a + bd + cd 2
3.4.3. Reflexão Especular Se em uma cena empregarmos apenas luzes difusas e ambientes, teremos uma cena com aspecto 3D e sombreamento, porém, todos os objetos parecerão foscos. Faltará o brilho desenhado nas superfícies lisas que geralmente possui uma cor diferente da refletida pela luz ambiente e difusa. Este brilho é resultado da reflexão especular. Ao contrário das superfícies difusas, que são irregulares, superfícies especulares são lisas como mostra a Figura 27, uma ampliação de um pedaço de uma superfície especular. Estas superfícies são caracterizadas por refletirem a luz incidente em uma variação muito pequena de ângulos. Quanto mais lisa a superfície, menor a variação angular de reflexão e mais próximo de um espelho (ou superfície perfeitamente especular) ela fica.
Figura 27: Ampliação de uma superfície especular. Modelagem muito próxima de reflexão especular real pode ser um tanto complexa, pois, os raios refletidos pela superfície não são simétricos. Tudo depende do comprimento de onda da luz incidente, o que pode mudar também com o ângulo de reflexão. Phong propôs um modelo de aproximação que é um pequeno acréscimo ao trabalho desenvolvido pelo cálculo da luz difusa. Isto é, ele considerou que a luz é refletida de maneira difusa e especular ao mesmo tempo. A quantidade de luz que o observador vê depende do ângulo Φ entre o vetor r que especifica onde a reflexão é perfeita e v, a direção do observador.
39
Is = ks Ls cos αφ O coeficiente ks (0 ≤ ks ≤ 1) é a fração da luz incidente que é refletida. O expoente α representa o coeficiente de brilho. O gráfico da Figura 28 mostra o que acontece com o alcance do brilho quando se incrementa α. No limite, α tende ao infinito. Temos então um espelho. Com α entre 100 e 500 temos superfícies metálicas e com α < 100, superfícies com um brilho amplo e pouco acentuado.
α=1 α=2 α=5
Figura 28: Efeito do coeficiente de brilho. A vantagem computacional do método de Phong ocorre no caso de os vetores r e v estarem normalizados (ANGEL, 2006), assim, podemos usar o produto interno:
Is = ks Ls max((r . v)α , 0) Podemos mais uma vez incorporar a distância da fonte de luz da superfície, resultando em:
Id =
1 (kd Ld max(l . n, 0) + ks Ls max((r . v)α , 0)) + ka La a + bd + cd 2
Sendo esta fórmula computada para todas as fontes de luz e todas as cores primárias. Um artifício utilizado é associar valores diferentes para as componentes de cada uma das fontes de luz para tornar a cena um pouco mais próxima da real. Isso porque, como não conseguimos resolver a equação da renderização (Seção 3.2) por completo, é necessário que se encontrem alternativas que contornem este problema. Considere, por exemplo, uma cena iluminada com muitos objetos. Quando a luz incide diretamente sobre um objeto, ela é refletida e podemos modelar esse fenômeno através das componentes difusa e especular da fonte. Entretanto,
40
grande parte da luz restante é refletida por outros objetos na cena, o que contribui com a iluminação recebida pelo objeto em questão. Podemos aproximar este termo tendo uma componente ambiente associada à fonte. A quantidade de luz que será associada a este termo depende tanto da cor da fonte quanto da cor dos objetos na cena. Porém, o problema está em tentar calcular iluminação global através de renderizações locais. 3.4.4. O Modelo de Phong Modificado (Modelo Blinn-Phong) Se utilizamos o modelo de Phong para renderizar reflexões especulares, o produto interno (r . v) deve ser recalculado para cada ponto na superfície. Podemos obter uma aproximação relevante deste produto usando um vetor normalizado na metade do caminho (halfway) entre o vetor v (a direção do observador) e o vetor l (a direção da fonte de luz) (ANGLE, 2006).
h=
l+v |l + v|
A Figura 29 mostra todos os cinco vetores. Aqui, o ângulo entre o vetor h (halfway) e a normal n é ψ. Quando v está no mesmo plano que l, n e r, obtemos:
2ψ = Φ Se substituirmos (r . v) por (n . h), deixamos de calcular r, o que já representa um ganho computacional. Entretanto, o ângulo ψ é menor que Φ, e se usarmos o mesmo expoente e em (n . h)e que usamos em (r . v)e, então o tamanho do brilho especular será menor. Para sanar este problema, podemos usar um expoente e' para aproximar (n . h)e' de (r . v)e.
Figura 29: Determinação do vetor h (halfway vector).
41
Esta modificação do modelo de Phong foi proposta por James F. Blinn e o modelo completo é chamado de modelo Blinn-Phong ou Phong modificado. Este modelo é o padrão de renderização de iluminação usado em OpenGL. 3.5. SOMBREAMENTO POLIGONAL (POLYGONAL SHADING) Em OpenGL ou em muitos outros sistemas gráficos, todas as superfícies são modeladas baseadas em polígonos. Isso facilita os cálculos para as placas gráficas e faz com que um maior número de superfícies complexas possam ser renderizadas. Assumindo que é possível se encontrar o vetor normal a partir de um conjunto de fontes de luz e um observador, os modelos de iluminação então podem ser aplicados para cada um dos pontos que formam uma superfície. Infelizmente, mesmo com os cálculos mais simples, a complexidade computacional para esses cálculos é bastante grande. A grande vantagem surge quando temos uma superfície plana, onde podemos ter uma vantagem muito significativa computacionalmente. Para isso podemos tirar vantagem da renderização em polígonos, onde uma superfície complexa pode ser dividida em vários polígonos planos, como mostra a Figura 30.
Figura 30: Uma superfície dividida em polígonos. Consideramos três maneiras de efetuar o sombreamento poligonal: sombreamento plano (flat shading), sombreamento suave (smooth) ou Gouraund e sombreamento Phong (Phong shading) (ANGEL, 2006).
42
3.5.1. Sombreamento Plano (Flat Shading) Para cada um dos pontos de uma superfície, é necessário se calcular os vetores l, n, e v. No entanto, em superfícies planas, n é constante. Se considerarmos que temos uma fonte de luz distante e um observador distante, podemos assumir que l e v também são constantes. Aqui podemos interpretar que a fonte de luz está no infinito, substituindo a distância da luz simplesmente pela direção da mesma. A distância também pode ser interpretada em termos do tamanho do polígono relativo a quão longe o observador está dele. Se todos os vetores são constantes, precisamos calcular o sombreamento apenas uma vez por polígono da face. Esta técnica é conhecida como Flat (ou Constant) Shading – Sombreamento Plano (ou Constante). Em OpenGL, não é padrão este tipo de renderização de sombreamento, porém é possível
se
renderizar
com
flat
shading,
basta
especificar
ao
comando
glShadeModel (que muda os estados da máquina para o modo de como será feita a renderização do sombreamento) que se deseja o modo flat: glShadeModel(GL_FLAT); Se o flat shading está ativo, então a OpenGL usará a normal do primeiro vértice para calcular o sombreamento de toda uma face.
Figura 31: Flat shading aplicado a uma superfície. Apesar de ser mais rápido e simples, o flat shading apresenta um problema: se a luz e o observador estiverem próximos da superfície, então os vetores l e v terão de ser recalculados para cada um dos polígonos. Se a superfície for projetada para ser suave, então será possível ver uma pequena diferença no sombreamento entre polígonos adjacentes, como mostra a Figura 31. Isso acontece
43
por que o olho humano percebe a diferença de padrões que estavam sendo mantidos e são mudados repentinamente, como mostra a Figura 32.
Figura 32: Faixas Mach (Mach bands). O que vemos são tiras que são chamadas de Mach bands (Mach em referência às barreiras da velocidade do som), um efeito que desejamos que não aconteça. 3.5.2. Sombreamento Suave/Gouraud (Smooth/Gouraud Shading) Quando associamos cores diferentes para vértices em uma mesma face de um polígono, a OpenGL interpola as cores. Se configurarmos o modelo de sombreamento para ser suave através do comando: glShadeModel(GL_SMOOTH) então a OpenGL interpolará não somente as cores das faces, mas também as cores dos vértices e arestas. O cálculo da iluminação é feito para cada vértice utilizando as propriedades do material e os vetores v e l. Se a fonte de luz estiver distante, e o observador estiver distante ou não houver reflexões especulares, então a interpolação das cores será constante. Consideremos um vértice que ajuda a formar polígonos no interior de uma superfície. Cada um destes polígonos possui sua normal. Por causa disso, a normal do vértice em questão será descontínua. Isso pode causar complicações matemáticas. Gouraund 9 propôs que a normal de um vértice pode ser calculada para manter a suavidade de uma superfície.
9
Henri Gouraud: cientista da computação francês, ph.D pela universidade de Utah em 1971.
44
n n1
n2 n3
n4
Figura 33: Normais dos polígonos e do vértice central segundo Gouraud. Considere a Figura 33, onde quatro polígonos se encontram em um vértice. Cada polígono possui a sua normal. No método de Gouraud, consideramos que a normal do vértice central é um vetor normalizado da soma das normais dos polígonos adjacentes (ANGEL, 2006).
n=
n1 + n 2 + n3 + n 4 |n1 + n 2 + n3 + n 4 |
Da perspectiva da OpenGL, Gouraud shading é muito simples. Basta que calculemos corretamente as normais dos vértices. O resultado pode ser visto na Figura 34, uma significante melhoria em relação à Figura 31.
Figura 34: Gourauge Shading. 3.5.3. Sombreamento de Phong (Phong Shading) Mesmo a suavidade proporcionada pelo sombreamento de Gouraud, o efeito de Mach bands ainda pode surgir. Phong propôs que ao invés de utilizarmos apenas a normal do vértice de encontro entre polígonos, são adicionadas outras normais nas arestas de encontro de polígonos. Normais que podem ser encontradas segundo um cálculo chamado de interpolação bilinear.
45
3.6. SOMBRAS Sombras são um importante método para adicionar realismo à cena. Portanto, se é desejado um nível aceitável de realismo, sombras são essenciais. Como discutido no capítulo 2.1.4, a sombra é formada pela umbra e pela penumbra, a umbra sendo a silhueta mais escura e a penumbra formando a região de transição entre a umbra e a região iluminada. Fontes pontuais não formam penumbra, pois, como dito no capítulo 3.3.3 elas formam imagens de alto contraste. A luminosidade da sombra varia em função da geometria da fonte de luz e do objeto que está sendo iluminado. Quanto mais complexo um objeto e uma fonte de luz são, mais complexas as sombras geradas podem ser. Infelizmente, a OpenGL não suporta sombras nativamente, porém, existem diversos métodos para implementá-las. Estes métodos variam na dificuldade de implementação, na performance e na qualidade dos resultados obtidos, que, por sua vez estão relacionados com a complexidade dos objetos a serem iluminados e da região onde serão projetadas as sombras. Para a produção de sombras, utiliza-se um artifício da OpenGL chamado buffer. As buffers da OpenGL trabalham como sendo um mapa de pixels base para as cenas a serem renderizadas. A color buffer, por exemplo, armazena todas as cores utilizadas para cada pixel na cena. Já a depth buffer armazena as distâncias entre cada pixel da cena e o observador. Para sombras, utilizamos a stencil buffer, que é especializada em bloquear partes da cena, limitando a visão do observador. 3.6.1. Sombras Projetadas (Projective Shadows) Um dos métodos mais simples de implementar é o método de sombras projetadas. Ele consiste em redesenhar o objeto por completo e escurecido na superfície onde a sombra será projetada na direção inversa da fonte de luz. O funcionamento básico deste método consiste em (HAWKINS, 2001): 1. Renderizar a cena, incluindo o objeto que formará a sombra.
46
2. Fazer com que as renderizações aconteçam apenas nos eixos x e z. Em OpenGL isso é possível através da função glScalef (xscale, yscale, zscale): glScalef(1.f, 0.f, 1.f); Isso diz à OpenGL que todas as renderizações a partir daqui serão feitas com a escala normal tanto no eixo x, quanto no z, porém todos os pontos indicados para serem renderizados no eixo y serão escalonados para zero. 3. Configurar os estados de posição e coloração da OpenGL. 4. Desenhar a sombra. No último passo, o objeto base será redesenhado, mas agora, com a OpenGL nos estados configurados, o que resultará na sombra fiel à ele. Podemos também automatizar boa parte deste procedimento criando a chamada matriz de projeção de sombra, que, multiplicada a todos os vértices do objeto, resulta no mesmo projetado sobre um plano. Essa matriz depende da posição da fonte de luz e do plano onde a sombra será projetada. Uma série de derivações matemáticas seriam necessárias para a criação desta matriz, porém, apenas o resultado será mostrado: dot - lightPos[0] * plane.a - lightPos[0] * plane.b M= - lightPos[0] * plane.c - lightPos[0] * plane.d
- lightPos[1] * plane.a dot - lightPos[1] * plane.b - lightPos[1] * plane.c - lightPos[1] * plane.d
- lightPos[2] * plane.a - lightPos[2] * plane.b dot - lightPos[2] * plane.c - lightPos[2] * plane.d
- lightPos[3] * plane.a - lightPos[3] * plane.b - lightPos[3] * plane.c dot - lightPos[3] * plane.d
Figura 35: Matriz de sombreamento. Na matriz, dot é o produto interno entre o vetor de posição da luz e o plano. plane é uma estrutura que contém quatro elementos: a, b, c e d que provêm da equação do plano: ax + by + cz + d = 0. Esta equação pode ser conseguida para qualquer plano apenas conhecendo sua normal e um ponto arbitrário pertencente a ele. As variáveis a, b e c são as coordenadas x, y e z da normal e d pode ser conseguido substituindo-se suas coordenadas na equação já com a, b e c definidos. Agora, basta apenas configurar o estado de coloração da OpenGL para que a sombra saia da cor desejada e renderizar o objeto. Embora o método de sombras projetadas seja bastante simples e rápido, ele apresenta algumas limitações. A primeira delas é que é difícil utilizá-lo para projetar sombras em outros objetos senão superfícies planas. O que pode ser
47
feito é tratar cada polígono do objeto que receberá a sombra como sendo uma superfície plana. Uma sombra no canto de uma parede ainda é viável, porém, projetar uma sombra em um objeto muito mais completo torna este método impraticável. Outra limitação do método de sombras projetadas é o fato de a sombra ser uma versão achatada do objeto original e não um objeto novo, o que significa que suas normais também foram achatadas, portanto, impossibilita a correta iluminação de uma sombra projetada. Apesar destas limitações, este método ainda é bastante utilizado para aplicações em que não é necessária a interação de sombras com outros objetos. Para estas situações, um dos métodos favoritos dos programadores é o de volumes de sombras. 3.6.2. Volumes de Sombras (Shadow Volumes) Volumes de sombras é um método que não era muito utilizado há alguns anos, pois ele requer mais processamento que o de sombras projetadas. Porém, com o avanço rápido das placas gráficas, este método está se tornando bastante popular. A vantagem deste método sobre o de sombras projetadas é que este impõe a sombra sobre qualquer superfície que esteja na direção do volume de sombra, permitindo que um objeto projete sua sombra sobre outros objetos ou ainda nele mesmo. A idéia por trás do método de volumes de sombras é projetar linhas que partem da fonte luz e coincidem com as arestas do objeto que gerará a sombra. Isso define um volume semi-infinito no lado oposto do objeto, como ilustrado na Figura 36. Depois que todos os volumes de sombras forem definidos, é necessário que se determine se um objeto ou parte dele está dentro de um deles. Dois passos então devem ser seguidos: a construção do volume de sombra e a determinação de se um ponto arbitrário está ou não dentro deste volume.
48
Figura 36: Volume de sombra. Fonte: McREYNOLDS, BLYTHE, 2005. Grande parte do custo computacional deste método está relacionado com a determinação do que o do volume de sombra é. Para isso, é necessário que se encontre as arestas silhuetas de todas os objetos na cena. Arestas silhuetas (silhouete edges) são quaisquer arestas que possuem uma face adjacente que está iluminada e outra não. O que consiste em verificar dentre todas as arestas de todos os objetos na cena quais são silhuetas. Uma vez conseguidas todas estas arestas, podemos definir as linhas que partem da fonte de luz e coincidem com os vértices que definem estas arestas para formar o volume. Para determinar se um ponto está dentro de um volume de sombra, basta traçar uma linha entre o ponto e o observador, contando todas as vezes que a intercepta um volume de sombra. Deve-se determinar também se a linha intercepta a face interior ou exterior do volume, pois, se ela intercepta na parte interior, ela está saindo do volume e se intercepta na parte exterior, ela está entrando. Cada vez que ela intercepta o exterior, um contador é incrementado, e cada vez que intercepta a parte interior, o contador é decrementado. O contador pode ser mantido com o stencil buffer (por isso este método também é chamado de Stenciled Volume Shadow) utilizando os seguintes passos: 1. Renderizar a cena normalmente utilizando as luzes ambientes e emissivas. 2. Renderizar apenas os volumes de sombras. Como não queremos ver os volumes como objetos na cena, desabilitamos a escrita no color e no depth buffer e desenhamos apenas no stencil buffer. Para contar quantas vezes um volume é adentrado, é necessário desabilitar o desenho das faces internas, em OpenGL:
49
glEnable(GL_CULL_FACE); glFrontFace(GL_CCW); Isso faz com que as faces traseiras não sejam desenhadas e indica que as faces desenhadas no sentido anti-horário são as faces fronteiras 10 . Com isso, basta incrementar o contador toda vez que for encontrada uma face no stencil buffer. 3. Neste passo, deve ser feito quase o mesmo que no passo anterior, mas agora as faces que não serão desenhadas serão as faces exteriores. Em OpenGL: glCullFace(GL_CW); O que inverte o resultado do comando glCullFace anterior. Agora deve-se decrementar o contador toda vez que uma face é encontrada no stencil buffer. 4. O último passo consiste em renderizar, com as luzes especular e difusa ligadas, os pontos que possuem o contador do stencil buffer igual a zero. Estes quatro passos para cada ponto da cena podem ser um tanto pesados computacionalmente, porém, como dito há pouco, isto não está se tornando mais um problema. Um outro problema que pode surgir é quando o observador está dentro de um volume de sombra, o que vai causar uma inconsistência no valor do contador. Há algoritmos que podem resolver esta questão, porém são complicados e não estão no âmbito deste trabalho. 3.7. REFLEXOS Reflexos são um dos efeitos que mais são notados em uma cena. Se corretamente implementados, eles podem adicionar muito realismo, mesmo nas mais simples cenas. Tentar utilizar os modelos da física diretamente nos cálculos de reflexos em cenas renderizadas pode ser muito caro computacionalmente. Quanto mais fiel à física o modelo for, maior o processamento necessário. Os métodos aqui descritos tentam englobar as mais importantes partes dos efeitos reais, juntamente com uma eficiência aceitável. Considere o reflexo como sendo a visão de um objeto virtual. Como mostra a Figura 37, o reflexo de um objeto é formada atrás de sua superfície refletora. Dois passos são necessários para implementar reflexos: usar os objetos da
10
Desenhar as faces dianteiras no sentido anti-horário é uma convenção utilizada em OpenGL.
50
cena para criar suas versões refletidas e desenhá-las cortadas pelo desenho do objeto refletor.
Figura 37: Etapas para realização do efeito de reflexo Fonte: McREYNOLDS, BLYTHE, 2005. Há duas maneiras básicas de implementar reflexos: através de texturas e através da implementação de um objeto virtual refletido. O método de uso de textura é o mais intuitivo e consiste em anexar uma textura ao objeto refletor. Uma vantagem deste método é a independência da representação geométrica do objeto que está sendo refletido. Em contrapartida, o método de objetos virtuais pode gerar reflexos em superfícies distorcidas ou curvas, o que não é possível através do método de reflexão por texturas. Este método é suportado nativamente pela OpenGL e com as funcionalidades de matrizes de texturas e suporte à texturização através do mapeamento dos arredores (environment mapping), torna a renderização de reflexos em superfícies arbitrárias relativamente direto. O método de implementação de um objeto virtual, por sua vez, é bem mais complexo. Ele consiste em encontrar um vértice "virtual" para cada vértice dos objetos originais, usando como parâmetro as relações entre o objeto, a superfície refletora e o observador. Uma vantagem deste método é a independência de sua performance da resolução da imagem. Outra vantagem é precisão. Environment mapping, usado na maioria dos métodos de reflexão por texturas, é um aproximação. Ele trabalha refletindo imagens que estão teoricamente distantes do objeto refletor. O método de implementação de objetos virtuais pode adicionar mais precisão aos reflexos dos objetos que se encontram próximos às superfícies refletoras.
51
Cabe ao programador a decisão de qual método será utilizado. Tudo depende dos requerimentos da aplicação e da precisão desejada para a cena. 3.7.1. Reflexos Através do Método de Reflexão por Texturas Várias técnicas se encaixam no método de reflexão por texturas, porém, a mais utilizada é a chamada environment mapping (mapeamento dos arredores). Esta técnica consiste em mapear virtualmente os arredores de um objeto refletor dentro de uma textura e aplicá-la ao objeto refletor e será discutida neste capítulo. Antes de começarmos a discussão sobre environment mapping, é necessário que se introduza o conceito de multi-texturas em OpenGL. 3.7.2. Multi-texturas Para a aplicação do método de reflexos através de texturas, é necessário se entender o conceito de multi-texturas em OpenGL, que é a aplicação de várias texturas a uma face. Este artifício é de grande interesse para a criação de cenas mais dinâmicas e próximas de cenas reais. Apesar de este artifício ser de grande utilidade, ele não é nativo em todas as versões da biblioteca OpenGL. Para fazer uso dele, é necessário que se possua uma implementação que o suporte e utilizar funções providas pela extensão da OpenGL específica para este fim. Entende-se por extensão da OpenGL como sendo funções que ao são suportadas por todas as implementações da biblioteca. A Figura 38 mostra a aplicação de múltiplas texturas em uma mesma face de um polígono ordinário.
Figura 38: Aplicação de múltiplas texturas a uma mesma face
52
3.7.3. Environment Mapping Por exemplo, se uma esfera polida de metal for posta em um campo aberto, podemos ver que nela são refletidos o céu, as nuvens, árvores, o chão, etc. Este é o tipo de efeito conseguido pelo environment mapping. O funcionamento consiste em, ao invés de refletir verdadeiramente todo o arredor do objeto, simular este efeito através de uma textura que representa este arredor. Em OpenGL, basta aplicar a textura ao objeto e gerar automaticamente as coordenadas a cada vez que o objeto se mover, dando a real impressão de reflexão dos arredores do objeto refletor, através dos comandos: glTexGenf(GL_S,GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glTexGenf(GL_T,GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); // renderizar os objetos com a textura anexada. Onde glTexGenf, através dos parâmetros, gera as coordenadas de textura automaticamente e glEnable habilita esta geração e aplicação destas coordenadas. A textura pode ser aplicada diretamente ao objeto refletor ou pode fazer uso do artifício de multi-texturas discutido há pouco. A utilização deste método incrementa ainda mais o nível de realidade da environment mapping,. A Figura 39 mostra a aplicação da técnica de environment mapping a um anel (torus).
Figura 39: Figura de um environment mapping. Fonte: http://www.sparse.org/images/envmap/quad3.jpg
53
A melhor maneira de criar texturas que serão usadas com a técnica de environment mapping é desenhá-las como uma visão de uma lente olho-depeixe, como mostra a Figura 40. Embora este tipo desenho de textura não seja necessário, utilizá-lo acrescenta maior qualidade nos resultados obtidos.
Figura 40: Textura lente olho-de-peixe. Fonte: http://www.sparse.org/images/envmap/front.jpg Embora esta técnica acrescente realismo à cena, ela não é fisicamente correta. A maior parte da deste problema provém da discrepância entre a geração da imagem mapeada e de sua aplicação na geometria do objeto, o que distorce a textura para uma imagem que não necessariamente representa a imagem real dos arredores. 3.8. REFLEXOS UTILIZANDO OBJETOS VIRTUAIS A técnica de reflexos utilizando objetos virtuais é um tanto mais complexa e menos trivial que a environment mapping. Porém como dito anteriormente, os resultados obtidos são muito mais expressivos e podem aumentar consideravelmente o nível de realidade de uma cena. O que será feito nesta seção é a explicação do funcionamento básico do algoritmo que implementa esta técnica, passo a passo, sendo os problemas apresentados e suas soluções discutidas e apresentadas. Este algoritmo foi retirado de [OpenGL Game Programming] e os detalhes de como funcionam as funções de OpenGL aqui descritas também podem ser encontrados neste livro. Vamos começar imaginando uma cena muito simples, onde temos um plano reflexivo infinito na posição y = 0 e um objeto suspenso logo acima. Para fazer com que este objeto reflita uma imagem sobre o plano, basta simplesmente
54
desenhar todos os objetos normalmente e depois redesenhar o objeto a ser refletido com suas coordenadas y invertidas. desenharChao(); desenharObjeto(); glScalef(1.f, -1.f, 1.f); desenharObjeto(); Onde o método desenharChao() desenha plano inferior reflexivo, desenharObjeto() desenha o objeto a ser refletido e glScalef(), uma função da OpenGL (já utilizada neste trabalho) que realiza a escala nos eixos x, y e z do objeto nas proporções passadas segundo os parâmetros respectivos. Este é o funcionamento básico do algoritmo. Se tivermos luzes ativas na cena, notaremos que a iluminação estará incorreta, a não ser que invertamos também a posição da luz. Assumindo que para este propósito temos uma função chamada posicionarLuz(), podemos incrementar o código: posicionarLuz(); desenharChao(); desenharObjeto(); glScalef(1.f, -1.f, 1.f); posicionarLuz(); desenharObjeto(); Há vários problemas que ainda surgirão. Por exemplo: se estivermos utilizando a depth buffer (o que provavelmente está acontecendo), então o objeto refletido não está aparecendo, pois o plano está mais próximo da tela que o reflexo. A solução imediata é desligar o depth buffer antes de desenhar o objeto refletido, porém, isso pode causar problemas se tivermos múltiplos objetos na cena que estão sobrepostos na visão do observador. É desejado que os reflexos mantenham a ordem visual dos objetos originais. A solução é não desenhar na depth buffer o plano refletor. Porém, ainda queremos que o plano não sobrescreva os objetos na frente da cena, pois ele está mais ao fundo. Isto é possível configurando o teste da depth buffer para não atualizar, através da função glDepthMask() 11 . posicionarLuz(); 11
O teste da depth buffer é um teste que testa se um ponto que está sendo desenhado numa determinada posição da tela está à frente ou atrás de um ponto já naquela posição. A função glDepthMask() habilita ou não este teste. Mais detalhes sobre esta função em [OpenGL Game Programming].
55
desenharObjeto(); glDepthMask(GL_FALSE); desenharChao(); glScalef(1.f, -1.f, 1.f); posicionarLuz(); desenharObjeto(); Até o presente momento, assumimos que o plano em que estamos configurando o reflexo é infinito, o que geralmente não acontece na prática. Se executarmos este algoritmo em superfícies finitas, em determinadas posições será possível ao observador ver reflexos em partes que não existem. Isso pode ocorrer, por exemplo, em uma cena que consiste de espelho numa parede não reflexiva. Se não cortamos a figura resultante do reflexo de acordo com as bordas do espelho, a parede refletirá tanto quanto o espelho. Como visto na Seção 3.6, um artifício bastante útil para este fim em OpenGL é a stencil buffer. Nosso algoritmo agora, mais elaborado, fica assim: // primeiro, desabilitamos as buffers de cores e profundidade // pois não é desejado que o plano apareça ainda na cena glColorMask(GL_FALSE,
GL_FALSE,
GL_FALSE,
GL_FALSE); glDepthMask(GL_FALSE);
// habilitamos então a stencil buffer glEnable(GL_STENCIL_TEST); glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF); glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
// desenhamos a superfície na stencil buffer desenharChao();
// normais
desnhamos
agora
os
reflexos
nas
condições
56
// (color e depth buffer habilitados) apenas nos lugares onde // há stencil buffer está preenchida glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDepthMask(GL_TRUE); glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
// desenhamos agora primeiro a imagem refletida glPushMatrix(); glScalef(1.0, -1.0, 1.0); posicionarLuz(); desenharObjeto(); glPopMatrix();
// e finalmente desenhamos a cena original posicionarLuz(); desenharChao(); desenharObjeto(); Com isso podemos renderizar nossa superfície reflexiva. Porém, este algoritmo é útil para espelhos, onde a reflexão é completa. Para superfícies que não são perfeitamente reflexivas, como metais, basta habilitar as funções de transparência da OpenGL antes da segunda vez em que o plano é desenhado, resultando no reflexo irregular do objeto na superfície. Outra necessidade que pode surgir é o fato que precisarmos implementar uma superfície reflexiva em outro plano que não seja o plano xz utilizado no algoritmo. Para realizar reflexão em planos arbitrário, basta modificar o algoritmo seguindo os seguintes passos: 1. Posicione e rotacione o plano reflexivo centralizado na origem e no plano xz, xy ou yz. 2. Faça as transformações reflexivas invertendo as coordenadas do eixo correspondente: y no plano xz (como no algoritmo), z no plano xy e x no plano yz.
57
3. Reverta as transformações executadas no passo 1 para mover todas os objetos para os seus respectivos lugares originais. Isto é o suficiente para produzir reflexos realistas, podendo até mesmo, através deste algoritmo, implementar reflexos em múltiplos planos. Porém, este efeito deve ser usado com parcimônia, visto que ele pode facilmente aumentar o processamento necessário para a renderização de uma cena.
58
4. CONCLUSÃO Estudar a biblioteca OpenGL, principalmente para quem tem interesse em programação de jogos, é algo bastante fascinante. Sua versatilidade, robustez e facilidade de implementação de funções de alto nível, mostra o porquê de esta biblioteca estar sendo tão utilizada. No contexto de iluminação, a OpenGL é bastante satisfatória pois conta com funções de iluminação bastante simples e intuitivas. Todos os cálculos que acompanhamos na seção 3.4, são hoje feitos muito rapidamente pelo hardware gráfico de computadores mais modestos, fazendo com que se ampliem as possibilidades sem limitar tanto o público-alvo de jogos mais exigentes. Os efeitos como sombra e reflexos poderiam ser portados pela biblioteca nativamente, porém, apesar de isso não ser uma realidade, não representa nenhum empecilho, como foi visto neste trabalho, pois como foi visto, utilizando algoritmos simples podemos simular estes efeitos satisfatoriamente para a maioria das aplicações, incluindo os jogos.
59
BIBLIOGRAFIA ADDITIVE Color. Wikipedia. Disponível em: Acesso em: 22/09/2006 AMPLITUDE. Wikipedia. Disponível em: Acesso em: 19/10/2006 ANGEL,Edward. Shading. In: ______. Interactive Computer Graphics: A TopDown Approach Using OpenGL. 4th ed. California: Pearson, 2006. p.285-320. BRIGHTNESS. Wikipedia. Disponível em: Acesso em: 24/09/2006 CMYK Color Model. Wikipedia. Disponível em: Acesso em: 22/09/2006 COLOR MODELS. Wikipedia. Disponível em: Acesso em: 22/09/2006 COLOR THEORY. Wikipedia. Disponível em: Acesso em: 17/09/2006 COLOR. Wikipedia. Disponível em: Acesso em:17/09/2006 CONE Cell. Wikipedia. Disponível em: Acesso em: 22/09/2006 COR. Wikipedia. Disponível em: . Acesso em: 17/09/2006 DARKNESS. Wikipedia. Disponível em: Acesso em: 21/10/2006 DIFFUSE Reflection. Wikipedia. Disponível em: Acesso em: 20/10/2006 FREQUENCY. Wikipedia. Disponível em: Acesso em: 25/09/2006 HAWKINS, Kevin; ASTLE, Dave. OpenGL Game Programming. California: Prima Tech, 2001. HLS Color Space. Wikipedia. Disponível em: Acesso em: 25/09/2006 HSV Color Space. Wikipedia. Disponível em: Acesso em: 24/09/2006
60
HUE. Wikipedia. Disponível em: Acesso em: 24/09/2006 INTENSITY. Wikipedia. Disponível em: Acesso em: 25/09/2006 LIGHT. Wikipedia. Disponível em: Acesso em: 17/09/2006 LUZ. Wikipedia. Disponível em: Acesso em: 17/09/2006 McREYNOLDS, Tom; BLYTHE, David. Advanced Graphics Programming Using OpenGL. California: Elsevier, 2005. OPTICS. Wikipedia. Disponível em: Acesso em: 19/10/2006 PHOTON. Wikipedia. Disponível em: Acesso em: 19/10/2006 POLARIZATION. Wikipedia. Disponível em: Acesso em: 19/10/2006 REFLECTION. Wikipedia. Disponível em: Acesso em: 19/10/2006 REFRACTION. Wikipedia. Disponível em: Acesso em: 19/10/2006 RGB Color Model. Wikipedia. Disponível em: Acesso em: 22/09/2006 SATURATION. Wikipedia. Disponível em: Acesso em: 24/09/2006 SHADOW. Wikipedia. Disponível em: Acesso em: 21/10/2006 SOMBRA. Wikipedia. Disponível em: Acesso em: 21/10/2006 SPECULAR Reflection. Wikipedia. Disponível em: Acesso em: 20/10/2006 SUBTRACTIVE Color. Wikipedia. Disponível em: Acesso em: 22/09/2006
61
TEORIA das cores. Wikipedia. Disponível em: Acesso em: 17/09/2006 TRAINA, Agma Juci Machado. Apostila de Computação Gráfica. Disponível em . Acesso em: 20/07/2006. VISIBLE Spectrum. Wikipedia. Disponível em: Acesso em: 19/10/2006 YOUNG-HELMHOLTZ Theory. Wikipedia. Disponível em: Acesso em: 23/09/2006