Ponto V!

Home OpenGL Luzes na prática – Parte 3
Vinícius Godoy de Mendonça
Luzes na prática – Parte 3Imprimir
Escrito por Vinícius Godoy de Mendonça

Nos artigos anteriores, vimos como desenhar e especificar as luzes na OpenGL. Neste último artigo sobre luzes, estudaremos o tipo de luz spotlight e mais alguns detalhes interessantes sobre iluminação.

Atenuação da luz

Você já deve ter notado que quanto mais longe você fica de uma origem de luz, mais fraca a iluminação se torna. Esse fenômeno é chamado de atenuação. A OpenGL possui um fator de atenuação, que pode reduzir o efeito da contribuição da luz sobre a cor de um objeto dependendo da distância em que ele se encontra da sua origem. O fator de atenuação é calculado com a seguinte fórmula:

Fórmula da atenuação da luz

Onde d é a distância da luz até o vértice e o resto dos parâmetros são definidos a seguir:

  • Kc: Chamado de atenuação constante. A luz já sairá atenuada por esse valor, e essa atenuação se manterá. É útil para criar efeitos ou para fazer pequenos ajustes. É definido usando a constante GL_CONSTANT_ATTENUATION;
  • Kl: Chamado de atenuação linear. Note que esse valor é multiplicado pela distância do vértice, o que significa que quanto mais longe o ponto estiver, maior será sua atenuação. A iluminação de um lampião no escuro sofreria esse tipo de atenuação. Ela é definida pela constante GL_LINEAR_ATTENUATION;
  • Kq: Chamado de atenuação quadrática. O valor é multiplicado pela distância do vértice elevada ao quadrado, o que significa, que a luz perde sua intensidade rapidamente. A iluminação de um holofote na neblina, ou em baixo d’agua, por exemplo, seria um exemplo desse tipo de atenuação.É definida pela constante GL_QUADRATIC_ATTENUATION;

Apesar de produzir um efeito bonito, a atenuação tem um preço. Ela deve ser calculada para cada objeto na cena, o que implica em perda de performance. Portanto, use-a com cuidado e apenas se necessário.

Spotlights

Spotlight Spotlights são luzes que partem de uma origem específica e se propagam em uma direção, formando um cone de luz. Lanternas e holofotes, por exemplo, produzem esse tipo de iluminação. Para criar uma spotlight, você define a posição da luz como faria para qualquer luz posicional, e então, define uma série de parâmetros extras: direção, ângulo de abertura e foco.

Se você olhar para um holofote na escuridão total, verá que na posição para onde ele aponta se projeta um cone. Com a OpenGL é possível definir o quão largo será esse cone apenas definindo um ângulo de abertura em relação ao centro. Usamos para isso o parâmetro GL_SPOT_CUTOFF.

Um GL_SPOT_CUTOFF de 15 graus, por exemplo, produz um cone de abertura de 30 graus, 15 em cada direção. A OpenGL aceita valores de 0º até 90º e o valor especial 180º (padrão), que é usado para transformar uma spotlight numa luz normal novamente.

Além disso, devemos especificar a direção do spotlight através da propriedade GL_SPOT_DIRECTION, passando um array com apenas três floats contendo um vetor (x,y,z), preferencialmente unitário, apontado para o local onde o spotlight está virado. Por padrão esse vetor tem coordenadas de (0.0, 0.0,-1.0).

Finalmente, especificamos também o expoente com o parâmetro GL_SPOT_EXPONENT. Ele nada mais é do que uma medida de quão concentrada a luz é no centro. A medida que se afasta do centro, a luz se atenua até que não haja apenas escuridão. Quanto maior for o expoente, mais concentrada será a luz.

Abaixo, a figura ilustra essas propriedades. O expoente não aparece no desenho, mas ele é que dá o foco branco de luz concentrada, no centro:

Spotlight

Para construir essa spotlight, daríamos a seguinte sequência de comandos:

//Ligamos a luz
glEnable(GL_LIGHT0);

//15º de abertura
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 15); 

//Definimos a direção: para direita
float spotDirection = {0.1f, 0.0f, 0.0f};
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, spotDirection);

//Definimos um expoente pequeno.
glLightfv(GL_LIGHT0, GL_SPOT_EXPONENT, 5);

Eu fiz tudo certo, mas não parece a lanterna do Doom 3!

Infelizmente, o cone de luz do spotlight não é visível. Não só isso, ele iluminará apenas os vértices que forem atingidos pela luz. Tentar projetar o spotlight sobre uma parede traçada por dois triângulos é no mínimo frustrante: se o spot atingir apenas o centro, nada se ilumina, pois nenhum vértice é atingido. Se ela atingir um dos vértices, um canto da parede se ilumina.

Agora, o spotlight sobre uma malha, ou sobre vários pequenos triângulos já produz efeitos interessantes e, provavelmente o designer do seu jogo saberá aproveitá-los. Veremos técnicas de como produzir lanternas mais convincentes algum dia no futuro.

Iluminação de uma ou duas faces

Vimos os artigos passados que podemos definir a iluminação global, lembram-se? Esse não é o único aspecto do modelo de iluminação que podemos personalizar.

Normalmente, a OpenGL só calcula a direção da luz na face em que foi definida a normal de luz. E isso geralmente é suficiente para um bom efeito. Entretanto, numa figura vazada, como um violão ou uma caixa, você pode querer que ela calcule as normais em ambos os lados do polígono.

Para alterar essa propriedade, você deve definir a propriedade GL_LIGHT_MODEL_TWO_SIDE como verdadeiro, como no comando abaixo:

glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);

Logicamente, isso implica em mais cálculos de luz, o que pode reduzir um pouco a performance da sua aplicação. E, como você já deve ter deduzido, é possível desligar a propriedade passando GL_FALSE para a mesma função. Quando a propriedade está ligada, a OpenGL simplesmente inverterá as normais para a outra face do polígono para só então efetuar os cálculos de iluminação.

Observador no local ou no infinito

Durante o cálculo do componente especular das luzes, tanto a direção do vértice, quanto o local onde o observador está situado são levados em conta. O parâmetro GL_LIGHT_MODEL_LOCAL_VIEWER permite que você diga se esse observador é local, e baseado na posição da câmera, ou está infinitamente distante (padrão).

Ativar essa propriedade gera uma cena mais realista, porém, implica num custo extra de processamento já que a direção terá que ser calculada para cada vértice. Ativar essa propriedade não é muito diferente do que a propriedade anterior:

glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);

A diferença entre um observador local e no infinito é mais evidente quando se está próximo dos objetos observados. O custo dessa propriedade é significativo, então, use-o apenas se realmente necessário.

Concluindo

E chegamos ao fim de nossos artigos de luzes! Obviamente, esses tópicos cobrem apenas o básico, não vimos como criar efeitos mais avançados como sombras ou reflexo, nem qualquer das funções de extensão da OpenGL. Porém, eles já dão um excelente ponto de partida para a implementação de jogos simples, como o Campeonato Bola Gelada.

O que vem pela frente? Nos próximos artigos, abordaremos texturas, transparência e criaremos uma classe melhor para controle da câmera.

Há muita coisa por vir! Até lá!


Comentários (2)
  • Ráfagan
    avatar

    Grande tutorial... Aborda aqueles detalhes que eu sempre estou correndo atrás de saber =D

    Grande mestre Vinícius!

  • Darth Çeqüella  - Bom tutorial
    avatar

    Excelente tutorial. Esperando o tuto de câmeras.
    Já tenho uma câmera implementada, com quaternion e movimentação por curvas de bezier... Mas quero dar uma olha no que posso melhorar ou adicionar ^^

Escrever um comentário
Your Contact Details:
Gravatar enabled
Comentário:
[b] [i] [u] [url] [quote] [code] [img]   
:angry::0:confused::cheer:B):evil::silly::dry::lol::kiss::D:pinch::(:shock:
:X:side::):P:unsure::woohoo::huh::whistle:;):S:!::?::idea::arrow:
Security
Por favor coloque o código anti-spam que você lê na imagem.
LAST_UPDATED2  

Busca

Linguagens

Twitter