• Olá Visitante, se gosta do forum e pretende contribuir com um donativo para auxiliar nos encargos financeiros inerentes ao alojamento desta plataforma, pode encontrar mais informações sobre os várias formas disponíveis para o fazer no seguinte tópico: leia mais... O seu contributo é importante! Obrigado.

Introdução à OpenGL

helldanger1

GForum VIP
Entrou
Ago 1, 2007
Mensagens
29,631
Gostos Recebidos
1
09. Linhas, Pontos e Polígonos

Com apenas algumas primitivas simples, tais como pontos, linhas e polígonos, é possível criar estruturas complexas. Em outras palavras, objetos e cenas criadas com OpenGL consistem em simples primitivas gráficas que podem ser combinadas de várias maneiras [Wright 2000]. Portanto, OpenGL fornece ferramentas para desenhar pontos, linhas e polígonos, que são formados por um ou mais vértices. Neste caso, é necessário passar uma lista de vértices, o que pode ser feito entre duas chamadas de funções OpenGL:
glBegin()
glEnd()
O argumento passado para glBegin() determina qual objeto será desenhado. No exemplo fornecido por [Hill 2000], para desenhar três pontos pretos foi usada a seguinte seqüência de comandos:
glBegin(GL_POINTS);
glColor3f(0.0f, 0.0f, 0.0f);
glVertex2i(100, 50);
glVertex2i(100, 130);
glVertex2i(150, 130);
glEnd();


Para desenhar outras primitivas, basta trocar GL_POINTS, que exibe um ponto para cada chamada ao comando glVertex, por:

GL_LINES: exibe uma linha a cada dois comandos glVertex;

GL_LINE_STRIP: exibe uma seqüência de linhas conectando os pontos definidos por glVertex;

GL_LINE_LOOP: exibe uma seqüência de linhas conectando os pontos definidos por glVertex e ao final liga o primeiro como último ponto;

GL_POLYGON: exibe um polígono convexo preenchido, definido por uma seqüência de chamadas a glVertex;

GL_TRIANGLES: exibe um triângulo preenchido a cada três pontos definidos por glVertex;

GL_TRIANGLE_STRIP: exibe uma seqüência de triângulos baseados no trio de vértices v0, v1, v2, depois, v2, v1, v3, depois, v2, v3, v4 e assim por diante;

GL_TRIANGLE_FAN: exibe uma seqüência de triângulos conectados baseados no trio de vértices v0, v1, v2, depois, v0, v2, v3, depois, v0, v3, v4 e assim por diante;

GL_QUADS: exibe um quadrado preenchido conectando cada quatro pontos definidos por glVertex;

GL_QUAD_STRIP: exibe uma seqüência de quadriláteros conectados a cada quatro vértices; primeiro v0, v1, v3, v2, depois, v2, v3, v5, v4, depois, v4, v5, v7, v6, e assim por diante [Hill 2000, Pinho 2000].
 

helldanger1

GForum VIP
Entrou
Ago 1, 2007
Mensagens
29,631
Gostos Recebidos
1
A função glVertex2i pertence à biblioteca GL e possui dois argumentos inteiros. De maneira análoga, conforme explicado no capítulo 4, também é possível passar valores de ponto flutuante no lugar de inteiros, e três coordenadas (x,y,z) no lugar de duas usando, por exemplo, as seguintes chamadas às funções OpenGL:
glVertex2d(100.0, 50.0);
glVertex3f(50.0, 50.0, 50.0); Além disso, para cada vértice é possível definir uma cor diferente. Neste caso, no desenho final é feita uma "interpolação" das cores, como mostra o exemplo da figura 8.1.

Para ilustrar a diferença na utilização de algumas primitivas gráficas o código apresentado no capítulo 8 foi alterado da seguinte maneira: inicialmente, os parâmetros passados para a função glutInitWindowSize foram alterados para (200,200), para diminuir o tamanho da janela GLUT; depois, antes da função glBegin(GL_QUADS) foram chamadas as funções glPointSize(3) e glLineWidth(3); finalmente, GL_QUADS, foi substituído por GL_POINTS, GL_LINES, GL_LINE_STRIP e GL_LINE_LOOP, gerando as imagens apresentadas na figura 9.1.

Figura9.1.png


Figura 9.1 - Imagens geradas com a utilização de (a) GL_POINTS, (b) GL_LINES, (c) GL_LINE_STRIP e (d) GL_LINE_LOOP
 

helldanger1

GForum VIP
Entrou
Ago 1, 2007
Mensagens
29,631
Gostos Recebidos
1
10. Transformações Geométricas

As transformações geométricas são usadas para manipular um modelo, isto é, através delas é possível mover, rotacionar ou alterar a escala de um objeto. A aparência final da cena ou do objeto depende muito da ordem na qual estas transformações são aplicadas.

A biblioteca gráfica OpenGL é capaz de executar transformações de translação, escala e rotação através de uma multiplicação de matrizes. A idéia central destas transformações em OpenGL é que elas podem ser combinadas em uma única matriz, de tal maneira que várias transformações geométricas possam ser aplicadas através de uma única operação.

Isto ocorre porque uma transformação geométrica em OpenGL é armazenada internamente em uma matriz. A cada transformação que é aplicada, esta matriz é alterada e usada para desenhar os objetos a partir daquele momento. A cada nova alteração é feita uma composição de matrizes. Para evitar este efeito "cumulativo", é necessário utilizar as funções glPushMatrix() e glPopMatrix(), que salvam e restauram, respectivamente, a matriz atual em uma pilha interna da OpenGL.

A translação é feita através da função glTranslatef(Tx, Ty, Tz), que pode receber três números float ou double (glTranslated) como parâmetro. Neste caso, a matriz atual é multiplicada por uma matriz de translação baseada nos valores dados.

A rotação é feita através da função glRotatef(Ângulo, x, y, z), que pode receber quatro números float ou double (glRotated) como parâmetro. Neste caso, a matriz atual é multiplicada por uma matriz de rotação de "Ângulo" graus ao redor do eixo definido pelo vetor "x,y,z" no sentido anti-horário.

A escala é feita através da função glScalef(Ex, Ey, Ez), que pode receber três números float ou double (glScaled) como parâmetro. Neste caso, a matriz atual é multiplicada por uma matriz de escala baseada nos valores dados.
 

helldanger1

GForum VIP
Entrou
Ago 1, 2007
Mensagens
29,631
Gostos Recebidos
1
Logo abaixo a função "Desenha" do exemplo do capítulo 8 é alterada para incluir as transformações geométricas de translação e escala. As funções glPushMatrix( ) e glPopMatrix( ) são usadas para que esta transformação não seja aplicada no modelo cada vez que ele é redesenhado [Wright 2000]. A figura 10.1 mostra como o quadrado é exibido após a aplicação das transformações especificadas.
void Desenha(void)
{
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0f, 0.0f, 0.0f);
glTranslatef(-100.0f, -30.0f, 0.0f);
glScalef(1.5f, 0.5f, 1.0f);

glBegin(GL_QUADS);
glVertex2i(100,150);
glVertex2i(100,100);
// Especifica que a cor corrente é azul
glColor3f(0.0f, 0.0f, 1.0f);
glVertex2i(150,100);
glVertex2i(150,150);
glEnd();
glFlush();
}


Figura10.1.png


Figura 10.1 - Saída do programa Quadrado.c após a alteração da função "Desenha"

 

helldanger1

GForum VIP
Entrou
Ago 1, 2007
Mensagens
29,631
Gostos Recebidos
1
11. Animação com OpenGL e GLUT

Para exemplificar como fazer uma animação, como por exemplo mover ou girar objetos, será retomado o exemplo do capítulo 8, que desenha um quadrado numa janela com fundo preto. Agora, o quadrado será movido numa direção até bater em uma das bordas da janela e então mudar de direção.

É possível criar um laço que continuamente altera as coordenadas do objeto antes de chamar a função "Desenha". Isto daria a impressão de que o quadrado se move na janela. Porém, a biblioteca GLUT fornece a possibilidade de registrar uma função callback que torna mais fácil o processo de fazer uma simples animação. A função glutTimerFunc pega o nome da função callback que deve ser chamada e o tempo que ela deve esperar antes de chamar a função. A seguir é apresentado o código do exemplo de animação, e na seqüência as novas funções utilizadas são descritas [Wright 2000].
// Anima.c - Isabel H. Manssour
// Um programa OpenGL simples que mostra a animação
// de quadrado em uma janela GLUT.
// Este código está baseado no Bounce.c, exemplo
// disponível no livro "OpenGL SuperBible",
// 2nd Edition, de Richard S. e Wright Jr.

#include <windows.h>
#include <gl/glut.h>

// Tamanho e posição inicial do quadrado
GLfloat x1 = 100.0f;
GLfloat y1 = 150.0f;
GLsizei rsize = 50;

// Tamanho do incremento nas direções x e y
// (número de pixels para se mover a cada
// intervalo de tempo)
GLfloat xstep = 1.0f;
GLfloat ystep = 1.0f;

// Largura e altura da janela
GLfloat windowWidth;
GLfloat windowHeight;


// Função callback chamada para fazer o desenho
void Desenha(void)
{
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

// Limpa a janela de visualização com a cor de fundo especificada
glClear(GL_COLOR_BUFFER_BIT);

// Especifica que a cor corrente é vermelha
// R G B
glColor3f(1.0f, 0.0f, 0.0f);

// Desenha um quadrado preenchido com a cor corrente
glBegin(GL_QUADS);
glVertex2i(x1,y1+rsize);
glVertex2i(x1,y1);
// Especifica que a cor corrente é azul
glColor3f(0.0f, 0.0f, 1.0f);
glVertex2i(x1+rsize,y1);
glVertex2i(x1+rsize,y1+rsize);
glEnd();

// Executa os comandos OpenGL
glutSwapBuffers();
}

// Função callback chamada pela GLUT a cada intervalo de tempo
// (a window não está sendo redimensionada ou movida)
void Timer(int value)
{
// Muda a direção quando chega na borda esquerda ou direita
if(x1 > windowWidth-rsize || x1 < 0)
xstep = -xstep;

// Muda a direção quando chega na borda superior ou inferior
if(y1 > windowHeight-rsize || y1 < 0)
ystep = -ystep;

// Verifica as bordas. Se a window for menor e o
// quadrado sair do volume de visualização
if(x1 > windowWidth-rsize)
x1 = windowWidth-rsize-1;

if(y1 > windowHeight-rsize)
y1 = windowHeight-rsize-1;

// Move o quadrado
x1 += xstep;
y1 += ystep;

// Redesenha o quadrado com as novas coordenadas
glutPostRedisplay();
glutTimerFunc(33,Timer, 1);
}

// Inicializa parâmetros de rendering
void Inicializa (void)
{
// Define a cor de fundo da janela de visualização como preta
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}

// Função callback chamada quando o tamanho da janela é alterado
void AlteraTamanhoJanela(GLsizei w, GLsizei h)
{
// Evita a divisao por zero
if(h == 0) h = 1;

// Especifica as dimensões da Viewport
glViewport(0, 0, w, h);

// Inicializa o sistema de coordenadas
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

// Estabelece a janela de seleção (left, right, bottom, top)
if (w <= h) {
windowHeight = 250.0f*h/w;
windowWidth = 250.0f;
}
else {
windowWidth = 250.0f*w/h;
windowHeight = 250.0f;
}

gluOrtho2D(0.0f, windowWidth, 0.0f, windowHeight);
}

// Programa Principal
int main(void)
{
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(400,350);
glutInitWindowPosition(10,10);
glutCreateWindow("Anima");
glutDisplayFunc(Desenha);
glutReshapeFunc(AlteraTamanhoJanela);
glutTimerFunc(33, Timer, 1);
Inicializa();
glutMainLoop();
}
 

helldanger1

GForum VIP
Entrou
Ago 1, 2007
Mensagens
29,631
Gostos Recebidos
1
Obs.:
// Anima.c - Isabel H. Manssour
// Um programa OpenGL simples que mostra a animação
// de quadrado em uma janela GLUT.
// Este código está baseado no Bounce.c, exemplo
// disponível no livro "OpenGL SuperBible",
// 2nd Edition, de Richard S. e Wright Jr.

#include <windows.h>
#include <gl/glut.h>

// Tamanho e posição inicial do quadrado
GLfloat x1 = 100.0f;
GLfloat y1 = 150.0f;
GLsizei rsize = 50;

// Tamanho do incremento nas direções x e y
// (número de pixels para se mover a cada
// intervalo de tempo)
GLfloat xstep = 1.0f;
GLfloat ystep = 1.0f;

// Largura e altura da janela
GLfloat windowWidth;
GLfloat windowHeight;


// Função callback chamada para fazer o desenho
void Desenha(void)
{
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

// Limpa a janela de visualização com a cor de fundo especificada
glClear(GL_COLOR_BUFFER_BIT);

// Especifica que a cor corrente é vermelha
// R G B
glColor3f(1.0f, 0.0f, 0.0f);

// Desenha um quadrado preenchido com a cor corrente
glBegin(GL_QUADS);
glVertex2i(x1,y1+rsize);
glVertex2i(x1,y1);
// Especifica que a cor corrente é azul
glColor3f(0.0f, 0.0f, 1.0f);
glVertex2i(x1+rsize,y1);
glVertex2i(x1+rsize,y1+rsize);
glEnd();

// Executa os comandos OpenGL
glutSwapBuffers();
}

// Função callback chamada pela GLUT a cada intervalo de tempo
// (a window não está sendo redimensionada ou movida)
void Timer(int value)
{
// Muda a direção quando chega na borda esquerda ou direita
if(x1 > windowWidth-rsize || x1 < 0)
xstep = -xstep;

// Muda a direção quando chega na borda superior ou inferior
if(y1 > windowHeight-rsize || y1 < 0)
ystep = -ystep;

// Verifica as bordas. Se a window for menor e o
// quadrado sair do volume de visualização
if(x1 > windowWidth-rsize)
x1 = windowWidth-rsize-1;

if(y1 > windowHeight-rsize)
y1 = windowHeight-rsize-1;

// Move o quadrado
x1 += xstep;
y1 += ystep;

// Redesenha o quadrado com as novas coordenadas
glutPostRedisplay();
glutTimerFunc(33,Timer, 1);
}

// Inicializa parâmetros de rendering
void Inicializa (void)
{
// Define a cor de fundo da janela de visualização como preta
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}

// Função callback chamada quando o tamanho da janela é alterado
void AlteraTamanhoJanela(GLsizei w, GLsizei h)
{
// Evita a divisao por zero
if(h == 0) h = 1;

// Especifica as dimensões da Viewport
glViewport(0, 0, w, h);

// Inicializa o sistema de coordenadas
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

// Estabelece a janela de seleção (left, right, bottom, top)
if (w <= h) {
windowHeight = 250.0f*h/w;
windowWidth = 250.0f;
}
else {
windowWidth = 250.0f*w/h;
windowHeight = 250.0f;
}

gluOrtho2D(0.0f, windowWidth, 0.0f, windowHeight);
}

// Programa Principal
int main(void)
{
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(400,350);
glutInitWindowPosition(10,10);
glutCreateWindow("Anima");
glutDisplayFunc(Desenha);
glutReshapeFunc(AlteraTamanhoJanela);
glutTimerFunc(33, Timer, 1);
Inicializa();
glutMainLoop();
}


glutTimerFunc(33, Timer, 1); estabelece a função Timer previamente definida como a função callback de animação. Seu protótipo é: void glutTimerFunc(unsigned int msecs, void (*func)(int value), int value);. Esta função faz a GLUT esperar msecs milisegundos antes de chamar a função func. É possível passar um valor definido pelo usuário no parâmetro value. Como esta função é "disparada" apenas uma vez, para se ter uma animação contínua é necessário reinicializar o timer novamente na função Timer.

void Timer(int value) é a função chamada pela glutTimerFunc. No exemplo, as variáveis utilizadas para determinar a posição do retângulo são atualizadas nesta função.

Antes de prosseguir com a descrição das funções, é necessário explicar o funcionamento do double-buffering, que é uma das características mais importantes em qualquer pacote gráfico que está disponível na GLUT. Double-buffering permite que um desenho seja exibido na tela enquanto está sendo realizado o rendering em um offscreen buffer. Então, um comando de swap coloca a imagem na tela instantaneamente. Isto é útil, principalmente, por dois motivos:
- Alguns desenhos complexos podem levar um certo tempo para serem feitos, e não é desejado que cada passo da composição da imagem seja visível; então, é possível compor uma imagem e exibi-la somente depois de completa, de maneira que o usuário nunca vê uma imagem parcial, pois ela é exibida somente quando está pronta.
- No caso de uma animação, cada quadro (ou frame) é desenhado no offscreen buffer e é exibido (swapped) rapidamente depois de pronto.

glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB), já explicada anteriormente, foi usada para trocar o modo de exibição de GLUT_SINGLE para GLUT_DOUBLE. Isto faz com que todo o rendering seja feito em um offscreen buffer.

glutSwapBuffers(); é usada no lugar da glFlush porque quando é feita a troca (ou swap) de buffers, é realizada implicitamente uma operação de flush. Esta função continua fazendo o flush mesmo que o programa esteja sendo executado no modo single-buffer, porém com uma qualidade bastante inferior [Wright 2000].


 

helldanger1

GForum VIP
Entrou
Ago 1, 2007
Mensagens
29,631
Gostos Recebidos
1
12. Gerenciamento de Eventos (teclado e mouse)

A biblioteca GLUT também contém funções para gerenciar eventos de entrada de teclado e mouse. De acordo com [Woo 1999] e [Wright 2000], estas funções foram descritas a seguir

glutKeyboardFunc
Estabelece a função callback que é chamada pela GLUT cada vez que uma tecla que gera código ASCII é pressionada (por exemplo: a, b, A, b, 1, 2). Além do valor ASCII da tecla, a posição (x,y) do mouse quando a tecla foi pressionada também é retornada. Parâmetros de entrada da função callback: (unsigned char key, int x, int y)

glutSpecialFunc
Estabelece a função callback que é chamada pela GLUT cada vez que uma tecla que gera código não-ASCII é pressionada, tais como Home, End, PgUp, PgDn, F1 e F2. Além da constante que identifica a tecla, a posição corrente (x,y) do mouse quando a tecla foi pressionada também é retornada. Parâmetros de entrada da função callback: (unsigned char key, int x, int y). Os valores válidos para o primeiro parâmetro são: GLUT_KEY_F1, GLUT_KEY_F2, GLUT_KEY_F3, GLUT_KEY_F4, GLUT_KEY_F5, GLUT_KEY_F6, GLUT_KEY_F7, GLUT_KEY_F8, GLUT_KEY_F9, GLUT_KEY_F10, GLUT_KEY_F11, GLUT_KEY_F12, GLUT_KEY_LEFT, GLUT_KEY_UP, GLUT_KEY_RIGHT, GLUT_KEY_DOWN, GLUT_KEY_PAGE_UP, GLUT_KEY_PAGE_DOWN, GLUT_KEY_HOME, GLUT_KEY_END, GLUT_KEY_INSERT.

glutMouseFunc
Estabelece a função callback que é chamada pela GLUT cada vez que ocorre um evento de mouse. Parâmetros de entrada da função callback: (int button, int state, int x, int y). Três valores são válidos para o parâmetro button: GLUT_LEFT_BUTTON, GLUT_MIDDLE_BUTTON e GLUT_RIGHT_BUTTON. O parâmetro state pode ser GLUT_UP ou GLUT_DOWN. Os parâmetros x e y indicam a localização do mouse no momento que o evento ocorreu.

O programa abaixo exemplifica a utilização das funções acima especificadas. Neste caso, foram implementadas as seguintes interações: sempre que o usuário pressiona a tecla "R" ou "r", o retângulo é exibido com a cor vermelha; ao pressionar a tecla "G" ou "g" o retângulo é exibido com a cor verde; pressionar a tecla "B" ou "b" o retângulo é exibido com a cor azul; cada vez que o usuário clica com o botão esquerdo do mouse, o tamanho do retângulo é alterado (vai do centro da janela até a posição onde houve o click do mouse); e cada vez que as teclas KEY_UP e KEY_DOWN são pressionadas ocorre zoom-in e zoom-out, respectivamente.
// Interacao.c - Isabel H. Manssour
// Um programa OpenGL simples que desenha um quadrado em
// uma janela GLUT de acordo com interações do usuário.
// 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 xf, yf, win;
GLint view_w, view_h;

// Função callback chamada para fazer o desenho
void Desenha(void)
{
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glClear(GL_COLOR_BUFFER_BIT);
// Desenha um retângulo preenchido com a cor corrente
glBegin(GL_POLYGON);
glVertex2f(0.0f, 0.0f);
glVertex2f(xf, 0.0f);
glVertex2f(xf, yf);
glVertex2f(0.0f, yf);
glEnd();
glFlush();
}

// Inicializa parâmetros de rendering
void Inicializa (void)
{
// Define a cor de fundo da janela de visualização como preta
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
xf=50.0f;
yf=50.0f;
win=250.0f;
}

// Função callback chamada quando o tamanho da janela é alterado
void AlteraTamanhoJanela(GLsizei w, GLsizei h)
{
// Especifica as dimensões da Viewport
glViewport(0, 0, w, h);
view_w = w;
view_h = h;

// Inicializa o sistema de coordenadas
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D (-win, win, -win, win);
}

// Função callback chamada para gerenciar eventos de teclado
void GerenciaTeclado(unsigned char key, int x, int y)
{
switch (key) {
case 'R':
case 'r':// muda a cor corrente para vermelho
glColor3f(1.0f, 0.0f, 0.0f);
break;
case 'G':
case 'g':// muda a cor corrente para verde
glColor3f(0.0f, 1.0f, 0.0f);
break;
case 'B':
case 'b':// muda a cor corrente para azul
glColor3f(0.0f, 0.0f, 1.0f);
break;
}
glutPostRedisplay();
}

// 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) {
// Troca o tamanho do retângulo, que vai do centro da
// janela até a posição onde o usuário clicou com o mouse
xf = ( (2 * win * x) / view_w) - win;
yf = ( ( (2 * win) * (y-view_h) ) / -view_h) - win;
}
glutPostRedisplay();
}

// Função callback chamada para gerenciar eventos do teclado
// para teclas especiais, tais como F1, PgDn e Home
void TeclasEspeciais(int key, int x, int y)
{
if(key == GLUT_KEY_UP) {
win -= 20;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D (-win, win, -win, win);
}
if(key == GLUT_KEY_DOWN) {
win += 20;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D (-win, win, -win, win);
}
glutPostRedisplay();
}

// Programa Principal
int main(void)
{
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(350,300);
glutInitWindowPosition(10,10);
glutCreateWindow("Exemplo de Interacao");
glutDisplayFunc(Desenha);
glutReshapeFunc(AlteraTamanhoJanela);
glutKeyboardFunc(GerenciaTeclado);
glutMouseFunc(GerenciaMouse);
glutSpecialFunc(TeclasEspeciais);
Inicializa();
glutMainLoop();
}
 

helldanger1

GForum VIP
Entrou
Ago 1, 2007
Mensagens
29,631
Gostos Recebidos
1
Obs:



// Interacao.c - Isabel H. Manssour
// Um programa OpenGL simples que desenha um quadrado em
// uma janela GLUT de acordo com interações do usuário.
// 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 xf, yf, win;
GLint view_w, view_h;

// Função callback chamada para fazer o desenho
void Desenha(void)
{
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glClear(GL_COLOR_BUFFER_BIT);
// Desenha um retângulo preenchido com a cor corrente
glBegin(GL_POLYGON);
glVertex2f(0.0f, 0.0f);
glVertex2f(xf, 0.0f);
glVertex2f(xf, yf);
glVertex2f(0.0f, yf);
glEnd();
glFlush();
}

// Inicializa parâmetros de rendering
void Inicializa (void)
{
// Define a cor de fundo da janela de visualização como preta
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
xf=50.0f;
yf=50.0f;
win=250.0f;
}

// Função callback chamada quando o tamanho da janela é alterado
void AlteraTamanhoJanela(GLsizei w, GLsizei h)
{
// Especifica as dimensões da Viewport
glViewport(0, 0, w, h);
view_w = w;
view_h = h;

// Inicializa o sistema de coordenadas
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D (-win, win, -win, win);
}

// Função callback chamada para gerenciar eventos de teclado
void GerenciaTeclado(unsigned char key, int x, int y)
{
switch (key) {
case 'R':
case 'r':// muda a cor corrente para vermelho
glColor3f(1.0f, 0.0f, 0.0f);
break;
case 'G':
case 'g':// muda a cor corrente para verde
glColor3f(0.0f, 1.0f, 0.0f);
break;
case 'B':
case 'b':// muda a cor corrente para azul
glColor3f(0.0f, 0.0f, 1.0f);
break;
}
glutPostRedisplay();
}

// 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) {
// Troca o tamanho do retângulo, que vai do centro da
// janela até a posição onde o usuário clicou com o mouse
xf = ( (2 * win * x) / view_w) - win;
yf = ( ( (2 * win) * (y-view_h) ) / -view_h) - win;
}
glutPostRedisplay();
}

// Função callback chamada para gerenciar eventos do teclado
// para teclas especiais, tais como F1, PgDn e Home
void TeclasEspeciais(int key, int x, int y)
{
if(key == GLUT_KEY_UP) {
win -= 20;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D (-win, win, -win, win);
}
if(key == GLUT_KEY_DOWN) {
win += 20;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D (-win, win, -win, win);
}
glutPostRedisplay();
}

// Programa Principal
int main(void)
{
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(350,300);
glutInitWindowPosition(10,10);
glutCreateWindow("Exemplo de Interacao");
glutDisplayFunc(Desenha);
glutReshapeFunc(AlteraTamanhoJanela);
glutKeyboardFunc(GerenciaTeclado);
glutMouseFunc(GerenciaMouse);
glutSpecialFunc(TeclasEspeciais);
Inicializa();
glutMainLoop();
}

:right:
 

helldanger1

GForum VIP
Entrou
Ago 1, 2007
Mensagens
29,631
Gostos Recebidos
1
14. Programando em 3D

Os exemplos apresentados até aqui mostraram apenas desenhos 2D. Este capítulo descreve como trabalhar em 3D usando OpenGL. As bibliotecas GLU e GLUT possuem uma série de funções para desenhar primitivas 3D, tais como esferas, cones, cilindros e teapot. Em 3D se assume que o processo utilizado para visualizar uma determinada cena é análogo a tirar uma fotografia com uma máquina fotográfica, o que inclui, segundo [Woo 1999], os seguintes passos:

Arrumar o tripé e posicionar a câmera para fotografar a cena - equivalente a especificar as transformações de visualização (veja a função gluLookAt descrita mais abaixo);
Arrumar a cena para ser fotografada, incluindo ou excluindo objetos/pessoas - equivalente à etapa de modelagem (inclui as tranformações geométricas, glTranslatef, glScalef, glRotatef, e o desenho dos objetos);
Escolher a lente da câmera ou ajustar o zoom - equivalente a especificar as transformações de projeção (veja a função gluPerspective descrita mais abaixo);
Determinar o tamanho final da foto (maior ou menor) - equivalente a especificar a viewport (funções glViewport e ChangeSize).


O exemplo abaixo exemplifica a utilização das funções OpenGL para visualização 3D.
// TeaPot3D.c - Isabel H. Manssour
// Um programa OpenGL que exemplifica a visualização
// de objetos 3D.
// 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)
{
glClear(GL_COLOR_BUFFER_BIT);

glColor3f(0.0f, 0.0f, 1.0f);

// Desenha o teapot com a cor corrente (wire-frame)
glutWireTeapot(50.0f);

// Executa os comandos OpenGL
glutSwapBuffers();
}

// Inicializa parâmetros de rendering
void Inicializa (void)
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
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.1,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);
glutInitWindowSize(350,300);
glutCreateWindow("Visualizacao 3D");
glutDisplayFunc(Desenha);
glutReshapeFunc(AlteraTamanhoJanela);
glutMouseFunc(GerenciaMouse);
Inicializa();
glutMainLoop();
 

helldanger1

GForum VIP
Entrou
Ago 1, 2007
Mensagens
29,631
Gostos Recebidos
1
O programa apresentado acima, como mostra a figura 14.1, apenas exibe um teapot (ou bule de chá) azul, no formato wire-frame, numa janela com fundo preto. Ao posicionar o mouse sobre a janela e clicar com o botão esquerdo e direito, é possível obter zoom-in e zoom-out, respectivamente. As novas funções utilizadas neste exemplo são descritas a seguir.


Figura14.1.png


Figura 14.1 - Saída do programa TeaPot3D.c

gluPerspective(angle,fAspect,0.1,500); segundo [Wright 2000], esta função estabelece os parâmetros da Projeção Perspectiva, atualizando a matriz de projeção perspectiva. Seu protótipo é: void gluPerspective( GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar );. Descrição dos parâmetros: fovy é o ângulo, em graus, na direção y (usada para determinar a "altura" do volume de visualização); aspect é a razão de aspecto que determina a área de visualização na direção x, e seu valor é a razão em x (largura) e y (altura); zNear, que sempre deve ter um valor positivo maior do que zero, é a distância do observador até o plano de corte mais próximo (em z); zFar, que também sempre tem um valor positivo maior do que zero, é a distância do observador até o plano de corte mais afastado (em z). Esta função sempre deve ser definida ANTES da função gluLookAt, e no modo GL_PROJECTION.

gluLookAt(0,80,200, 0,0,0, 0,1,0); define a transformação de visualização. Através dos seus argumentos é possível indicar a posição da câmera e para onde ela está direcionada. Seu protótipo é: void gluLookAt( GLdouble eyex, GLdouble eyey, GLdouble eyez, GLdouble centerx, GLdouble centery, GLdouble centerz, GLdouble upx, GLdouble upy, GLdouble upz );. Descrição dos parâmetros: eyex, eyey e eyez são usados para definir as coordenadas x, y e z, respectivamente, da posição da câmera (ou observador); centerx, centery e centerz são usados para definir as coordenadas x, y e z, respectivamente, da posição do alvo, isto é, para onde o observador está olhando (normalmente, o centro da cena); upx, upy e upz são as coordenadas x, y e z, que estabelecem o vetor up (indica o "lado de cima" de uma cena 3D) [Wright 2000].

glutWireTeapot(50.0f); é usada para desenhar o wire-frame de um teapot (ou bule de chá). Seu protótipo é: glutWireTeapot(GLdoouble size);, onde o parâmetro size indica um raio aproximado do teapot. Uma esfera com este raio irá "envolver" totalmente o modelo [Wright 2000].

 

helldanger1

GForum VIP
Entrou
Ago 1, 2007
Mensagens
29,631
Gostos Recebidos
1
Assim como o teapot, a biblioteca GLUT também possui funções para desenhar outros objetos 3D. Estas funções estão listadas abaixo [Woo 1999]:
- void glutWireCube(GLdouble size);
- void glutWireSphere(GLdouble radius, GLint slices, GLint stacks);
- void glutWireCone(GLdouble radius, GLdouble height, GLint slices, GLint stacks);
- void glutWireTorus(GLdouble innerRadius, GLdouble outerRadius, GLint nsides, GLint rings);
- void glutWireIcosahedron(void);
- void glutWireOctahedron(void);
- void glutWireTetrahedron(void);
- void glutWireDodecahedron(GLdouble radius);
Os parâmetros slices e stacks que aparecem no protótipo de algumas funções, significam, respectivamente, o número de subdivisões em torno do eixo z (como se fossem linhas longitudinais) e o número de subdivisões ao longo do eixo z (como se fossem linhas latitudinais). Já rings e nsides correspondem, respectivamente, ao número de seções que serão usadas para formar o torus, e ao número de subdivisões para cada seção. A figura 14.2 exibe um exemplo de um torus com rings=6 e nsides=20, e a figura 14.3 exibe um exemplo com rings=20 e nsides=20.


Figura14.2.png
Figura14.3.png


Figura 14.2 - Torus (rings=6, nsides=20) Figura 14.3 - Torus (rings=20, nsides=20)

 

helldanger1

GForum VIP
Entrou
Ago 1, 2007
Mensagens
29,631
Gostos Recebidos
1
Todas estas funções também podem ser usadas para desenhar objetos sólidos, ao invés de exibir apenas o seu wire-frame. Para isto, basta substituir a substring Wire do nome da função por Solid. Por exemplo, se substituirmos a chamada à função glutWireTeapot(50.0f) por glutSolidTeapot(50.0f) a imagem gerada é a apresentada na figura 14.4.


Figura14.4.png


Figura 14.4 - Teapot gerado usando a função glutSolidTeapot

Olhando a figura 14.4 é possível observar que a imagem gerada parece 2D. Isto ocorre porque a versão Solid deve ser usada somente quando se está trabalhando com iluminação (veja o próximo capítulo deste tutorial).

 

helldanger1

GForum VIP
Entrou
Ago 1, 2007
Mensagens
29,631
Gostos Recebidos
1
15. Utilizando Luzes

Como é possível observar na figura 14.4, a imagem gerada não possui uma qualidade satisfatória. Para adicionar um pouco de realismo nas imagens, é necessário, então, adicionar uma ou mais fontes de luz.

Inicialmente, é preciso definir o modelo de colorização que será utilizado. OpenGL fornece dois modelos: uma polígono preenchido pode ser desenhado com uma única cor (GL_FLAT), ou com uma variação de tonalidades (GL_SMOOTH, também chamado de modelo de colorização de Gouraud [Foley 1990]). A função glShadeModel() é usada para especificar a técnica de colorização desejada.

Quando objetos 3D sólidos são exibidos, é importante desenhar os objetos que estão mais próximos do observador (ou posição da câmera), eliminando objetos que ficam "escondidos", ou "parcialmente escondidos", por estes. Sendo assim,algoritmos de remoção de elementos escondidos foram desenvolvidos para determinar as linhas, arestas, superfícies ou volumes que são visíveis ou não para um observador localizado em um ponto específico no espaço. A complexidade do problema dos elementos ocultos resultou em um grande número de soluções na Computação Gráfica.

Conforme descrito por [Woo 1999], OpenGL possui um depth buffer que trabalha através da associação de uma profundidade, ou distância, do plano de visualização (geralmente o plano de corte mais próximo do observador) com cada pixel da window. Inicialmente, os valores de profundidade são especificados para serem o maior possível através do comando glClear(GL_DEPTH_BUFFER_BIT). Entretanto, habilitando o depth-buffering através dos comandos glutInitDisplayMode(GLUT_DEPTH | ...) e glEnable(GL_DEPTH_TEST), antes de cada pixel ser desenhado é feita uma comparação com o valor de profundidade já armazenado. Se o valor de profundidade for menor (está mais próximo) o pixel é desenhado e o valor de profundidade é atualizado. Caso contrário as informações do pixel são desprezadas.

Em OpenGL a cor de uma fonte de luz é caracterizada pela quantidade de vermelho (R), verde (G) e azul (B) que ela emite, e o material de uma superfície é caracterizado pela porcentagem dos componentes R, G e B que chegam e são refletidos em várias direções. No modelo de iluminação a luz em uma cena vem de várias fontes de luz que podem ser "ligadas" ou "desligadas" individualmente. A luz pode vir de uma direção ou posição (por exemplo, uma lâmpada) ou como resultado de várias reflexões (luz ambiente - não é possível determinar de onde ela vem, mas ela desaparece quando a fonte de luz é desligada).
 

helldanger1

GForum VIP
Entrou
Ago 1, 2007
Mensagens
29,631
Gostos Recebidos
1
No modelo de iluminação OpenGL a fonte de luz tem efeito somente quando existem superfícies que absorvem e refletem luz. Assume-se que cada superfície é composta de um material com várias propriedades. O material pode emitir luz, refletir parte da luz incidente em todas as direções, ou refletir uma parte da luz incidente numa única direção, tal com um espelho. Então, conforme descrito por [Woo 1999], OpenGL considera que a luz é dividida em quatro componentes independentes (que são colocadas juntas):
Ambiente: resultado da luz refletida no ambiente; é uma luz que vem de todas as direções;
Difusa: luz que vem de uma direção, atinge a superfície e é refletida em todas as direções; assim, parece possuir o mesmo brilho independente de onde a câmera está posicionada;
Especular: luz que vem de uma direção e tende a ser refletida numa única direção;
Emissiva: simula a luz que se origina de um objeto; a cor emissiva de uma superfície adiciona intensidade ao objeto, mas não é afetada por qualquer fonte de luz; ela também não introduz luz adicional da cena.

A cor do material de um objeto depende da porcentagem de luz vermelha, verde e azul incidente que ele reflete. Assim como as luzes, o material possui cor ambiente, difusa e especular diferentes, que determinam como será a luz refletida. Isto é combinado com as propriedades das fontes de luz, de tal maneira que a reflexão ambiente e difusa definem a cor do material. A especular é geralmente cinza ou branca.

Os componentes de cor especificados para a luz possuem um significado diferente dos componentes de cor especificados para os materiais. Para a luz, os números correspondem a uma porcentagem da intensidade total para cada cor. Se os valores R, G e B para a cor da luz são 1, a luz é branca com o maior brilho possível. Se os valores são 0.5 a cor ainda é branca, mas possui metade da intensidade, por isso parece cinza. Se R=G=1 e B=0, a luz parece amarela.
 

helldanger1

GForum VIP
Entrou
Ago 1, 2007
Mensagens
29,631
Gostos Recebidos
1
Para os materiais, os números correspondem às proporções refletidas destas cores. Se R=1, G=0.5 e B=0 para um material, este material reflete toda luz vermelha incidente, metade da luz verde e nada da luz azul. Assim, simplificadamente, a luz que chega no observador é dada por (LR.MR, LG.MG, LB.MB), onde (LR, LG, LB) são os componentes da luz e (MR, MG, MB) os componentes do material [Woo 1999].

O programa abaixo apresenta um exemplo completo da utilização de luzes em OpenGL. A imagem gerada, como mostra a figura 15.1, apenas exibe um teapot azul iluminado, numa janela com fundo preto.
// 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();
}
 

helldanger1

GForum VIP
Entrou
Ago 1, 2007
Mensagens
29,631
Gostos Recebidos
1
Figura15.1.png


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].
 

helldanger1

GForum VIP
Entrou
Ago 1, 2007
Mensagens
29,631
Gostos Recebidos
1
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].
 

helldanger1

GForum VIP
Entrou
Ago 1, 2007
Mensagens
29,631
Gostos Recebidos
1
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].
 

helldanger1

GForum VIP
Entrou
Ago 1, 2007
Mensagens
29,631
Gostos Recebidos
1
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 );
 

helldanger1

GForum VIP
Entrou
Ago 1, 2007
Mensagens
29,631
Gostos Recebidos
1
16. Malha de Polígonos

Como a maioria dos objetos em Computação Gráfica é representada através de uma malha de polígonos, logo abaixo é apresentada uma função que exemplifica o uso de uma malha de polígonos para fazer o desenho de um cubo.
void Desenha(void)
{

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(0.0f, 0.0f, 1.0f);

// Desenha um cubo

glBegin(GL_QUADS); // Face posterior
glNormal3f(0.0, 0.0, 1.0); // Normal da face
glVertex3f(40.0, 40.0, 40.0);
glVertex3f(-40.0, 40.0, 40.0);
glVertex3f(-40.0, -40.0, 40.0);
glVertex3f(40.0, -40.0, 40.0);
glEnd();


glBegin(GL_QUADS); // Face frontal
glNormal3f(0.0, 0.0, -1.0); // Normal da face
glVertex3f(40.0, 40.0, -40.0);
glVertex3f(40.0, -40.0, -40.0);
glVertex3f(-40.0, -40.0, -40.0);
glVertex3f(-40.0, 40.0, -40.0);
glEnd();
glBegin(GL_QUADS); // Face lateral esquerda
glNormal3f(-1.0, 0.0, 0.0); // Normal da face
glVertex3f(-40.0, 40.0, 40.0);
glVertex3f(-40.0, 40.0, -40.0);
glVertex3f(-40.0, -40.0, -40.0);
glVertex3f(-40.0, -40.0, 40.0);
glEnd();
glBegin(GL_QUADS); // Face lateral direita
glNormal3f(1.0, 0.0, 0.0); // Normal da face
glVertex3f(40.0, 40.0, 40.0);
glVertex3f(40.0, -40.0, 40.0);
glVertex3f(40.0, -40.0, -40.0);
glVertex3f(40.0, 40.0, -40.0);
glEnd();
glBegin(GL_QUADS); // Face superior
glNormal3f(0.0, 1.0, 0.0); // Normal da face
glVertex3f(-40.0, 40.0, -40.0);
glVertex3f(-40.0, 40.0, 40.0);
glVertex3f(40.0, 40.0, 40.0);
glVertex3f(40.0, 40.0, -40.0);
glEnd();
glBegin(GL_QUADS); // Face inferior
glNormal3f(0.0, -1.0, 0.0); // Normal da face
glVertex3f(-40.0, -40.0, -40.0);
glVertex3f(40.0, -40.0, -40.0);
glVertex3f(40.0, -40.0, 40.0);
glVertex3f(-40.0, -40.0, 40.0);
glEnd();
glutSwapBuffers();
}
 
Topo