Bem, amigos.
O objetivo desta prática é entender como desenhar objetos simples em OpenGL. Para tanto, a biblioteca oferece um conjunto de primitivas de desenho, que podem ser utilizadas tanto em 2D como em 3D.
Para começar, recomendo a leitura disto:
Obs.: o site explica em Java, mas em
C é a mesma coisa, apenas tire o
gl. do começo dos comandos.
Aqui segue o código :
#include <GL/glut.h>
// Função call back chamada para fazer o desenho
void DesenhaNaTela(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glutSwapBuffers();
}
// Inicializa parâmetros de rendering
void Inicializa (void)
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}
// Programa principal
int main(int argc, char** argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(320,240);
glutInitWindowPosition(100,100);
glutCreateWindow("Primeiro Programa em OpenGL");
glutDisplayFunc(DesenhaNaTela);
Inicializa();
glutMainLoop();
}
Apenas para criar uma janela, isso já é o suficiente.
Agora, salve como
TesteOpenGL.c e compile:
gcc -o TesteOpenGL TesteOpenGL.c -lglut -lGL -lGLU -lm
Se tudo ocorreu bem, aparecerá uma janelinha preta sem nada (de 320x240):
Mas agora, vocês me perguntam:
- Thiago, como vamos colocar alguma coisa na tela?
Aguarde um pouco, "pequeno gafanhoto", vamos por partes. Primeiramente, irei explicar esse código.
Mas antes, quero dizer o que é o GLUT: é um toolkit que serve de comunicação mais fácil com o usuário (é como o SDL. Obs.: existe a possibilidade de colocar o OpenGL + SDL, mas isso é com o tio
Sam.L)
Vamos começar pelo
main:
É importante se lembrar de colocar: "int argc, char** argv" no
main.
glutInit(&argc,argv); :: inicializa o GLUT com os argumentos passados.
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); :: inicializa o sistema gráfico com o Single Buffer e o RGB.
- Tá, mas o que é Single Buffer e o RGB?
Single Buffer é quando o desenho é feito dentro da tela. Opcionalmente, é possível trocar por GLUT_DOUBLE.
- E o que é o Double?
O Double funciona assim: a imagem é criada fora da tela de visualização e depois é rapidamente enviada para a tela (muito utilizado para fazer animações).
- E o RGB?
É um apelido para RGBA. Inicializa o sistema de cores RGBA (Red, Green, Blue e Alpha).
Esses dois são fáceis:
glutInitWindowSize(320,240);
glutInitWindowPosition(100,100);
Funciona assim: o primeiro cria a janela com 320x240 pixels e a outra posiciona nos pixels 100x100 do seu monitor (equivale ao lado esquerdo superior).
glutCreateWindow("Primeiro Programa em OpenGL"); :: esse também é fácil, ele cria a janela propriamente dita e coloca como título o que estiver dentro de aspas.
glutDisplayFunc(DesenhaNaTela); :: esse indica onde será processado o desenho. Ex.: eu criei um quadrado, o "DesenhaNaTela" colocará esse quadrado para mim.
Inicializa(); :: essa função já deixa marcado o que será inicializado quando a janela abrir. (Obs.: essa não é uma função do GLUT e nem do OpenGL).
glutMainLoop(); :: é a função que faz com que comece a execução da "máquina de estados" e processa todas as mensagens específicas do sistema operacional, tais como teclas e botões do mouse pressionados, até que o programa termine.
glClearColor(0.0f, 0.0f, 1.0f, 1.0f) :: vai limpar a tela e pintar de preto. O esquema de cores é assim RGBA (Red, Green, Blue e Alpha - ou para quem não sabe inglês: Vermelho, Verde, Azul e Alfa).
glClear(GL_COLOR_BUFFER_BIT); :: "limpa" um buffer particular ou combinações de buffers. Onde buffer, é uma área de armazenamento para informações da imagem. Os componentes RGB são geralmente referenciados como color buffer ou pixel buffer. Existem vários tipos de buffer, mas por enquanto, só é necessário entender que o color buffer é onde a imagem é armazenada internamente e limpar o buffer com glClear, remove o desenho da janela.
glutSwapBuffers; :: atualiza a tela e o (ou os, caso seja Double) buffer. Isso fica melhor de explicar com um exemplo:
Você criou um triângulo, mas ele ainda não foi processado, então o
glutSwapBuffers() atualiza a tela e coloca o triângulo.
Primeiro desenho
Agora que você já entendeu o conceito básico de criar uma janela, vamos desenhar nela.
Vamos definir a Área Cartesiana de
-10 até
10 em
'x' e
-10 até
10 em
'y'.
O código:
#include <GL/glut.h>
void desenhaGrade()
{
glColor3f(0.8f,0.8f,0.8f);
glLineWidth(1.0f);
glBegin(GL_LINES);
float x = -10;
for(;x<=10; x++)
{
glVertex2f(-10,x);
glVertex2f( 10,x);
glVertex2f(x,-10);
glVertex2f(x, 10);
}
glEnd();
glColor3f(0.0f,0.0f,0.0f);
glLineWidth(3.0f);
glBegin(GL_LINES);
glVertex2f(-10,0);
glVertex2f( 10,0);
glVertex2f(0,-10);
glVertex2f(0, 10);
glEnd();
}
void DesenhaNaTela(void)
{
glClear(GL_COLOR_BUFFER_BIT);
desenhaGrade();
// Troque Aqui
glColor3f(1.0f, 0.0f, 0.0f); // vermelho
glPointSize(10.0f); // aumenta o tamanho dos pontos
glBegin(GL_POINTS);
glVertex2f(-8,-5);
glVertex2f( 8,-5);
glVertex2f(-8, 0);
glVertex2f( 8, 0);
glVertex2f(-8, 5);
glVertex2f( 8, 5);
glEnd();
// Ate Aqui
glutSwapBuffers();
}
void Inicializa (void)
{
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-10,10,-10,10);
glMatrixMode(GL_MODELVIEW);
}
int main(int argc, char** argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(320,240);
glutInitWindowPosition(100,100);
glutCreateWindow("Primeiro Programa em OpenGL - Poligonos");
glutDisplayFunc(DesenhaNaTela);
Inicializa();
glutMainLoop();
}
Vocês podem estar pensando assim: "Nossa, quanto código!".
Aí eu falo: "Isso é só o começo".
Vamos voltar ao foco:
glMatrixMode(GL_PROJECTION); e
glLoadIdentity(); :: servem, respectivamente, para avisar a OpenGL que todas as futuras alterações, tais como operações de escala, rotação e translação, irão afetar a "câmera" (ou observador), e para inicializar o sistema de coordenadas antes da execução de qualquer operação de manipulação de matrizes.
glMatrixMode(GL_MODELVIEW); :: avisa a OpenGL que todas as futuras alterações, tais como operações de escala, rotação e translação, irão afetar os modelos da cena, ou em outras palavras, o que é desenhado.
desenhaGrade :: Serve apenas para servir de apoio para facilitar o nosso entendimento na área cartesiana (-10 10).
"DesenhaNaTela".
Eu tentei ser o mais simples possível:
A primeira diferença é o
glColor3f;, ele define a cor vermelha no padrão RGB.
Caso goste do RGBA (o que é pouco provável), utilize
glColor4f(0.0, 0.5, 0.9,0.0);, sendo o quarto valor o Alfa.
A maior parte para desenhar polígonos, começa com:
glBegin(aqui vai o nome do polígono);
... // Código
glEnd();
Segue apenas exemplos (caso desejem entender direito, acesse o link informado) Troque apenas na Função "DesenhaNaTela" nos delimitadores (// Troque Aqui // Ate Aqui) :
Linhas:
glColor3f(1.0f, 0.0f, 0.0f); // vermelho
glLineWidth(3.0f); // aumenta a espessura das linhas
glBegin(GL_LINES);
glVertex2f(-8,-5); // linha 1
glVertex2f( 8,-5);
glVertex2f(-8, 0); // linha 2
glVertex2f( 8, 0);
glVertex2f(-8, 5); // linha 3
glVertex2f( 8, 5);
glEnd();
Sequência de linhas:
glColor3f(1.0f, 0.0f, 0.0f); // vermelho
glLineWidth(3.0f); // aumenta a espessura das linhas
glBegin(GL_LINE_STRIP);
glVertex2f(-8,-5);
glVertex2f( 8,-5);
glVertex2f(-8, 0);
glVertex2f( 8, 0);
glVertex2f(-8, 5);
glVertex2f( 8, 5);
glEnd();
Sequência de linhas, mas o último ponto se liga ao primeiro:
glColor3f(1.0f, 0.0f, 0.0f); // vermelho
glLineWidth(3.0f); // aumenta a espessura das linhas
glBegin(GL_LINE_LOOP);
glVertex2f(-8,-5);
glVertex2f( 8,-5);
glVertex2f(-8, 0);
glVertex2f( 8, 0);
glVertex2f(-8, 5);
glVertex2f( 8, 5);
glEnd();
Sequência de triângulos:
glBegin(GL_TRIANGLES);
glColor3f(1.0f, 0.0f, 0.0f); // vermelho
glVertex2f(-8,-5);
glVertex2f( 8,-5);
glVertex2f(-8, 0);
glColor3f(0.0f, 1.0f, 0.0f); // verde
glVertex2f( 8, 0);
glVertex2f(-8, 5);
glVertex2f( 8, 5);
glEnd();
Sequência de quadriláteros:
glBegin(GL_QUADS);
glColor3f(1.0f, 0.0f, 0.0f); // vermelho
glVertex2f(-8,-5);
glVertex2f( 8,-5);
glVertex2f( 8, 0);
glVertex2f(-8, 0);
glColor3f(0.0f, 1.0f, 0.0f); // verde
glVertex2f(-8, 5);
glVertex2f( 8, 5);
glVertex2f(-8, 8);
glVertex2f( 8, 8);
glEnd();
Polígono convexo:
glColor3f(1.0f, 0.0f, 0.0f); // vermelho
glBegin(GL_POLYGON);
glVertex2f(-6,-5);
glVertex2f(-8,-3);
glVertex2f(-8, 0);
glVertex2f(-8, 3);
glVertex2f(-6, 5);
glVertex2f( 6, 5);
glVertex2f( 8, 3);
glVertex2f( 8, 0);
glVertex2f( 8,-3);
glVertex2f( 6,-5);
glEnd();
Polígono não convexo (que não tem todos os pontos definidos):
glColor3f(1.0f, 0.0f, 0.0f); // vermelho
glBegin(GL_POLYGON);
glVertex2f(-6,-5);
glVertex2f(-3, 0);
glVertex2f(-6, 5);
glVertex2f( 6, 5);
glVertex2f( 3, 0);
glVertex2f( 6,-5);
glEnd();
Bom, eu acho que exemplos não faltam, mas ainda existem outros tipos que você pode olhar no link acima.
Agora troque o: glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB)
Por :
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
E veja a diferença !