Pular para o conteúdo principal

Aula 08 — Modelos de Iluminação

Objetivos​

Ao final desta aula você deve ser capaz de:

  • Distinguir fontes pontuais, direcionais e spot pelos parâmetros que definem sua emissão.
  • Calcular as contribuições ambiente, difusa e especular de um modelo de reflexão local.
  • Explicar o papel dos vetores normal, direção da luz e direção do observador no resultado.
  • Comparar tonalização flat, Gouraud e Phong, identificando onde cada uma calcula a iluminação.
  • Configurar luzes e materiais no pipeline fixo do OpenGL 2.1.
  • Diagnosticar problemas causados por normais incorretas, posição da luz e brilho especular.

Conteúdo​

Retomando: o que muda em relação à Aula 07​

A Aula 07 decidiu quais superfícies chegam à imagem. Agora precisamos calcular a cor de cada ponto visível. Em computação gráfica, um modelo de iluminação descreve a luz emitida pelas fontes, enquanto um modelo de reflexão aproxima como o material devolve essa luz ao observador. O resultado depende da fonte, do material e da geometria local da superfície.

Na aula anterior, a orientação das faces ajudava a decidir qual lado era frontal. No OpenGL, o descarte usa a ordem dos vértices projetados e glFrontFace, não a normal enviada por glNormal*. Aqui, a normal participa do cálculo de iluminação: invertê-la muda a reflexão, mas não muda o descarte.

É útil separar três perguntas:

  1. De onde a luz vem? A fonte fornece posição, direção, cor e atenuação.
  2. Como a superfície reflete? O material define as parcelas ambiente, difusa e especular.
  3. Onde o cálculo é feito? A tonalização escolhe entre face, vértices ou fragmentos.

Laboratório que acompanha a leitura​

📥 Baixe o arquivo completo: modelos_iluminacao.py

Executável. Use Python 3.10 ou superior, PySide6, PyOpenGL e um contexto compatível com OpenGL 2.1. Na raiz do repositório fundamentos-opengl-python:

uv run aula-08-modelos-iluminacao/modelos_iluminacao.py

Para o arquivo baixado isoladamente, instale PySide6 e PyOpenGL com python -m pip install PySide6 PyOpenGL e execute python modelos_iluminacao.py. Os demais trechos desta página são recortes para leitura.

O exemplo permite isolar os parâmetros do modelo:

TeclaAlternaO que observar
1, 2, 3pontual, direcional e spotdireção, distância e região atingida
A, D, Eambiente, difusa e especularcontribuição visual de cada termo
Sflat e Gouraudmuda somente a interpolação das cores
Nnormais por face e por vérticemuda somente as normais enviadas
Inormais originais ou invertidasproduz um defeito de iluminação
Oabertura spot: 12°, 28°, 45°região coberta pelo cone
Pexpoente spot: 0, 12, 48concentração em torno do eixo
Rrestaura o estado inicialrepete o experimento nas mesmas condições
[ e ]brilho especulartamanho e concentração do ponto de brilho
setasrotação do objetoorientação das facetas em relação à luz
J, Lórbita da câmeradependência do brilho em relação ao observador
Cluz no mundo ou na câmerareferencial usado ao enviar a fonte
Escfecha a janelaencerra o laboratório

Comece apenas com R, A, D e E; os demais controles serão usados nos experimentos seguintes. O título mostra os estados ativos. R restaura fonte pontual, A/D/E ligadas, normais por vértice, Gouraud, brilho 48, spot com abertura 28° e expoente 0, luz no mundo e câmera inicial.

O programa usa uma esfera tessellada (dividida em triângulos) com poucos setores para que as diferenças entre geometria, normais e tonalização permaneçam visíveis.

Tipos de fonte de luz​

FonteRepresentaçãoVaria com a distância?Região atingida
Pontualposição (x,y,z,1)(x,y,z,1)sim, quando há atenuaçãotodas as direções a partir do ponto
Direcionaldireção (x,y,z,0)(x,y,z,0)nãotoda a cena, com raios paralelos
Spotposição, direção e conesim, quando há atenuaçãointerior do cone

Uma luz pontual aproxima uma lâmpada pequena. O vetor até a fonte muda em cada ponto da superfície. Uma luz direcional aproxima uma fonte muito distante, como o Sol: todos os pontos recebem raios paralelos. Uma luz spot é pontual, mas restringe a emissão a um cone e pode reduzir a intensidade perto da borda.

A Figura 1 resume a geometria que diferencia as fontes. Ela também explica por que uma luz direcional não precisa de atenuação por distância: o modelo a trata como se estivesse infinitamente longe.

Três painéis com fontes de luz. A fonte pontual emite raios em várias direções a partir de uma posição. A direcional envia raios paralelos. A spot forma um cone com direção central e ângulo de corte.
Fonte pontual, direcional e spot não são apenas aparências diferentes. Cada uma fornece uma geometria distinta para o cálculo de iluminação.

No quarto componente de GL_POSITION, w=1 indica posição e w=0 indica direção. Nesse último caso, os três primeiros valores apontam de onde a luz vem.

glLightfv(GL_LIGHT0, GL_POSITION, (3.0, 4.0, 5.0, 1.0)) # pontual
glLightfv(GL_LIGHT0, GL_POSITION, (-1.0, -1.0, -1.0, 0.0)) # direcional

# Spot: redefina a fonte como posicional antes de configurar o cone.
glLightfv(GL_LIGHT0, GL_POSITION, (0.0, 3.0, 0.0, 1.0))
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, (0.0, -1.0, 0.0))
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 25.0)
glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 12.0)

As chamadas ilustram configurações sucessivas da mesma GL_LIGHT0, não três luzes simultâneas: cada GL_POSITION substitui o estado anterior. Para voltar do spot à emissão em todas as direções, restaure GL_SPOT_CUTOFF para 180°. A direção do spot aponta para onde a luz é emitida; a direção em GL_POSITION de uma fonte direcional aponta de onde a luz vem.

Para uma fonte pontual ou spot, o OpenGL pode reduzir a intensidade com a distância dd:

fat(d)=1kc+kld+kqd2f_{at}(d)=\frac{1}{k_c+k_l d+k_q d^2}

Os coeficientes constante, linear e quadrático são configurados com GL_CONSTANT_ATTENUATION, GL_LINEAR_ATTENUATION e GL_QUADRATIC_ATTENUATION. Os valores padrão não reduzem a intensidade com a distância: kc=1k_c=1, kl=0k_l=0 e kq=0k_q=0, portanto fat=1f_{at}=1. Posicionar uma luz mais longe não a enfraquece por distância no pipeline fixo. Ainda assim, deslocá-la pode mudar o vetor até a fonte e, com isso, a reflexão.

Experimento 1 — reconhecer as fontes​

Pressione R, desligue ambiente e especular com A e E e compare 1, 2 e 3. Observe a região iluminada, sem mover câmera ou objeto. As fontes do laboratório têm geometrias diferentes; essa primeira observação não isola apenas a distância. A atividade de comparação fará mudanças controladas.

Reflexão ambiente, difusa e especular​

O modelo local clássico soma três aproximações. Para uma fonte, podemos escrever a intensidade resultante como:

I=KaIa+KdIdmax⁡(0,n^⋅l^)+KsIsmax⁡(0,r^⋅v^)αI = K_a I_a + K_d I_d\max(0,\hat{n}\cdot\hat{l}) + K_s I_s\max(0,\hat{r}\cdot\hat{v})^\alpha

Os vetores são unitários: n^\hat{n} é a normal, l^\hat{l} aponta para a luz, v^\hat{v} aponta para o observador e r^\hat{r} é a reflexão ideal de −l^-\hat{l} em torno da normal. Os coeficientes KaK_a, KdK_d e KsK_s descrevem o material; IaI_a, IdI_d e IsI_s descrevem as cores da fonte. A expressão é aplicada separadamente aos canais RGB e omite atenuação e cone spot. Para uma superfície opaca, a parcela especular também é zero quando n^⋅l^≤0\hat n\cdot\hat l \leq 0: não há iluminação direta pelo lado de trás. A reflexão ideal é r^=2(n^⋅l^)n^−l^\hat r = 2(\hat n\cdot\hat l)\hat n - \hat l. O modelo local não verifica obstáculos entre o ponto e a fonte; sombras projetadas exigem uma técnica adicional.

A Figura 2 coloca esses vetores no mesmo ponto da superfície. O ângulo entre n^\hat n e l^\hat l controla a parcela difusa; o alinhamento entre r^\hat r e v^\hat v controla a especular.

Superfície curva com um ponto P. A partir dele saem a normal para cima, o vetor para a luz à esquerda, a reflexão ideal à direita da normal e o vetor para o observador mais inclinado à direita. Arcos identificam os ângulos usados nos termos difuso e especular.
A geometria local separa as dependências: o termo difuso compara normal e luz; o especular compara reflexão ideal e observador.
ComponenteEfeito visualDepende deLimitação da aproximação
Ambientemantém áreas sem luz direta visíveismaterial e luz ambientenão calcula as múltiplas reflexões reais
Difusarevela a orientação da superfícieângulo entre normal e luznão depende do observador
Especularproduz o ponto de brilholuz, normal, observador e expoenteaproxima superfícies brilhantes

Reflexão ambiente​

A parcela ambiente é constante para uma mesma combinação de luz e material. Ela representa, de forma barata, a luz indireta que chegaria após várias reflexões. Por não considerar posição nem orientação, ilumina igualmente todos os pontos do material no modelo simplificado acima. No OpenGL, a parcela ambiente de cada fonte também recebe os fatores de atenuação e de spot; a luz ambiente global é um estado separado.

Reflexão difusa de Lambert​

A parcela difusa cresce com max⁡(0,n^⋅l^)\max(0,\hat{n}\cdot\hat{l}). Quando a luz chega perpendicularmente, o produto escalar vale 1; em um ângulo rasante, aproxima-se de 0. A luz refletida tem a mesma intensidade em todas as direções, por isso a posição do observador não participa desse termo.

Reflexão especular​

A parcela especular concentra brilho quando o observador se aproxima da direção de reflexão ideal. O expoente α\alpha, chamado brilho ou shininess, controla o tamanho da região: valores baixos produzem um brilho amplo; valores altos, um brilho pequeno e concentrado. A cor especular costuma acompanhar a cor da fonte, embora o material também possa filtrá-la.

Experimento 2 — decompor a aparência​

Pressione R, depois D e E: sobra apenas ambiente. A superfície mantém uma cor uniforme, sem revelar a curvatura pela luz. Desligue A: o objeto fica preto. Ative somente D: aparece a variação de intensidade que revela a orientação. Acrescente E: procure o destaque especular. Se ele for pouco visível, orbite com J e L. A silhueta depende da malha em todos os casos.

A Figura 3 mostra as três parcelas isoladas na mesma esfera, com fonte pontual e enquadramento inicial. A ambiente preserva a cor sem sugerir volume; a difusa revela a orientação; a especular aparece apenas numa região pequena. O preto nos dois últimos painéis é a superfície sem contribuição daquela parcela, não um buraco na malha. A imagem final combina as parcelas ativas.

Três capturas da mesma esfera: ambiente em azul uniforme; difusa com gradiente claro à direita; especular quase preta com um destaque claro localizado.
As componentes isoladas explicam de onde vêm a cor de fundo do material, a percepção de volume e o destaque especular.

Exemplo de cálculo em um canal​

Considere Ka=0,2K_a=0{,}2, Ia=0,1I_a=0{,}1, Kd=0,6K_d=0{,}6, Id=1I_d=1, Ks=0,5K_s=0{,}5, Is=1I_s=1, n^⋅l^=0,8\hat n\cdot\hat l=0{,}8, r^⋅v^=0,5\hat r\cdot\hat v=0{,}5 e α=4\alpha=4, sem atenuação:

I=0,2×0,1+0,6×1×0,8+0,5×1×(0,5)4=0,02+0,48+0,03125=0,53125.I = 0{,}2\times0{,}1 + 0{,}6\times1\times0{,}8 + 0{,}5\times1\times(0{,}5)^4 = 0{,}02 + 0{,}48 + 0{,}03125 = 0{,}53125.

Se apenas o observador mudar, o termo difuso permanece 0,480{,}48; a parcela especular pode mudar. Repita o cálculo com α=8\alpha=8: o resultado é 0,5019531250{,}501953125, pois o mesmo desalinhamento atenua mais o brilho.

Phong e Blinn-Phong​

A equação anterior é o modelo de reflexão de Phong. O pipeline fixo usa uma variante, Blinn-Phong: o termo especular compara a normal com o vetor intermediário h^=(l^+v^)/∥l^+v^∥\hat h = (\hat l + \hat v)/\|\hat l + \hat v\|, quando a soma é não nula, usando max⁡(0,n^⋅h^)s\max(0, \hat n\cdot\hat h)^s. Os expoentes das duas formulações não são diretamente equivalentes.

Modelo de reflexão de Phong e tonalização de Phong são conceitos diferentes: o primeiro define a reflexão; o segundo calcula iluminação por fragmento, uma amostra produzida pela rasterização que pode contribuir para um pixel.

Luz e material no OpenGL​

O pipeline fixo separa propriedades da fonte (glLight*) das propriedades da superfície (glMaterial*). Habilitar GL_LIGHTING faz o OpenGL usar normais e materiais; a cor enviada por glColor* só controla o material se GL_COLOR_MATERIAL também estiver ativo.

Essa separação é importante: mudar GL_DIFFUSE da luz altera todos os materiais atingidos; mudar GL_DIFFUSE do material altera apenas as superfícies desenhadas com aquele estado. Em ambos os casos, as quatro componentes representam vermelho, verde, azul e alfa.

glEnable(GL_DEPTH_TEST)
glEnable(GL_LIGHTING)
glEnable(GL_LIGHT0)
glEnable(GL_NORMALIZE)
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (0.0, 0.0, 0.0, 1.0))
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE)

glLightfv(GL_LIGHT0, GL_AMBIENT, (0.10, 0.10, 0.12, 1.0))
glLightfv(GL_LIGHT0, GL_DIFFUSE, (0.90, 0.85, 0.75, 1.0))
glLightfv(GL_LIGHT0, GL_SPECULAR, (1.00, 1.00, 1.00, 1.0))

glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, (0.20, 0.55, 0.85, 1.0))
glMaterialfv(GL_FRONT, GL_SPECULAR, (1.0, 1.0, 1.0, 1.0))
glMaterialf(GL_FRONT, GL_SHININESS, 48.0) # faixa: 0 a 128

O laboratório zera a luz ambiente global para permitir isolar as parcelas com A, D e E. Com todas desligadas, o objeto fica preto. O observador local (GL_LIGHT_MODEL_LOCAL_VIEWER) faz o cálculo especular usar a direção até a câmera; o padrão usa uma direção de observação constante.

O estado do OpenGL persiste. Se o programa muda um material para desenhar um objeto e não restaura o estado antes do próximo, ambos podem receber o mesmo material por acidente. A pilha de matrizes estudada nas aulas anteriores não salva luzes nem materiais.

A posição da luz usa a matriz MODELVIEW vigente

glLightfv(GL_LIGHT0, GL_POSITION, ...) transforma a posição no momento da chamada. Para manter a luz parada no mundo enquanto o objeto gira, envie a posição em paintGL, depois de gluLookAt e antes das transformações do objeto. Se a chamada ocorrer com a matriz identidade, a fonte ficará presa ao espaço da câmera.

Exemplo — iluminar uma malha conhecida​

Na Aula 07, o octaedro era descrito por VERTICES, FACES e normal_face. Esses dados continuam úteis. Para iluminar a malha, a normal calculada deve ser enviada antes dos vértices aos quais se aplica:

octaedro_iluminado_base.py (trecho a completar na atividade)
for face in FACES:
glNormal3f(*normal_face(face))
for indice in face:
glVertex3f(*VERTICES[indice])

A atividade 1 preserva a câmera, a geometria e a visibilidade, e acrescenta iluminação por etapas. Isso permite atribuir a mudança de aparência à luz e ao material, sem reconstruir o objeto.

Normais por face e por vértice​

A normal por face calculada na Aula 07 basta para uma superfície plana. Em uma malha que aproxima uma curva, podemos estimar uma normal de vértice combinando as normais das faces vizinhas e normalizando o resultado. Quinas vivas exigem normais diferentes no mesmo ponto geométrico; por isso arquivos OBJ podem repetir um vértice com índices de normal distintos.

Uma média simples funciona bem em regiões suaves, mas nem sempre é a melhor estimativa. Faces com áreas muito diferentes podem exigir uma média ponderada por área ou pelo ângulo no vértice. Para esta aula, a média normalizada das faces vizinhas basta para evidenciar o princípio.

GL_NORMALIZE corrige o comprimento das normais depois de transformações, especialmente escalas. Ele não corrige uma normal apontando para o lado errado.

Modelos de tonalização​

O modelo de reflexão diz qual cálculo realizar. O modelo de tonalização diz onde realizá-lo e o que interpolar dentro do triângulo.

TonalizaçãoCálculo de iluminaçãoInterpolaçãoConsequência
Flatnos vértices; seleciona o vértice provocadornenhumausa um resultado constante e evidencia facetas
Gouraudnos vérticescores ou intensidadesé rápida, mas pode perder um brilho entre vértices
Phongpor fragmentonormaispreserva melhor o brilho especular

No pipeline fixo do OpenGL, glShadeModel(GL_FLAT) usa em toda a primitiva a cor calculada no vértice provocador. Quando o programa envia uma única normal para toda a face, o efeito visual corresponde à tonalização plana, mas isso não significa que a API faça literalmente um único cálculo por face. glShadeModel(GL_SMOOTH) produz tonalização de Gouraud, interpolando os resultados dos vértices. O comando GL_SMOOTH não implementa tonalização de Phong. Esta exige cálculo por fragmento, normalmente em um fragment shader.

Tonalização suave não cria polígonos nem altera a silhueta. Ela muda somente a variação de cor sobre a geometria existente.

A Figura 4 mostra por que essa distinção importa. Os três métodos recebem o mesmo triângulo, mas distribuem o cálculo de iluminação de maneiras diferentes.

Três triângulos iguais. O primeiro tem uma cor constante e uma normal central, representando flat. O segundo tem normais e amostras nos três vértices com cor interpolada, representando Gouraud. O terceiro mostra várias normais interpoladas e um brilho no interior, representando Phong.
Flat usa um resultado por face; Gouraud interpola resultados dos vértices; Phong interpola normais e calcula a luz por fragmento.

Na Figura 5, os três estados usam a mesma malha, fonte direcional e somente reflexão difusa. Compare o primeiro com o segundo para isolar S; compare o primeiro com o terceiro para isolar N. No terceiro, a luz e a normal são constantes dentro de cada face, então os vértices recebem a mesma cor: a interpolação de Gouraud não tem uma variação para suavizar. Os três painéis mantêm o mesmo contorno poligonal.

Três esferas com o mesmo contorno: normais por vértice com Gouraud produzem gradiente suave; as mesmas normais com flat produzem manchas triangulares; normais por face com Gouraud também evidenciam facetas.
Interpolar cores e escolher normais são decisões independentes; nenhuma delas acrescenta geometria à silhueta.

Passo a passo do exemplo​

  1. initializeGL habilita profundidade, descarte, iluminação, GL_LIGHT0 e normalização das normais.
  2. configurar_fonte envia as parcelas ativas e configura a geometria da fonte escolhida.
  3. paintGL envia a fonte depois da câmera no modo mundo; no modo câmera, envia antes de gluLookAt, com MODELVIEW identidade.
  4. desenhar_esfera emite os mesmos triângulos com uma normal por face ou uma normal por vértice.
  5. O tratamento do teclado altera o estado e solicita um novo quadro com update().

S altera apenas glShadeModel; N escolhe as normais. Assim podemos investigar separadamente a interpolação e a orientação usada na reflexão. Como a esfera é simétrica, girá-la evidencia sobretudo as facetas; use J e L para investigar a dependência em relação ao observador.

modelos_iluminacao.py (núcleo da comparação)
if not self.normais_vertices:
self.enviar_normal(normal)
for ponto in triangulo:
if self.normais_vertices:
self.enviar_normal(ponto) # esfera unitária centrada na origem
glVertex3f(*ponto)

enviar_normal chama glNormal3f; com I ativo, troca o sinal dos três componentes, sem alterar os vértices nem a ordem das faces.

No trecho acima, ponto só é uma normal correta porque a esfera tem raio 1 e centro na origem. Em uma malha arbitrária, a posição do vértice não substitui a normal.


Atividades de Laboratório​

Aquecimento — prever antes de executar​

Use os experimentos 1 e 2 durante a leitura. Antes de cada troca de componente, anote sua previsão e confira o título da janela. Ao terminar, responda:

  1. Que componente permite enxergar o material mesmo sem luz direta?
  2. Qual componente revela a orientação sem depender do observador?
  3. No exemplo numérico, recalcule a intensidade com Ks=0K_s=0. Por que o resultado é 0,500{,}50?

Atividade 1 — iluminar o octaedro da Aula 07​

Objetivo. Acrescentar iluminação a uma malha conhecida, distinguindo os papéis da normal, da fonte e do material.

Baixe o arquivo-base octaedro_iluminado_base.py. Ele é independente do laboratório da esfera e usa o mesmo ambiente Python. Na raiz do repositório:

uv run aula-08-modelos-iluminacao/atividades/octaedro_iluminado_base.py

Para o download isolado, execute python octaedro_iluminado_base.py.

Roteiro​

Passo 1 — reconheça o que já funciona. Execute sem editar. Gire com as setas esquerda/direita: o octaedro está preenchido de laranja, mas a cor não varia com a orientação das faces. VERTICES, FACES, normal_face, câmera, teste de profundidade e descarte já estão prontos. Preserve-os.

Confira: as oito faces continuam compondo uma superfície fechada. A iluminação não será usada para corrigir problemas de visibilidade.

Passo 2 — habilite o cálculo (TODO 2). Em initializeGL, habilite GL_LIGHTING, GL_LIGHT0 e GL_NORMALIZE. As cores da fonte e o ambiente global já estão configurados para concentrar a atividade nas novas chamadas.

Confira: glColor3f deixa de determinar o laranja porque GL_COLOR_MATERIAL está desligado. O resultado intermediário ainda usa normal e material padrão; não tente corrigi-lo mudando os vértices.

Passo 3 — conecte luz e geometria (TODOs 3a e 3b). Em paintGL, envie GL_POSITION = (3.0, 4.0, 5.0, 1.0) depois de gluLookAt e antes de glRotatef. No laço de faces, envie normal_face(face) com glNormal3f antes dos três vértices. Consulte o trecho do octaedro na seção de conteúdo.

Confira: ao girar, faces com orientações diferentes recebem intensidades diferentes. Se todas responderem como um único plano, confira se cada face recebe sua própria normal. A posição da fonte deve ser reenviada em cada quadro.

Passo 4 — defina o material (TODO 4). Em initializeGL, configure GL_FRONT com GL_AMBIENT_AND_DIFFUSE = (0.85, 0.45, 0.20, 1.0), GL_SPECULAR = (1.0, 1.0, 1.0, 1.0) e GL_SHININESS = 32.0. Use glMaterialfv para as cores e glMaterialf para o expoente.

Confira: o laranja retorna como propriedade do material. Depois, compare apenas a cor difusa com (0.20, 0.55, 0.85, 1.0) e restaure-a. A fonte e a geometria permanecem iguais. O octaedro usa flat e poucos vértices: não espere um brilho contínuo como o de uma superfície calculada por fragmento.

A Figura 6 compara a execução inicial do arquivo-base com a solução dos quatro TODOs, sem alterar câmera ou vértices. À esquerda, todas as faces têm a mesma cor e a forma parece achatada. À direita, as diferenças de intensidade permitem distinguir as faces. Use essa comparação como referência qualitativa: a rotação e as cores escolhidas no passo 4 podem mudar a aparência final.

Duas capturas do octaedro no mesmo ângulo: à esquerda uma silhueta laranja uniforme; à direita faces superiores laranjas e faces inferiores escuras, sem mudança no contorno.
A iluminação revela as faces de uma geometria que já existia no arquivo-base.

Checklist de conclusão​

  • A malha mantém seis vértices e oito faces, sem alterar a ordem dos índices.
  • Cada face recebe sua normal antes dos vértices.
  • A fonte é enviada entre a câmera e a transformação do objeto.
  • O material controla a cor e as faces respondem à rotação.

Para responder​

  1. Por que normal_face existir no arquivo não basta para iluminar o objeto?
  2. Por que a cor de glColor3f deixou de controlar a superfície no passo 2?
  3. O que mudaria se a posição da fonte fosse enviada depois de glRotatef?

Atividade 2 — comparar fontes e referenciais​

Objetivo. Relacionar parâmetros da fonte ao resultado, mudando uma variável por comparação. Use modelos_iluminacao.py.

Roteiro​

Passo 1 — fixe as condições. Pressione R, A e E. Confira A=False, D=True e E=False. Preserve objeto e câmera. Compare 1 e 2: a direção até a fonte pontual varia pela superfície; na direcional, é constante.

Passo 2 — investigue o cone. Selecione 3. Mantenha expoente 0 e use O para comparar aberturas 12°, 28° e 45°. O número representa o ângulo entre o eixo e a borda, não a abertura total. Com a abertura menor, uma porção menor da esfera recebe luz. Com 45°, o cone pode cobrir toda a parte voltada à fonte.

Confira: se nada mudar ao pressionar O, confirme fonte=spot no título. Gouraud amostra a iluminação nos vértices; a borda visível do cone na malha grosseira é aproximada.

Passo 3 — investigue a concentração. Volte à abertura 28° e use P para comparar expoentes 0, 12 e 48. A abertura fica fixa; a intensidade cai mais rapidamente longe do eixo quando o expoente cresce. Restaure com R.

A Figura 7 organiza as duas comparações: na linha superior varia apenas a abertura; na inferior, apenas o expoente. O painel de 28° e expoente 0 se repete para servir de referência comum. A borda pode parecer irregular porque o spot é avaliado nos vértices e suas cores são interpoladas em triângulos grandes. Isso é uma limitação desta demonstração com Gouraud, não uma mudança na geometria do cone. Neste enquadramento, 28° e 45° produzem praticamente o mesmo resultado: aumentar o cone não acrescenta luz onde a superfície relevante já estava coberta. Não espere uma diferença visível em toda alteração de parâmetro.

Seis capturas da esfera em duas linhas. Acima, aberturas de 12, 28 e 45 graus com expoente zero; abaixo, abertura de 28 graus com expoentes zero, 12 e 48. O cone estreito cobre uma área menor e os expoentes maiores escurecem as regiões longe do eixo.
A abertura limita a região atingida; o expoente controla como a intensidade varia dentro dela.

Passo 4 — separe os referenciais. Pressione 2, A e E, mantendo somente difusa. Orbite com J e L no modo mundo. A luz permanece fixa em relação à superfície, embora você a veja de outros ângulos. Pressione R, 2, A, E e C e repita a mesma órbita: a direção da luz acompanha a câmera. Localize em paintGL as duas posições possíveis de configurar_fonte.

Passo 5 — confirme a dependência especular. Pressione R, 2 e A. Com D e E ativas e luz no mundo, orbite. Repita a órbita com E desligada para separar o destaque especular da variação da região visível. Compare brilho 8 e 96 usando [ e ], conferindo o número no título. Um expoente alto pode fazer o brilho desaparecer entre os vértices da esfera pouco subdividida.

Checklist de conclusão​

  • Abertura e expoente spot foram comparados separadamente.
  • A câmera foi movimentada nos dois referenciais, com o objeto parado.
  • A explicação diferencia direção da luz, direção do observador e normal.

Para responder​

  1. Por que aumentar o expoente spot não equivale a diminuir a abertura?
  2. Qual ordem de chamadas prende a luz à câmera?
  3. Por que o brilho pode desaparecer com expoentes altos em Gouraud?

Atividade 3 — diagnosticar normais e tonalização​

Objetivo. Distinguir geometria, normais e interpolação, usando um defeito reversível. Continue no laboratório da esfera.

Roteiro​

Passo 1 — mude apenas a interpolação. Pressione R, 2, A e E. Mantenha normais por vértice e use S para comparar Gouraud e flat. A geometria e as normais são iguais: flat espalha a cor de um vértice por cada triângulo; Gouraud interpola as cores. A silhueta continua poligonal.

Passo 2 — mude apenas as normais. Pressione R, 2, A e E outra vez. Mantenha Gouraud e alterne N. Com normal por face, os três vértices de cada triângulo têm a mesma orientação. Sob luz direcional e somente difusa, isso produz uma intensidade constante por face mesmo com GL_SMOOTH.

Confira: suavizar a interpolação não inventa normais de uma superfície curva. Para recuperar a aparência suave, volte a normais por vértice com N.

Passo 3 — introduza um erro de normal. Com as condições do passo 2 restauradas, pressione I. Ele inverte todas as normais enviadas por enviar_normal, sem mudar a ordem dos vértices. A região clara muda, mas nenhuma face passa a ser descartada por isso. Pressione I novamente para corrigir. Depois deixe somente ambiente (D, A) e repita: a normal não participa desse termo, portanto inverter seu sinal não muda a cor.

A Figura 8 registra somente difusa direcional com normais por vértice e Gouraud. Com I, a parte originalmente voltada para longe da luz passa a receber a contribuição difusa. A silhueta e os triângulos visíveis são os mesmos, pois o descarte continua usando a ordem dos vértices. Para reparar esse defeito, restaure o sinal das normais; desligar o descarte não o corrige.

Duas esferas com contornos idênticos: a primeira tem iluminação na região superior direita; na segunda, com normais invertidas, a região superior direita escurece e a luz aparece no lado oposto.
Inverter as normais muda a reflexão sem inverter a orientação geométrica das faces.

Passo 4 — relacione o sintoma à causa. Complete a associação: silhueta poligonal → tesselação; iluminação voltada para o lado errado → normais; face que desaparece com descarte → ordem dos vértices. Encerre com R.

Checklist de conclusão​

  • S e N foram testados separadamente, com a mesma fonte e componentes.
  • A inversão das normais mudou a difusa, mas não a ambiente nem o descarte.
  • O estado original foi restaurado e cada sintoma foi associado à sua causa.

Para responder​

  1. Por que Gouraud com normais por face pode continuar parecendo facetado?
  2. Por que inverter glNormal3f não produz o mesmo efeito de trocar dois índices?
  3. Qual alteração suaviza a silhueta: mudar a tonalização ou subdividir a malha?

Exercícios (checkpoints)​

Questões dissertativas​

Q

Por que a reflexão difusa não depende da posição do observador, mas a especular depende?

Q

Uma esfera com GL_SMOOTH ainda apresenta uma silhueta poligonal. Isso indica falha na iluminação?

Q

Um brilho especular desaparece em Gouraud, mas surge com iluminação por fragmento. Qual é a causa?

Questões objetivas​

Quiz4 questões

1. Qual valor de w em GL_POSITION representa uma fonte direcional?

  • a)0
  • b)1
  • c)A abertura do spot
  • d)O expoente especular
  • e)A quantidade de luzes

2. Qual expressão controla a parcela difusa de Lambert?

  • a)O produto escalar entre normal e direção da luz
  • b)A distância entre dois vértices
  • c)A ordem de desenho das faces
  • d)A área do viewport
  • e)O valor armazenado no depth buffer

3. O que a tonalização de Gouraud interpola no interior do triângulo?

  • a)Cores ou intensidades calculadas nos vértices
  • b)Novos vértices
  • c)Profundidades já ordenadas
  • d)A posição da câmera
  • e)Índices do arquivo OBJ

4. O que tende a acontecer quando GL_SHININESS aumenta?

  • a)O brilho especular fica menor e mais concentrado
  • b)A luz ambiente aumenta
  • c)A malha ganha triângulos
  • d)A fonte vira direcional
  • e)O culling é desativado

Referências​

Principais (essenciais)​

  • HEARN, D.; BAKER, M. P.; CARITHERS, W. R. Computer Graphics with OpenGL. 4. ed. Pearson Prentice Hall, 2011. (004.92 H436co)
  • FOLEY, J. D. et al. Computer Graphics: Principles and Practice. 3. ed. Addison-Wesley, 2013. (004.92 C738)
  • The Khronos Group. OpenGL 2.1 Reference Pages — glLight, glMaterial e glShadeModel. Disponível em: registry.khronos.org/OpenGL-Refpages/gl2.1

Aprofundamento (opcionais)​

  • COHEN, M.; MANSSOUR, I. H. OpenGL: uma abordagem prática e objetiva. São Paulo: Novatec, 2006. (004.92 C678o)
  • PHONG, B. T. Illumination for computer generated pictures. Communications of the ACM, v. 18, n. 6, p. 311–317, 1975.
  • GOURAUD, H. Continuous shading of curved surfaces. IEEE Transactions on Computers, v. C-20, n. 6, p. 623–629, 1971.