Lic. Engenharia Informática 2000/2001 - Computação Gráfica Filipe Pacheco
OpenGL
Estas são as páginas de apoio às aulas práticas sobre OpenGL.

Pode também consultar a página de apoio à cadeira de Computação Gráfica e directamente as páginas internacionais sobre OpenGL (incluindo a GLUT).

Informação Disponível:

1-Compilação e execução de programas em OpenGL no Microsoft Visual C++

2-Guia de consulta rápida de funções  OpenGL mais comuns
Estão também disponíveis cópias neste servidor da documentação do OpenGL, da GLUT e Tutoriais OpenGL.

3-Programas Exemplo
Actualizado: 23-05-2001

4-Livrarias e Bibliotecas OpenGL para Windows 95/NT

   
1 Compilação e execução de programas em OpenGL no Microsoft Visual C++

Para compilar um programa OpenGL sobre Visual C++ 4.0/Visual Studio 95 basta executar os passos seguintes (em itálico instruções para o Visual C++ 5.0/Visual Studio 97):

Iniciar novo Project Workspace:

File | New | Project Workspace | Console Application
File | New | Projects | Win32 Console Application
Indicar no Project Name o nome da aplicação e selecionar OK

Para adicionar ficheiros ao Project Workspace:

Insert | Files into Project
Project | Add to Project | Files 

Para utilizar as livrarias do OpenGL (Windows NT):

Project | Settings | Link | Library Modules (Verificar se estão selecionadas todas as configurações disponíveis, normalmente Runtime e Debug)
Project | Settings | Link | Object/Library Modules (Verificar se está activo Settings For: All Configurations)
Acrescentar os seguintes ficheiros à lista:
opengl32.lib glu32.lib glut32.lib 

Para compilar o ficheiro .c:

Build | Compile 
Build | Compile
Nesta altura é verificada a sintaxe do ficheiro .c e criado o código objecto respectivo. Um ficheiro objecto tem o código executável para o processador juntamente com todas as chamas externas do ficheiro. 

Para criar um ficheiro executável:

Build | Rebuild All 
Build | Rebuild All
Nesta altura são analizados e combinados os ficheiros .obj do projecto sendo assim criado um ficheiro executável final. Dependendo da configuração do Visual C++, podem ser compilados automaticamente os ficheiros .c alterados desde a última compilação.

Para executar o programa:

Build | Start Debug | Go 
Build | Start Debug | Go
Este comando inicia a execução do programa permitindo a execução passo a passo e outras funções de debug. Dependendo da configuração do Visual C++, podem ser invocado automaticamente o comando Rebuild All de acordo com os ficheiros alterados.

Build | Execute 
Build | Execute
Semelhante ao anterior mas sem funções de debug. 

Para terminar o programa:

Debug | Stop Debug
Debug | Stop Debug
Apenas eficaz se em modo Debug. 

Para indicar/alterar pontos de paragem do programa (breakpoints):

Edit | Breakpoints...
Edit  | Breakpoints
Clicar na seta á direita do campo Break At: para indicar a linha actual (O botão da barra de ferramnetas apenas permite ligar/desligar um ponto de paragem, utilizar os menus para funções mais avançadas)

Para ver o valor de uma varável durante o debug:

Quanto o programa está parado num ponto de paragem, pode-se verificar o valor das variáveis bastando para tal manter o rato parado por uns segundos sobre uma referência à variável no ficheiro .c respectivo. 

Para tornar visível a barra de ferramentas de debug:

Clicar com o botão do lado direito do rato sobre uma toolbar e selecionar Debug
Nota: O Visual C++ utiliza configurações independentes das barras de ferramentas para o modo execução e o modo edição, como tal será mais útil tornar visível a barra apenas durante a execução de um programa (ou seja: iniciar a execução do programa e, depois, activar a barra de ferramentas).
 

2 Guia de consulta rápida de funções  OpenGL mais comuns

Nesta secção apresentam-se algumas das funções OpenGL (incluindo glut) utilizadas nos programas de exemplo
 

void glutInitWindowPosition(int x, int y);
void glutInitWindowSize(int width, int height);
Define a posição e dimensões da janela a utilizar
glutInitWindowPosition(0, 0);
glutInitWindowSize(500, 500);
 

void glutInit(int *argcp, char **argv);
Inicializa a glut.
void main(int argc, char **argv)
{
    glutInit(&argc, argv);
...

#define GLUT_RGB
#define GLUT_RGBA
#define GLUT_INDEX
#define GLUT_SINGLE
#define GLUT_DOUBLE
#define GLUT_DEPTH
void glutInitDisplayMode(unsigned int mode);
indica o modo de apresentação a utilizar. RGA, RGBA, INDEX: modo de cor, SINGLE, DOUBLE: utilização de buffer para animação, DEPTH: utilização de Z buffer.
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);

void glutMainLoop(void);
Entra no ciclo principal de execução da glut. A partir deste momento é feita a interação com o utilizador e serão chamadas as funções de utilizador respectivas.
glutMainLoop()

int glutCreateWindow(const char *title);
cria uma nova janela com o título indicado
glutCreateWindow("Color Cube");

void glutSwapBuffers(void);
troca o buffer utilizado (para animação). 
glutSwapBuffers();

void glutDisplayFunc(void (*)(void));
void glutReshapeFunc(void (*)(int width, int height));
void glutKeyboardFunc(void (*)(unsigned char key, int x, int y));
void glutMouseFunc(void (*)(int button, int state, int x, int y));
void glutMotionFunc(void (*)(int x, int y));
void glutPassiveMotionFunc(void (*)(int x, int y));
void glutIdleFunc(void (*)(void));
permitem definir funções que serão chamadas em resposta a certos eventos. Indicar NULL para limpar uma definição. Display: é chamada quando a janela é apresentada, Reshape: quando são alteradas as dimensões da janela, Keyboard:  quando é premida uma tecla, MouseFunc: quando o utilizador move o rato com um (ou mais) botão premido, PassiveMouseFunc: quando o utilizador move o rato, Idle: chamada quando o sistema está à espera do utilizador.
/* definição da função do utilizador */
void myReshape(int w, int h)
{
...
}
...
/* indicá-la à glut */
glutReshapeFunc(myReshape);
...
/* exemplos de outras definições de função do utilizador: */
void myDisplay() ...
void myKeyboard(unsigned char key, int x, int y) ...
void myMouse(int button, int state, int x, int y) ...
void myMotion(int x, int y) ...
void myPassiveMotion(int x, int y) ...
void myIdle() ...

void glutWireSphere(GLdouble radius, GLint slices, GLint stacks); 
void glutSolidSphere(GLdouble radius, GLint slices, GLint stacks); 
void glutWireCone(GLdouble base, GLdouble height, GLint slices, GLint stacks); 
void glutSolidCone(GLdouble base, GLdouble height, GLint slices, GLint stacks); 
void glutWireCube(GLdouble size); 
void glutSolidCube(GLdouble size); 
void glutWireTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings); 
void glutSolidTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings); 
void glutWireDodecahedron(void); 
void glutSolidDodecahedron(void); 
void glutWireTeapot(GLdouble size); 
void glutSolidTeapot(GLdouble size); 
void glutWireOctahedron(void); 
void glutSolidOctahedron(void); 
void glutWireTetrahedron(void); 
void glutSolidTetrahedron(void); 
void glutWireIcosahedron(void); 
void glutSolidIcosahedron(void); 
permitem desenhar facilmente um conjunto de elementos utilizando faces sólidas (Solid) ou desenhando apenas as arestas (Wire).
glutSolidSphere(1.0,  15.0, 15.0);
 

#define GLUT_BITMAP_9_BY_15 
#define GLUT_BITMAP_8_BY_13 
#define GLUT_BITMAP_TIMES_ROMAN_10
#define GLUT_BITMAP_TIMES_ROMAN_24
#define GLUT_BITMAP_HELVETICA_10
#define GLUT_BITMAP_HELVETICA_12
#define GLUT_BITMAP_HELVETICA_18
void glutBitmapCharacter(void *font, int character);
permite desenhar texto com fonte de mapa de bits. A posição actual é automaticamente actualizada.
glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, 'A');

#define GL_COLOR_BUFFER_BIT 
#define GL_DEPTH_BUFFER_BIT 
#define GL_ACCUM_BUFFER_BIT 
#define GL_STENCIL_BUFFER_BIT 
void glClear (GLbitfield mask);
Limpa buffers.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 

void glLightf(GLenum light, GLenum pname, GLfloat param); 
void glLighti(GLenum light, GLenum pname, GLint param); 
void glLightiv(GLenum light, GLenum pname, const GLint *params); 
void glLightfv(GLenum light, GLenum pname, const GLfloat *params); 
Define parâmetros de uma determinada luz.
O parâmetro light indica a luz e pode ser: GL_LIGHT0, GL_LIGHT1, etc...
Para glLightf(...) e glLighti(...), pname pode ser: GL_SPOT_EXPONENT, GL_SPOT_CUTOFF, GL_CONSTANT_ATTENUATION, GL_LINEAR_ATTENUATION ou GL_QUADRATIC_ATTENUATION
Para glLightfv(...) e glLightiv(...), pname pode ser: GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR, GL_POSITION, GL_SPOT_DIRECTION, GL_SPOT_EXPOENT, GL_SPOT_CUTOFF, GL_CONSTANT_ATTENUATION, GL_LINEAR_ATTENUATION ou GL_QUADRATIC_ATTENUATION.
static GLfloat light_ambient[]={0.0, 0.0, 0.0, 1.0};
static GLfloat light_diffuse[]={1.0, 1.0, 1.0, 1.0};
static GLfloat light_specular[]={1.0, 1.0, 1.0, 1.0};
static GLfloat light_position[]={2.0, 2.0, 2.0, 0.0};
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);

void glMaterialf(GLenum face, GLenum pname, GLfloat param); 
void glMateriali(GLenum face, GLenum pname, GLint param); 
void glMaterialiv(GLenum face, GLenum pname, const GLint *params); 
void glMaterialfv(GLenum face, GLenum pname, const GLfloat *params); 
Define características das superfícies a desenhar.
O parâmetro face indica qual a face que estamos a definir e pode ser: GL_FRONT, GL_BACK ou GL_FRONT _AND_BACK.
Para glMaterialf(...) e glMateriali(...), pname só pode ser GL_SHINNESS.
Para glMaterialfv(...) e glMaterialiv(...), pname pode ser: GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR, GL_EMISSION, GL_SHINNESS, GL_AMBIENT_AND_DIFFUSE ou GL_COLOR_INDEXES.
static GLfloat mat_specular[]={0.5, 1.0, 1.0, 1.0};
static GLfloat mat_diffuse[]={1.0, 1.0, 1.0, 1.0};
static GLfloat mat_ambient[]={1.0, 1.0, 1.0, 1.0};
static GLfloat mat_shininess={50.0};
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialf(GL_FRONT, GL_SHININESS, mat_shininess);

void glEnable(GLenum cap); 
void glDisable(GLenum cap);
Permite activar ou desactivar parâmetros globais do OpenGL.
Alguns valores possíveis para cap
GL_COLOR_MATERIAL: as características dos materiais são derivadas da cor actual (ver glColorMaterial)
GL_DEPTH_TEST: activa a  utilização do buffer de profundidade (remoção de faces escondidas)
GL_LIGHTi: activa a luz i.
GL_LIGHTING: activa a utilização das luzes para o cálculo das cores finais de cada vértice.
GL_LINE_SMOOTH: desenha linhas suavizadas (anti-aliasing)
GL_NORMALIZE: normaliza os vectores indicados em glNormal.
GL_POINT_SMOOTH: equivalente a GL_LINE_SMOOTH mas para pontos.
GL_POLYGON_SMOOTH: equivalente a GL_LINE_SMOOTH mas para polignos.
GL_SMOOTH: activa sombreamento suave (interpolação entre vértices).
glEnable(GL_SMOOTH); /*activar shading suave */
glEnable(GL_LIGHTING); /* activar luzes */
glEnable(GL_LIGHT0);  /* activar luz 0 */
glEnable(GL_DEPTH_TEST); /* activar teste z buffer */
glEnable(GL_COLOR_MATERIAL); /* activar materiais a partir da cor */

void glClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); 
Indica a cor de fundo a ser utilizada por glClear(...).
glClearColor (0.0, 0.0, 0.0, 0.0);

void glFlush(void);
Obriga o OpenGL a completar todas as operações pendentes. glFlush(...) deve ser chamada quando é necessário garantir que a imagem está completamente definida no ecran, por exemplo anters de aguardar por entrada do utilizador.
glFlush();
 
void glPushMatrix( void ); 
void glPopMatrix( void ); 
Permitem guardar temporariamente a matriz de transformação actual. Após a instrução glPopMatrix() todas as operações que alteram a matriz actual (ex: glTranslatef(...), glLoadIdentity()) efectuadas após o último glPushMatrix(), são ignoradas.
glPushMatrix();
glScalef(1.0,5.0,3.0);
gluWireCube(1.0);
glPopMatrix();

void glOrtho( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far ); 
Define a área de visualização para uma projecção ortogonal. De notar que os parâmetros near e far são indicados relativamente ao utilizador, ou seja near deve ser menor que far. Os parâmetros left, right, top e bottom devem ter em conta as dimensões actuais do viewport utilizado para que as imagens não apareçam distorcidas. Todos os objectos, ou secções dos mesmos, fora do volume de visualização indicado não são apresentadas na janela.
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION); 
glLoadIdentity(); 
if (w <= h) 
    glOrtho(-2.0, 2.0, -2.0 * (GLfloat) h / (GLfloat) w, 2.0 * (GLfloat) h / (GLfloat) w, -10.0, 10.0);
else 
    glOrtho(-2.0 * (GLfloat) w / (GLfloat) h, 2.0 * (GLfloat) w / (GLfloat) h, -2.0, 2.0, -10.0, 10.0);
glMatrixMode(GL_MODELVIEW);

void glFrustum( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble znear, GLdouble zfar );
Permite definir uma perspectiva. Os parâmetros left, right, top, bottom e znear definem a área de visualização mais próxima do observador, o parâmetros zfar define o plano de corte mais distante. De notar que tanto znear como zfar tem de ser maiores que zero. Da mesma forma que glOrtho, estes parâmetros são indicados relativamente ao observador.
glViewport(0, 0, w, h); 
glMatrixMode(GL_PROJECTION); 
glLoadIdentity(); 
if (w <= h) 
    glFrustum(-2.0, 2.0, -2.0 * (GLfloat) h / (GLfloat) w, 2.0 * (GLfloat) h / (GLfloat) w, 10.0, 30.0);
else 
    glFrustum(-2.0 * (GLfloat) w / (GLfloat) h, 2.0 * (GLfloat) w / (GLfloat) h, -2.0, 2.0, 10.0, 30.0);
glTranslatef(0.0, 0.0, -20.0);
glMatrixMode(GL_MODELVIEW);

void gluPerspective( GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar );
Permite definir uma perspectiva equivalente a glFrustum. O parâmetro fovy indica o ângulo (em graus) de abertura vertical, aspect é a relação entre a largura e a altura do viewport. znear e zfar definem os planos de corte de profundidade. Tal como em glFrustum devem ser ambos maiores que zero.
glViewport(0, 0, w, h); 
glMatrixMode(GL_PROJECTION); 
glLoadIdentity(); 
if (w <= h) 
    gluPerspective(90.0 * (GLfloat) h / (GLfloat) w, (GLfloat) w / (GLfloat) h, 10.0, 30.0); 
else 
    gluPerspective(90.0, (GLfloat) w / (GLfloat) h, 10.0, 30.0); 
glTranslatef(0.0, 0.0, -20.0);
glMatrixMode(GL_MODELVIEW);

void gluLookAt( GLdouble eyex, GLdouble eyey, GLdouble eyez, GLdouble centerx, GLdouble centery, GLdouble centerz, GLdouble upx, GLdouble upy, GLdouble upz ); 
Permite alterar o ponto de vista de uma perspectiva. eye.... são as coordenadas do observador, center... as coordenadas do centro da cena e up... indica o topo da cena (permitindo rodar a vista). De notar que após gluLookAt os parâmetros znear e zfar utilizados em glFrustum ou gluPerspective são relativos ao observador indicado em gluLookAt o que pode ter resultados algo inesperados.
glViewport(0, 0, w, h); 
glMatrixMode(GL_PROJECTION); 
glLoadIdentity(); 
if (w <= h) 
    gluPerspective(90.0 * (GLfloat) h / (GLfloat) w, (GLfloat) w / (GLfloat) h, 10.0, 30.0); 
else 
    gluPerspective(90.0, (GLfloat) w / (GLfloat) h, 10.0, 30.0);
gluLookAt(0.0, 0.0, -20.0, 0.0, 6.0, -20.0, 0.0, 0.0, -1.0);
glTranslatef(0.0, 0.0, -20.0);
glMatrixMode(GL_MODELVIEW);

void glTranslatef( GLfloat x, GLfloat y, GLfloat z );
void glScalef( GLfloat x, GLfloat y, GLfloat z ); 
void glRotatef( GLfloat angle, GLfloat x, GLfloat y, GLfloat z ); 
Multiplicam a matriz de transformação actual pelas matrizes de translação (glTranslatef), escala (glScalef) ou rotação (glRotatef). No caso de glRotatef o ângulo é indicado em graus. Na prática os objectos desenhados após estas instruções são deslocados, esticados ou rodados de acordo com a operação realizada. De notar que é importante a ordem pela qual executamos as instruções, no exemplo a seguir o ponto actual será (3.0, 2.0, 0.0), no entanto se efectuassemos as operações por ordem inversa seria (1.5, 2.0, 0.0).
glScalef(2.0,1.0,1.0);
glTranslatef(1.5,2.0,0.0);

23-5-2001