// Iluminacao.c - Isabel H. Manssour
// Um programa OpenGL que exemplifica a visualização
// de objetos 3D com a inserção de uma fonte de luz.
// Este código está baseado nos exemplos disponíveis no livro
// "OpenGL SuperBible", 2nd Edition, de Richard S. e Wright Jr.
#include <gl/glut.h>
GLfloat angle, fAspect;
// Função callback chamada para fazer o desenho
void Desenha(void)
{
// Limpa a janela e o depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(0.0f, 0.0f, 1.0f);
// Desenha o teapot com a cor corrente (solid)
glutSolidTeapot(50.0f);
glutSwapBuffers();
}
// Inicializa parâmetros de rendering
void Inicializa (void)
{
GLfloat luzAmbiente[4]={0.2,0.2,0.2,1.0};
GLfloat luzDifusa[4]={0.7,0.7,0.7,1.0}; // "cor"
GLfloat luzEspecular[4]={1.0, 1.0, 1.0, 1.0};// "brilho"
GLfloat posicaoLuz[4]={0.0, 50.0, 50.0, 1.0};
// Capacidade de brilho do material
GLfloat especularidade[4]={1.0,1.0,1.0,1.0};
GLint especMaterial = 60;
// Especifica que a cor de fundo da janela será preta
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// Habilita o modelo de colorização de Gouraud
glShadeModel(GL_SMOOTH);
// Define a refletância do material
glMaterialfv(GL_FRONT,GL_SPECULAR, especularidade);
// Define a concentração do brilho
glMateriali(GL_FRONT,GL_SHININESS,especMaterial);
// Ativa o uso da luz ambiente
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, luzAmbiente);
// Define os parâmetros da luz de número 0
glLightfv(GL_LIGHT0, GL_AMBIENT, luzAmbiente);
glLightfv(GL_LIGHT0, GL_DIFFUSE, luzDifusa );
glLightfv(GL_LIGHT0, GL_SPECULAR, luzEspecular );
glLightfv(GL_LIGHT0, GL_POSITION, posicaoLuz );
// Habilita a definição da cor do material a partir da cor corrente
glEnable(GL_COLOR_MATERIAL);
//Habilita o uso de iluminação
glEnable(GL_LIGHTING);
// Habilita a luz de número 0
glEnable(GL_LIGHT0);
// Habilita o depth-buffering
glEnable(GL_DEPTH_TEST);
angle=45;
}
// Função usada para especificar o volume de visualização
void EspecificaParametrosVisualizacao(void)
{
// Especifica sistema de coordenadas de projeção
glMatrixMode(GL_PROJECTION);
// Inicializa sistema de coordenadas de projeção
glLoadIdentity();
// Especifica a projeção perspectiva
gluPerspective(angle,fAspect,0.4,500);
// Especifica sistema de coordenadas do modelo
glMatrixMode(GL_MODELVIEW);
// Inicializa sistema de coordenadas do modelo
glLoadIdentity();
// Especifica posição do observador e do alvo
gluLookAt(0,80,200, 0,0,0, 0,1,0);
}
// Função callback chamada quando o tamanho da janela é alterado
void AlteraTamanhoJanela(GLsizei w, GLsizei h)
{
// Para previnir uma divisão por zero
if ( h == 0 ) h = 1;
// Especifica o tamanho da viewport
glViewport(0, 0, w, h);
// Calcula a correção de aspecto
fAspect = (GLfloat)w/(GLfloat)h;
EspecificaParametrosVisualizacao();
}
// Função callback chamada para gerenciar eventos do mouse
void GerenciaMouse(int button, int state, int x, int y)
{
if (button == GLUT_LEFT_BUTTON)
if (state == GLUT_DOWN) { // Zoom-in
if (angle >= 10) angle -= 5;
}
if (button == GLUT_RIGHT_BUTTON)
if (state == GLUT_DOWN) { // Zoom-out
if (angle <= 130) angle += 5;
}
EspecificaParametrosVisualizacao();
glutPostRedisplay();
}
// Programa Principal
int main(void)
{
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(400,350);
glutCreateWindow("Visualizacao 3D");
glutDisplayFunc(Desenha);
glutReshapeFunc(AlteraTamanhoJanela);
glutMouseFunc(GerenciaMouse);
Inicializa();
glutMainLoop();
}
Obs.: Clique aqui para
fazer o download deste programa.
Figura 15.1 - Saída do programa Iluminacao.c
As funções utilizadas neste exemplo, e que não foram descritas no
capítulo anterior, são apresentadas a seguir
segundo [Woo 1999] e [Wright 2000].
glShadeModel(GL_SMOOTH);
estabelece o modelo de colorização: GL_FLAT (a cor não varia na primitiva que é desenhada -
um exemplo de primitiva é o triângulo); ou GL_SMOOTH (a cor de cada ponto da primitiva é
interpolada a partir da cor calculada nos vértices). Seu protótipo é:
void glShadeModel(GLenum mode);.
Descrição dos parâmetros: mode especifica o modelo de colorização, sendo que o default
é GL_SMOOTH [Wright 2000].
glMaterialfv(GL_FRONT,GL_SPECULAR, especularidade);
estabelece os parâmetros do material que serão usados pelo modelo de iluminação.
Possui algumas variações cujos protótipos são:
glMaterialf(GLenum face, GLenum pname, GLfloat param);
glMateriali(GLenum face, GLenum pname, GLint param);
glMaterialfv(GLenum face, GLenum pname, const GLfloat *params);
glMaterialiv(GLenum face, GLenum pname, const GLint *params);
Descrição dos parâmetros:
face determina se as propriedades do material dos polígonos que estão sendo
especificadas são front (GL_FRONT), back (GL_BACK) ou ambas (GL_FRONT_AND_BACK);
pname para as duas primeiras variações especifica o parâmetro de um único valor que
está sendo determinado (atualmente apenas GL_SHININESS possui um único valor como parâmetro);
para as duas últimas variações, que recebem um vetor como parâmetro, pode determinar as
seguintes propriedades do material: GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR, GL_EMISSION,
GL_SHININESS, GL_AMBIENT_AND_DIFFUSE ou GL_COLOR_INDEXES;
param (GLfloat ou GLint) especifica o valor que será atribuído para o
parâmetro determinado por pname (neste caso, GL_SHININESS);
params (GLfloat* ou GLint*) um vetor de números reais ou inteiros que contém
as componentes da propriedade que está sendo espeficada;
Através desta função é possível determinar as propriedades de refletância do material
dos polígonos. As propriedades GL_AMBIENT, GL_DIFFUSE e GL_SPECULAR afetam a maneira na qual
as componentes de luz incidente são refletidas. GL_EMISSION é usado para materiais que possuem
"luz própria". GL_SHININESS pode variar de 0 a 128 (quanto maior o valor, maior é a área de
highlight especular na superfície). GL_COLOR_INDEXES é usado para as propriedades de
refletância do material no modo de índice de cores [Wright 2000].
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, luzAmbiente);
estabelece os parâmetros do modelo de iluminação usado por OpenGL. É possível especificar
um, ou todos os três modelos:
- GL_LIGHT_MODEL_AMBIENT é usado para especificar a luz ambiente default para uma
cena, que tem um valor RGBA default de (0.2, 0.2, 0.2, 1.0);
- GL_LIGHT_MODEL_TWO_SIDE é usado para indicar se ambos os lados de um polígono são
iluminados (por default apenas o lado frontal é iluminado);
- GL_LIGHT_MODEL_LOCAL_VIEWER modifica o cálculo dos ângulos de reflexão especular;
Possui algumas variações cujos protótipos são:
glLightModelf(GLenum pname, GLfloat param);
glLightModeli(GLenum pname, GLint param);
glLightModelfv(GLenum pname, const GLfloat *params);
glLightModeliv(GLenum pname, const GLint *params);
Descrição dos parâmetros:
pname especifica um parâmetro do modelo de iluminação: GL_LIGHT_MODEL_AMBIENT,
GL_LIGHT_MODEL_LOCAL_VIEWER ou GL_LIGHT_MODEL_TWO_SIDE;
param (GLfloat ou GLint) para GL_LIGHT_MODEL_LOCAL_VIEWER um valor 0.0
indica que os ângulos da componente especular tomam a direção de visualização como sendo
paralela ao eixo z, e qualquer outro valor indica que a visualização ocorre a partir da origem
do sistema de referência da câmera; para GL_LIGHT_MODEL_TWO_SIDE um valor 0.0 indica que
somente os polígonos frontais são incluídos nos cálculos de iluminação, e qualquer outro
valor indica que todos os polígonos são incluídos nos cálculos de iluminação;
params (GLfloat* ou GLint*) para GL_LIGHT_MODEL_AMBIENT ou
GL_LIGHT_MODEL_LOCAL_VIEWER, aponta para um vetor de números inteiros ou reais;
para GL_LIGHT_MODEL_AMBIENT o conteúdo do vetor indica os valores das componentes RGBA
da luz ambiente [Wright 2000].
glLightfv(GL_LIGHT0, GL_AMBIENT, luzAmbiente);
estabelece os parâmetros da fonte de luz para uma das oito fontes de luz disponíveis. Possui
algumas variações cujos protótipos são:
glLightf(GLenum light, GLenum pname, GLfloat param);
glLighti(GLenum light, GLenum pname, GLint param);
glLightfv(GLenum light, GLenum pname, const GLfloat *params);
glLightiv(GLenum light, GLenum pname, const GLint *params);
As duas primeiras variações requerem apenas um único valor para determinar
uma das seguintes propriedades: GL_SPOT_EXPONENT, GL_SPOT_CUTOFF, GL_CONSTANT_ATTENUATION,
GL_LINEAR_ATTENUATION e GL_QUADRATIC_ATTENUATION. As duas últimas variações são usadas
para parâmetros de luz que requerem um vetor com múltiplos valores (GL_AMBIENT, GL_DIFFUSE,
GL_SPECULAR, GL_POSITION e GL_SPOT_DIRECTION).
Descrição dos parâmetros:
light especifica qual fonte de luz está sendo alterada (varia de 0 a
GL_MAX_LIGHTS); valores constantes de luz são enumerados de GL_LIGHT0 a GL_LIGHT7
pname especifica qual parâmetro de luz está sendo determinado pela
chamada desta função (GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR, GL_POSITION, GL_SPOT_DIRECTION,
GL_SPOT_EXPONENT, GL_SPOT_CUTOFF. GL_CONSTANT_ATTENUATION, GL_LINEAR_ATTENUATION,
GL_QUADRATIC_ATTENUATION);
param (GLfloat ou GLint) para parâmetros que são especificados por um
único valor (param); estes parâmetros, válidos somente para spotlights, são
GL_SPOT_EXPONENT, GL_SPOT_CUTOFF, GL_CONSTANT_ATTENUATION, GL_LINEAR_ATTENUATION e
GL_QUADRATIC_ATTENUATION.
params (GLfloat* ou GLint*) um vetor de valores que descrevem os
parâmetros que estão sendo especificados [Wright 2000].
glEnable(GL_COLOR_MATERIAL);
conforme já explicado no capítulo 6, a função
glEnable é usada para habilitar uma variável de estado OpenGL. Neste caso,
estão sendo habilitadas: GL_COLOR_MATERIAL (atribui a cor para o material a partir
da cor corrente), GL_DEPTH_TEST (controla as comparações de profundidade e
atualiza o depth buffer), GL_LIGHTING (habilita a iluminação) e GL_LIGHT0
(habilita a luz de número 0) [Woo 1999].
glutSwapBuffers(); e
glutInitDisplayMode(GLUT_DOUBLE...); já
explicadas anteriormente,
são usadas para evitar que a imagem fique "piscando" a cada interação (por exemplo,
quando se faz zoom-in e zoom-out).
Também é possível eliminar
o "brilho" do objeto, como se o material fosse opaco. Neste caso, basta eliminar a componente
especular removendo as seguintes linhas do código fonte:
GLfloat especularidade[4]={1.0,1.0,1.0,1.0};
GLint especMaterial = 60;
glMaterialfv(GL_FRONT,GL_SPECULAR, especularidade);
glMateriali(GL_FRONT,GL_SHININESS,especMaterial);
glLightfv(GL_LIGHT0, GL_SPECULAR, luzEspecular );
Comentários, dúvidas, sugestões, envie um mail para [email protected]