Desenho de objetos em OpenGL -- Computação Gráfica

jSSeção 5.2  

 

 

         5.2. Modelos de Iluminação



Para tentarmos sintetizar imagens realistas, necessitamos saber a quantidade de luz associada a um ponto qualquer, numa face do objeto a respeito do qual queremos gerar a imagem. Para isso, precisamos definir as características das fontes de luz e também as propriedades do material do objeto, criando assim um modelo de iluminação.

Os modelos de iluminação são na verdade, uma simplificação satisfatória do que acontece na realidade. Um raio de luz pode sofrer inúmeras reflexões ou refrações, interagindo com vários objetos até que consiga chegar a câmera. Esse processo é inadequado para a computação gráfica interativa pelo fato do tempo gasto na criação da imagem. Por isso, para se desenhar imagens em um tempo hábil mas que sejam de qualidade satisfatória é necessário utilizar esses modelos de iluminação. 

A seguir serão demonstrados cada modelo de iluminação separadamente e após isso um modelo geral de iluminação. 

LUZ AMBIENTE

A simplificação que este modelo propõe é que, cada ambiente possui uma pequena quantidade de luz, de origem desconhecida, independente de qualquer fonte de luz, que ilumina todas as faces do objeto de maneira uniforme. 

Cada objeto na cena pode refletir mais luz ou menos luz ambiente. Isso é determinado pelas propriedades do material desse objeto. 

Se quiséssemos descrever uma fórmula para calcular a intensidade de luminosa num ponto arbitrário em um objeto seria conforme abaixo:

I = Ia * Ka

Onde I é a intensidade de luz no ponto;
Ia é a intensidade de luz ambiente na cena;
Ka é a quantidade de luz ambiente que o objeto reflete.

Em OpenGL um modelo deste tipo poderia ser definido da seguinte forma:

    >> GLfloat luz_ambiente[]  = { XR, XG, XB, X } ;
    >> GLfloat objeto_ambiente [] = { YR, YG, YB, Y};
    >> glLightfv(GL_LIGHT0, GL_AMBIENT, luz_ambiente );
    >> glMaterialf (GL_FRONT_AND_BACK, GL_AMBIENT, objeto_ambiente);
    >> glEnable(GL_LIGHTING);
    >> glEnable(GL_LIGHT0);

Repare que os 3 primeiros atributos setados em luz_ambiente especificam a intensidade de luz vermelha (XR) , intensidade de luz verde (XG) e intensidade de luz azul (XB). Estes atributos devem variar de 0.0 a 1.0 . O último atributo indica a quantidade geral de luz ambiente que será emitida,em outras palavras um coeficiente que multiplicará cada intensidade de luz e também deve ser variado de 0.0 a 1.0.

Os atributos de objeto_ambiente funcionam de maneira semelhante a luz_ambiente .

O comando glLight cria uma fonte de luz ambiente GL_LIGHT0, com as características definidas em luz_ambiente.

O comando glMaterial especifica o quanto de luz ambiente vai ser refletido nas faces da frente e de trás (GL_FRONT_AND_BACK) de determinado objeto. 

Repare que é preciso habilitar a luz através dos dois últimos comandos, sendo que o último habilita uma fonte de luz específica dando liberdade ao programador de habilitar somente as fontes de luz necessárias. 

 

REFLEXÃO DIFUSA

Diferentemente da luz ambiente que  ilumina objetos de maneira uniforme, proporcionando uma imitação insuficientemente precisa do que acontece no mundo real, o modelo de reflexão difusa tenta imitar o que acontece com superfícies toscas ou ásperas, como o carvão,por exemplo. Superfícies assim parecem igualmente brilhantes de qualquer ponto de vista, devido a irregularidade na superfície. Porém, as faces onde os raios de luz incidem de maneira mais perpendicular parecem mais brilhantes que aquelas nas quais a luz incide de maneira mais inclinada.

Uma fórmula para calcular a intensidade luminosa de um ponto arbitrário num objeto é dada por:

I = Id * Kd * cos (teta) 

Onde I é a intensidade da luz no ponto analisado.
Id é a intensidade de luz difusa.
Kd é o coeficiente de reflexão da luz difusa.
teta é o ângulo entre a normal da superfície e a direção da luz.

Não iremos entrar em detalhes de como surgiu essa fórmula, mas mostraremos como construir um modelo desse tipo em OpenGL. Veja os comandos abaixo:

    >> GLfloat luz_difusa[]  = { XR, XG, XB, X } ;
    >> GLfloat objeto_difusa [] = { YR, YG, YB, Y};
    >> glLightfv(GL_LIGHT0, GL_DIFFUSE, luz_difusa );
    >> glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, objeto_difusa);
    >> glEnable(GL_LIGHTING);
    >> glEnable(GL_LIGHT0);

Os comandos são bem parecidos com os utilizados para criar um modelo de iluminação ambiente. A única diferença é que ao invés da constante GL_AMBIENT usa-se a constante GL_DIFFUSE. 

No caso da reflexão difusa é necessário especificar as normais para que o ângulo teta possa ser calculado. Iremos tratar desse assunto na seção 5.4. As normais não estão definidas dentro do modelo de iluminação, pois elas são definidas na descrição do objeto.

REFLEXÃO ESPECULAR

Este tipo de reflexão é o que ocorre em superfície polidas onde a luz refletida fica mais concentrada em determinada local do objeto, sendo que quanto mais polida for a superfície mais concentrada estará a luz refletida. Como exemplo podemos citar a reflexão da luz numa bola de sinuca. 

É importante observar que cada um dos modelos apresentados até aqui procuram se preocupar com alguns casos, criando assim aquela simplificação citada no começo dessa seção. 

Também não iremos entrar em detalhes a respeito da dedução de uma fórmula para calcular a intensidade luminosa de um ponto durante uma reflexão especular. Desta forma apenas citaremos a mesma:

I = Ie * Ke * cos^n (teta) 

Onde I é a intensidade da luz no ponto analisado.
Id é a intensidade de luz especular.
Kd é o coeficiente de reflexão da luz especular.
teta é o ângulo entre a normal da superfície e a direção da luz.
n é um índice que indica o quanto a superfície é polida.

É importante ressaltar que cos^n significa cosseno elevado a n. Para criar um modelo desses em OpenGL são necessários os seguintes comandos:

    >> GLfloat luz_especular[]  = { XR, XG, XB, X } ;
    >> GLfloat objeto_especular[] = { YR, YG, YB, Y};
    >> glLightfv(GL_LIGHT0, GL_SPECULAR, luz_especular );
    >> glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, objeto_especular);
    >> glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, n );
    >> glEnable(GL_LIGHTING);
    >> glEnable(GL_LIGHT0);

Verifique que todos os comandos já foram utilizados em modelos anteriores, porém com os parâmetros diferentes. O comando em azul define o quanto a superfície é polida, ou seja, o brilho dessa superfície. O intervalo de GL_SHININESS em OpenGL é de 0.0 a 128.0 . Quanto maior o valor, mais concentrado será o reflexo observado na região do objeto onde a direção do observador coincide com a direção preferida da reflexão.

Da mesma forma que a reflexão difusa, a reflexão especular exige que as normais sejam declaradas. Isso ocorre para o cálculo do ângulo teta. Veremos maiores detalhes na seção 5.4 .

 

ATENUAÇÃO ATMOSFÉRICA

Um raio de luz interage com os gases presentes na atmosfera antes de chegar ao olho do observador sofrendo assim uma atenuação. 

Num dia nublado, os objetos distantes tendem a ficar esbranquiçados a medida que se afastam do observador. Ao pôr do sol, objetos distantes ficam mais alaranjados. Em todos esses casos, as cores dos objetos tendem a ficar uniformes, aproximando-se de uma cor dominante que pode ser vista como a cor do horizonte ou "cor do fundo" .

Essa atenuação pode ser calculada em função da distância através da fórmula:

f(d) = I / a + b*d + (c^2)*d 

Em OpenGL é necessário utilizar comandos glLightf conforme abaixo:

    >> glLightf (GL_LIGHT0, GL_CONSTANT_ATTENUATION, a);
    >> glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, b) ;         
    >> glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, c) ;          

a-> é o parâmetro a da fórmula citada. 
b-> o parâmetro b da fórmula citada.
c-> o parâmetro c da fórmula citada.

CRIANDO UM MODELO GERAL

Até agora abordamos cada modelo separadamente. Entretanto se juntarmos todos eles podemos criar uma imagem mais realística. Nesse caso podemos dizer que a cor de um ponto qualquer seria um função da reflexão da luz ambiente, de reflexão difusa, reflexão especular e atenuação atmosférica. 

Baseado na idéia citada acima, a fórmula para definir a intensidade da luz num ponto qualquer neste modelo geral seria:

Em OpenGL podemos definir um modelo como através dos seguintes comandos:

    >> GLfloat luz_ambiente[]  = { XaR, XaG, XaB, Xa } ;
    >> GLfloat objeto_ambiente[] = { YaR, YaG, YaB, Ya};
    >> GLfloat luz_difusa[]  = { XdR, XdG, XdB, Xd } ;
    >> GLfloat objeto_difusa[] = { YdR, YdG, YdB, Yd};
    >> GLfloat luz_especular[]  = { XeR, XeG, XeB, Xe } ;
    >> GLfloat objeto_especular[] = { YeR, YeG, YeB, Ye};
    >> glLightfv(GL_LIGHT0, GL_AMBIENT, luz_ambiente );
    >> glLightfv(GL_LIGHT0, GL_DIFFUSE, luz_difusa );
    >> glLightfv(GL_LIGHT0, GL_SPECULAR, luz_especular );
    >> glLightf (GL_LIGHT0, GL_CONSTANT_ATTENUATION, a);
    >> glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, b) ;         
    >> glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, c) ;          
    
    >> glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, objeto_ambiente);
    >> glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, objeto_difusa);
    >> glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, objeto_especular);
    >> glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, n );
    >> glEnable(GL_LIGHTING);
    >> glEnable(GL_LIGHT0);

Verifique que apenas juntamos as declarações dos modelos anteriores e criamos um novo modelo geral. Você deve estar se perguntando onde estão os exemplos. Primeiro iremos mostrar os conceitos a respeito de iluminação e depois sim mostrar exemplos que utilizem vários desses conceitos ao mesmo tempo. 

Quando criamos um modelo geral precisamos especificar as normais pois existe reflexão especular e reflexão difusa. Se o modelo tivesse apenas reflexão ambiente e atenuação atmosférica as normais não deveriam ser especificadas. Maiores detalhes serão explorados na seção 5.4 .

PARTICULARIDADES NA ESPECIFICAÇÃO DE MATERIAIS

Conforme dito, as propriedades do material pelo qual é formado o objeto pode ser definida através do comando glMaterial. Entretanto ocorre que se for especificado glMaterial, o comando glColor (visto na seção 3.5 ) perde o efeito, ou seja, o objeto não ficará da cor especificada em glColor e sim de acordo com as características do material, definida em glMaterial. 

Para fins de simplificação, o OpenGL possui um comando chamado glColorMaterial. Através desse comando você consegue dizer que um objeto vai refletir luz ambiente,difusa, especular ou até mesmo emitir luz de acordo com os parâmetros configurados em glColor. Por exemplo, você está desenhando um cubo e especifica uma cor para o mesmo através do comando glColor. Agora você precisa dizer ao modelo de iluminação que ao receber uma luz ambiente ou difusa o cubo irá refletir a mesma cor indicada em glColor. Nesse caso você pode utilizar o comando glColorMaterial e a partir daí qualquer alteração em glColor altera automaticamente glColorMaterial. Veja a sintaxe abaixo:

    >> glColorMaterial (face, type );
    >> glEnable (GL_COLOR_MATERIAL);

O parâmetro face pode definido pelas constantes abaixo:

GL_FRONT -> indica somente as faces da frente
GL_BACK   -> indica somente as faces de trás 
GL_FRONT_AND_BACK -> ambas

O parâmetro type indica qual o tipo de iluminação será configurada de acordo com a cor especificada em glColor. Veja as constantes que definem o parâmetro:

AMBIENT -> indica que o coeficiente de reflexão ambiente do material do objeto será definido pelos parâmetro do comando glColor.
DIFFUSE  -> indica que o coeficiente de reflexão difusa do material do objeto será definido pelos parâmetros do comando glColor.
AMBIENT AND DIFFUSE ->  indica que o coeficiente de reflexão ambiente e difusa do material do objeto será definido pelos parâmetros do comando glColor.
SPECULAR ->  indica que o coeficiente de reflexão especular e difusa do material do objeto será definido pelos parâmetros do comando glColor.
EMISSION -> indica que o objeto irá emitir uma luz da mesma cor configurada em glColor, criando assim um objeto que possui luz própria.

Posteriormente, abordaremos exemplos que utilizam o comando glColorMaterial. 

 

 

[principal]

[anterior]

[próxima]