Tutorial OpenGL

Tutorial básico de OpenGL com exemplos práticos.

[ Hits: 68.958 ]

Por: Thiago Henrique Hüpner em 01/08/2014


Primeiro programa e exemplos



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 !

Página anterior     Próxima página

Páginas do artigo
   1. Explicação
   2. Primeiro programa e exemplos
   3. Manipulação de eventos do teclado e mouse
   4. Adicionando imagem ao OpenGL
   5. Fontes, links úteis e agradecimentos
Outros artigos deste autor

Tutorial OpenGL v3.0

Ubuntu/Debian/Kali Linux e outros no Android

Tutorial OpenGL v2.0

Tutorial SFML

Visual Studio no Linux

Leitura recomendada

Utilizando a biblioteca NCURSES - Parte I

Aleatoriedade em C

Utilizando a biblioteca NCURSES - Parte III

Túnel do Tempo: a função itoa()

Aprendendo a utilizar o GNU Debugger (parte 1)

  
Comentários
[1] Comentário enviado por SamL em 01/08/2014 - 09:11h

Ae cara ficou bom o tutorial.

[2] Comentário enviado por Thihup em 01/08/2014 - 09:15h


[1] Comentário enviado por Sam L. em 01/08/2014 - 09:11h:

Ae cara ficou bom o tutorial.

Valeu mano,sempre me apoiando.
Posso dizer que aquele desafio está encerrado ?

T+

[3] Comentário enviado por SamL em 01/08/2014 - 12:15h

rsrsrs Desafio Completo! You win!

[4] Comentário enviado por albfneto em 01/08/2014 - 12:19h

Muito bom, e diferente, original!
Favoritado e 10.

[5] Comentário enviado por Thihup em 01/08/2014 - 17:58h


[4] Comentário enviado por albfneto em 01/08/2014 - 12:19h:

Muito bom, e diferente, original!
Favoritado e 10.


Valeu Fera
T+

[6] Comentário enviado por razgriz em 02/08/2014 - 22:16h

Favoritado =]

[7] Comentário enviado por Thihup em 03/08/2014 - 23:16h


[6] Comentário enviado por razgriz em 02/08/2014 - 22:16h:

Favoritado =]


Muito Obrigado Mano

É difícil escrever um artigo que todos possam entender

Valor por Favoritar

Não se esqueça de deixar o seu 10,0 (rsrs)

T+


[8] Comentário enviado por thiagomiranda3 em 26/09/2014 - 18:45h

Cara muito bom teu artigo.
Da pra ver que você teve um trampo desgramado pra fazer esse artigo pra nós aqui não é? hehe

Parabéns!

Abraços!

[9] Comentário enviado por Thihup em 26/09/2014 - 18:52h

Hehehehehe , pois é 'chapa' (me chamo Thiago tamb)

Entende algo de C ou C++ ?

Se quiser falar comigo

Skype : thihup

E-mail : thupner@gmail.com

[]'s

[10] Comentário enviado por thiagomiranda3 em 26/09/2014 - 19:00h

Já programei umas estruturas de dados em C kkk, mas como não ponho em prática a algum tempo, já esqueci pacas.
To mais afiado com Java e Ruby agora, por conta da faculdade e do TCC.

É difícil eu ficar online no Skype, mas vou te add aqui pra gente tem uma proza outra hora. hehe

Flw!
Abraços

[11] Comentário enviado por thiago211 em 24/10/2014 - 19:57h

Sempre me surpreendendo thihup.

Parabens chará.

[12] Comentário enviado por flcoutos em 27/05/2015 - 13:22h

Bom o seu Artigo!

#Favoritado

[]s!

-----------------------------------------------------------------------------------
Estou tentando aprender, mas, reconheço que eu não sei nada!
Viva o GNU-Linux "Spira Mirabilis DEBIAN"


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts