Tutorial OpenGL v2.0

Finalmente chegou! Após quase 1 ano depois de meu primeiro artigo sobre OpenGL, chegou a versão 2.0. Clique e fique mais Geek.

[ Hits: 17.557 ]

Por: Thiago Henrique Hüpner em 08/05/2015


OpenGL e SDL botando pra quebrar



Bom, esse artigo é sobre SDL + OpenGL, mas cadê a presença do OpenGL nesse programa?

Na verdade, esse programa seria apenas o 'main' do programa mesmo, pois para o OpenGL atuar, devemos utilizar mais funções.

Observem o exemplo abaixo:

// Inclui a biblioteca SDL
#include <SDL/SDL.h>

// Inclui a biblioteca do SDL que tem o OpenGL
#include <SDL/SDL_opengl.h>

// Função que Desenha na Tela
void desenhaNaTela(){

// 'Limpa' a tela usando a cor de 'limpar' a tela
	glClear(GL_COLOR_BUFFER_BIT);

	// Define a Cor de 'limpar' para Branco usando
			//   Red     Blue    Green   Alpha
	glClearColor(255.0f, 255.0f, 255.0f, 1.0f);

	// Reinicia todas as transformações e/ou rotações
	glLoadIdentity();

	// Rotaciona x por y com 0 de profundidade (usado p/ jogos 3D)
	glTranslatef(400/2,400/2,0);

	// Começa a desenhar Quadrados
	glBegin(GL_QUADS);

		// Colori de Verde
		glColor3f (  0.0f,  1.0f, 0.0f );

		// Lado Inferior Esquerdo
		glVertex2f( 0,  10.0f );

		// Colori de Vermelho
		glColor3f (  1.0f,  0.0f, 0.0f );

		// Lado Superior Esquerdo
		glVertex2f( 0, 0 );

		// Colori de Amarelo
		glColor3f (  1.0f,  1.0f , 0.0f);

		// Lado Superior Direito
		glVertex2f(  10.0f, 0 );

		// Colori de Azul
		glColor3f (  0.0f,  0.0f, 1.0f );

		// Lado Inferior Direito
		glVertex2f(  10.0f,  10.0f );

	// Termina de Desenhar
	glEnd();
}

// Função que Inicializa o OpenGL
void inicializaOpenGL(){

	// Define a Cor de 'limpar' para Branco usando
			//   Red     Blue    Green   Alpha
	glClearColor(255.0f, 255.0f, 255.0f, 1.0f);

	// Avisa o OpenGL que qualquer alteração futura
	// afetará a Câmera ( O Observador)
	glMatrixMode(GL_PROJECTION);

	//  Reinicia todas as transformações e/ou rotações
	glLoadIdentity();

	// Define a projeção cartesiana 2D iniciando de (0,0)
	// No Lado Superior Esquerdo (ficando igual a projeção do SDL 'puro')
	gluOrtho2D(0,400,400,0);

	// Avisa o OpenGL que qualquer alteração futura
	// afetará o/os desenho/desenhos
	glMatrixMode(GL_MODELVIEW);

	// 'Limpa' a tela usando a cor de 'limpar' a tela
	glClear(GL_COLOR_BUFFER_BIT);
}

// Função Principal
int main(int argc,char *argv[]){

	// Se a inicialização do e o Subsistema de video falhar ...
	if(SDL_Init(SDL_INIT_VIDEO) < 0){
		// ... imprima a mensagem de erro e ...
		printf("Erro : %s
",SDL_GetError());
		// ... encerre o programa com 'erro'
		return -1;
	}

	//Define alguns atributos do OpenGL, tais como ...

	// Numero minimo de bits da cor Vermelha ;
	SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 );

	// Numero minimo de bits da cor  Verde ;
	SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8 );

	// Numero minimo de bits da cor Azul ;
	SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 8 );

	// Tamanho do pixels da cor Alfa ;
	SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 8 );

	// E o Buffer duplo ( 1 ligado , 0 desligado )
	SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );

	// Cria a Janela
	SDL_Surface * tela = SDL_SetVideoMode(400,400,32,SDL_OPENGL);

	// Se algum erro acontecer com na criação da Janela...
	if(tela == NULL){

		// ... imprima o erro ...
		printf("Erro : %s
",SDL_GetError());

		// ... feche o SDL e ...
		SDL_Quit();

		// ... encerre o programa com 'erro'
		return -1;
	}

	// Define o título da janela
	SDL_WM_SetCaption("Exemplo Básico SDL + OpenGL",NULL);

	// Variável para os eventos
	SDL_Event evento;

	// Controle do Loop
	int estaRodando = 1;

	// Inicia o OpenGL
	inicializaOpenGL();

	// Loop Principal
	while(estaRodando){

		// Lê a fila de eventos e põe o evento mais antigo em "evento"
		while(SDL_PollEvent(&evento)){

			// Entre nos tipos de eventos ...
			switch(evento.type){

				// ... caso o 'X' da janela foi apertado ...
				case SDL_QUIT:

					// ... então saia do Loop Principal.
					estaRodando = 0;

				break;

				// Outros eventos ....

				default:

				break;

			}
		}

		// Desenha na Tela
		desenhaNaTela();

		// Espera 30 milissegundos para não forçar uso do processador
		SDL_Delay(30);

		// Troca os Buffers e mostra o buffer antigo
		SDL_GL_SwapBuffers();
	}

	// Encerra o SDL
	SDL_Quit();

	// Nenhum erro ocorrido =D
	return 0;

}

Salve esse arquivo como "SegundaJanela.c" e compile com:

gcc -o SegundaJanela SegundaJanela.c -lSDL -lGL -lGLU -Wall

Esse programa mostra um pequeno quadrado no meio da tela, está ok o programa, mas já está ficando confuso usar o 400 para altura, 400 para largura e utilizar o tamanho '10.0f' no glVertex2f.

Então, para facilitar nosso entendimento, iremos utilizar algumas macros para deixar o programa mais "legível". Segue exemplo:

// Inclui a biblioteca SDL
#include <SDL/SDL.h>

// Inclui a biblioteca do SDL que tem o OpenGL
#include <SDL/SDL_opengl.h>

// Altura da Janela (eixo Y)
#define ALTURA 400

// Largura da Janela (eixo X)
#define LARGURA 400

// Tamanho do Quadrado
#define TAMANHO 10

// Função que Desenha na Tela
void desenhaNaTela(){

// 'Limpa' a tela usando a cor de 'limpar' a tela
	glClear(GL_COLOR_BUFFER_BIT);

	// Reinicia todas as transformações e/ou rotações
	glLoadIdentity();

	// Rotaciona x por y com 0 de profundidade (usado p/ jogos 3D)
	glTranslatef(LARGURA/2,ALTURA/2,0);

	// Começa a desenhar Quadrados
	glBegin(GL_QUADS);

		// Colori de Verde
		glColor3f (  0.0f,  1.0f, 0.0f );

		// Lado Inferior Esquerdo
		glVertex2f( 0,  TAMANHO );

		// Colori de Vermelho
		glColor3f (  1.0f,  0.0f, 0.0f );

		// Lado Superior Esquerdo
		glVertex2f( 0, 0 );

		// Colori de Amarelo
		glColor3f (  1.0f,  1.0f , 0.0f);

		// Lado Superior Direito
		glVertex2f(  TAMANHO, 0 );

		// Colori de Azul
		glColor3f (  0.0f,  0.0f, 1.0f );

		// Lado Inferior Direito
		glVertex2f(  TAMANHO,  TAMANHO );
	// Termina de Desenhar
	glEnd();
}

// Função que Inicializa o OpenGL
void inicializaOpenGL(){

	// Define a Cor de 'limpar' para Branco usando
			//   Red     Blue    Green   Alpha
	glClearColor(255.0f, 255.0f, 255.0f, 1.0f);

// 'Limpa' a tela usando a cor de 'limpar' a tela
	glClear(GL_COLOR_BUFFER_BIT);

	// Avisa o OpenGL que qualquer alteração futura
	// afetará a Câmera ( O Observador)
	glMatrixMode(GL_PROJECTION);

	//  Reinicia todas as transformações e/ou rotações
	glLoadIdentity();

	// Define a projeção cartesiana 2D iniciando de (0,0)
	// No Lado Superior Esquerdo (ficando igual a projeção do SDL 'puro')
	gluOrtho2D(0,LARGURA,ALTURA,0);

	// Avisa o OpenGL que qualquer alteração futura
	// afetará o/os desenho/desenhos
	glMatrixMode(GL_MODELVIEW);

	// 'Limpa' a tela usando a cor de 'limpar' a tela
	glClear(GL_COLOR_BUFFER_BIT);
}

// Função Principal
int main(int argc,char *argv[]){

	// Se a inicialização do e o Subsistema de video falhar ...
	if(SDL_Init(SDL_INIT_VIDEO) < 0){
		// ... imprima a mensagem de erro e ...
		printf("Erro : %s
",SDL_GetError());
		// ... encerre o programa com 'erro'
		return -1;
	}

	//Define alguns atributos do OpenGL, tais como ...

	// Numero minimo de bits da cor Vermelha ;
	SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 );

	// Numero minimo de bits da cor  Verde ;
	SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8 );

	// Numero minimo de bits da cor Azul ;
	SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 8 );

	// Tamanho do pixels da cor Alfa ;
	SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 8 );

	// E o Buffer duplo ( 1 ligado , 0 desligado )
	SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );

	// Cria a Janela
	SDL_Surface * tela = SDL_SetVideoMode(400,400,32,SDL_OPENGL);

	// Se algum erro acontecer com na criação da Janela...
	if(tela == NULL){

		// ... imprima o erro ...
		printf("Erro : %s
",SDL_GetError());

		// ... feche o SDL e ...
		SDL_Quit();

		// ... encerre o programa com 'erro'
		return -1;
	}

	// Define o título da janela
	SDL_WM_SetCaption("Exemplo Básico SDL + OpenGL",NULL);

	// Variável para os eventos
	SDL_Event evento;

	// Controle do Loop
	int estaRodando = 1;

	// Inicia o OpenGL
	inicializaOpenGL();

	// Loop Principal
	while(estaRodando){

		// Lê a fila de eventos e põe o evento mais antigo em "evento"
		while(SDL_PollEvent(&evento)){

			// Entre nos tipos de eventos ...
			switch(evento.type){

				// ... caso o 'X' da janela foi apertado ...
				case SDL_QUIT:

					// ... então saia do Loop Principal.
					estaRodando = 0;

				break;

				// Outros eventos ....

				default:

				break;

			}
		}

		// Desenha na Tela
		desenhaNaTela();

		// Espera 30 milissegundos para não forçar uso do processador
		SDL_Delay(30);

		SDL_GL_SwapBuffers();
	}

	// Encerra o SDL
	SDL_Quit();

	// Nenhum erro ocorrido =D
	return 0;

}

Salve esse arquivo como "SegundaJanelav2.c" e compile com:

gcc -o SegundaJanelav2 SegundaJanelav2.c -lSDL -lGL -lGLU -Wall

Deverá aparecer uma janela como esta:
Linux: Tutorial OpenGL v2.0
Certo, temos um quadrado no meio da tela, mas podemos adicionar mais funções a ele, por exemplo, o clique do mouse para mover o quadrado para lá, ou podemos movê-lo com as setinhas.

Segue novo exemplo:

// Inclui a biblioteca SDL
#include <SDL/SDL.h>

// Inclui a biblioteca do SDL que tem o OpenGL
#include <SDL/SDL_opengl.h>

// Altura da Janela (eixo Y)
#define ALTURA 400

// Largura da Janela (eixo X)
#define LARGURA 400

// Tamanho do Quadrado
#define TAMANHO 10

#define VELOCIDADE 10

// Função que Desenha na Tela
void desenhaNaTela(float x,float y){

// 'Limpa' a tela usando a cor de 'limpar' a tela
	glClear(GL_COLOR_BUFFER_BIT);

	// Reinicia todas as transformações e/ou rotações
	glLoadIdentity();

	// Rotaciona x por y com 0 de profundidade (usado p/ jogos 3D)
	glTranslatef(x,y,0);
	// Começa a desenhar Quadrados
	glBegin(GL_QUADS);

		// Colori de Verde
		glColor3f (  0.0f,  1.0f, 0.0f );

		// Lado Inferior Esquerdo
		glVertex2f( 0,  TAMANHO );

		// Colori de Vermelho
		glColor3f (  1.0f,  0.0f, 0.0f );

		// Lado Superior Esquerdo
		glVertex2f( 0, 0 );

		// Colori de Amarelo
		glColor3f (  1.0f,  1.0f , 0.0f);

		// Lado Superior Direito
		glVertex2f(  TAMANHO, 0 );

		// Colori de Azul
		glColor3f (  0.0f,  0.0f, 1.0f );

		// Lado Inferior Direito
		glVertex2f(  TAMANHO,  TAMANHO );
	// Termina de Desenhar
	glEnd();
}

// Função que Inicializa o OpenGL
void inicializaOpenGL(){

	// Define a Cor de 'limpar' para Branco usando
			//   Red     Blue    Green   Alpha
	glClearColor(255.0f, 255.0f, 255.0f, 1.0f);

	// Avisa o OpenGL que qualquer alteração futura
	// afetará a Câmera ( O Observador)
	glMatrixMode(GL_PROJECTION);

	//  Reinicia todas as transformações e/ou rotações
	glLoadIdentity();

	// Define a projeção cartesiana 2D iniciando de (0,0)
	// No Lado Superior Esquerdo (ficando igual a projeção do SDL 'puro')
	gluOrtho2D(0,LARGURA,ALTURA,0);

	// Avisa o OpenGL que qualquer alteração futura
	// afetará o/os desenho/desenhos
	glMatrixMode(GL_MODELVIEW);

	// 'Limpa' a tela usando a cor de 'limpar' a tela
	glClear(GL_COLOR_BUFFER_BIT);
}

// Função Principal
int main(int argc,char *argv[]){

	// Se a inicialização do e o Subsistema de video falhar ...
	if(SDL_Init(SDL_INIT_VIDEO) < 0){
		// ... imprima a mensagem de erro e ...
		printf("Erro : %s
",SDL_GetError());
		// ... encerre o programa com 'erro'
		return -1;
	}

	//Define alguns atributos do OpenGL, tais como ...

	// Numero minimo de bits da cor Vermelha ;
	SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 );

	// Numero minimo de bits da cor  Verde ;
	SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8 );

	// Numero minimo de bits da cor Azul ;
	SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 8 );

	// Tamanho do pixels da cor Alfa ;
	SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 8 );

	// E o Buffer duplo ( 1 ligado , 0 desligado )
	SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );

	// Cria a Janela
	SDL_Surface * tela = SDL_SetVideoMode(400,400,32,SDL_OPENGL);

	// Se algum erro acontecer com na criação da Janela...
	if(tela == NULL){

		// ... imprima o erro ...
		printf("Erro : %s
",SDL_GetError());

		// ... feche o SDL e ...
		SDL_Quit();

		// ... encerre o programa com 'erro'
		return -1;
	}

	// Define o título da janela
	SDL_WM_SetCaption("Exemplo Básico SDL + OpenGL",NULL);

	// Variável para os eventos
	SDL_Event evento;

	// Controle do Loop
	int estaRodando = 1;

	// Velocidade X e Velocidade Y
	int velX = 0,velY = 0;

	// Posição X e Posição Y
	int posX = LARGURA/2, posY = ALTURA/2;

	// Inicia o OpenGL
	inicializaOpenGL();

	// Loop Principal
	while(estaRodando){

		// Lê a fila de eventos e põe o evento mais antigo em "evento"
		while(SDL_PollEvent(&evento)){

			// Entre nos tipos de eventos ...
			switch(evento.type){

				// ... caso o 'X' da janela foi apertado ...
				case SDL_QUIT:

					// ... então saia do Loop Principal.
					estaRodando = 0;

				break;
				case SDL_KEYUP:
					switch(evento.key.keysym.sym){
						// Se soltou seta pra cima (^) ou para baixo (v)...
						case SDLK_UP:
						case SDLK_DOWN:
							// ...faz parar no eixo Y
							velY = 0;
						break;

						// Se soltou seta para direita (->) ou esquerda (<-)...
						case SDLK_RIGHT:
						case SDLK_LEFT:
						// ...faz parar no eixo X
							velX = 0;
						break;

						default:
						break;
					}
				break;

				case SDL_KEYDOWN:
					switch(evento.key.keysym.sym){

						case SDLK_ESCAPE:
							// Sairá do loop na proxima iteração
							estaRodando = 0;
						break;

						case SDLK_UP:
							// Faz a velocidade Y ser negativa para mover para cima (^)
							velY = -VELOCIDADE;
						break;

						case SDLK_DOWN:
							// Faz a velocidade Y ser positiva para mover para baixo (v)
							velY = VELOCIDADE;
						break;

						case SDLK_RIGHT:
							// Faz a velocidade X ser positiva para mover para direita (->)
							velX = VELOCIDADE;
						break;

						case SDLK_LEFT:
							// Faz a velocidade X ser negativa para mover para esquerda (<-)
							velX = -VELOCIDADE;
						break;

						default:
						break;
					}
				break;

				// Caso apertou algum botão do mouse
				case SDL_MOUSEBUTTONDOWN:
					// A posição do quadrado se iguala a posição do mouse
					posX = evento.button.x;
					posY = evento.button.y;
				default:

				break;

			}
		}

		// Soma o valor da posição com o valor da posição com o valor da velocidade
		posX = posX + velX;
		posY = posY + velY;

		// Desenha na Tela
		desenhaNaTela(posX,posY);

		// Espera 30 milissegundos para não forçar uso do processador
		SDL_Delay(30);

		SDL_GL_SwapBuffers();
	}

	// Encerra o SDL
	SDL_Quit();

	// Nenhum erro ocorrido =D
	return 0;

}

Salve esse programa como "TerceiraJanela.c" e compile com:

gcc -o TerceiraJanela TerceiraJanela.c -lSDL -lGL -lGLU -Wall

Não vou colocar imagem, pois não mudou nada "graficamente". Compile este você mesmo. =D

Agora já é possível ter uma noção do uso básico da incrível junção do SDL + OpenGL.

Página anterior     Próxima página

Páginas do artigo
   1. Introdução
   2. Inicializando o SDL
   3. OpenGL e SDL botando pra quebrar
   4. Simulando uma Gambiarra
   5. A jornada é longa parte 1 - Colisão Mouse e Retângulo
   6. A jornada é longa parte 2 - Colisão entre 2 Retângulos
   7. "Imagine" seu programa
   8. Agradecimentos, links úteis e fontes
Outros artigos deste autor

Tutorial OpenGL v3.0

Visual Studio no Linux

Ubuntu/Debian/Kali Linux e outros no Android

Tutorial OpenGL

Tutorial SFML

Leitura recomendada

Criando um sistema operacional com ASM e C++

Ponteiros void na linguagem C

Como aprender a programar e produzir aplicativos usando Euphoria

Aleatoriedade em C

Criando programas com suporte a arquivos de configuração com a libConfuse

  
Comentários
[1] Comentário enviado por fabio em 08/05/2015 - 10:30h

Muito bom! Vou tentar criar um game simples pra minha filha ficar clicando no retângulo com a cor certa com base neste tutorial.

[2] Comentário enviado por Thihup em 08/05/2015 - 11:21h


[1] Comentário enviado por fabio em 08/05/2015 - 10:30h

Muito bom! Vou tentar criar um game simples pra minha filha ficar clicando no retângulo com a cor certa com base neste tutorial.


Fábio, mais uma vez, muito obrigado !

E boa sorte com o aplicativo, espero que sua filha goste.

Qualquer dúvida só pedir =D

[]'s

T+

[3] Comentário enviado por UmCaraAToa em 08/05/2015 - 11:25h

Bom artigo!
Favoritado e pega meu 10!

Até

[4] Comentário enviado por Thihup em 08/05/2015 - 11:30h


[3] Comentário enviado por UmCaraAToa em 08/05/2015 - 11:25h

Bom artigo!
Favoritado e pega meu 10!

Até


Valeu fera

T+

[5] Comentário enviado por xerxeslins em 08/05/2015 - 11:49h


Favoritado. Vou ler depois com calma. Mas só de dar uma olhada por rápida vi que é material interessante!
--
http://pastebin.com/aji5Qp05

[6] Comentário enviado por Thihup em 08/05/2015 - 11:55h


[5] Comentário enviado por xerxeslins em 08/05/2015 - 11:49h


Favoritado. Vou ler depois com calma. Mas só de dar uma olhada por rápida vi que é material interessante!
--
http://pastebin.com/aji5Qp05


Valeu fera, Obrigado!

[]'s

T+

[7] Comentário enviado por preroeb em 08/05/2015 - 19:02h

Parabéns pelo artigo escrito, é uns dos melhores (e únicos) artigos sobre OpenGL aqui no VOL.

[8] Comentário enviado por Thihup em 08/05/2015 - 19:04h


[7] Comentário enviado por preroeb em 08/05/2015 - 19:02h

Parabéns pelo artigo escrito, é uns dos melhores (e únicos) artigos sobre OpenGL aqui no VOL.


Valew pela força!

Dando duro pra trazer um artigo de qualidade pra vocês, meu povinho do "Volzinho"!

[]'s

T+

[9] Comentário enviado por Felipeigor em 08/05/2015 - 19:43h

Ae Parabéns brother excelente artigo , favoritado aqui tbm :)

Igor Felipe
Cadastrado desde: 25/09/2009

[b]If it moves , compile it.[/b]

[10] Comentário enviado por Thihup em 08/05/2015 - 19:44h


[9] Comentário enviado por Felipeigor em 08/05/2015 - 19:43h

Ae Parabéns brother excelente artigo , favoritado aqui tbm :)

Igor Felipe
Cadastrado desde: 25/09/2009

[b]If it moves , compile it.[/b]


Valew Tambem pelo apoio!

[]'s

T+

[11] Comentário enviado por SamL em 09/05/2015 - 12:50h

Legal cara, bem explicada a parte sobre colisão. Um bom artigo como um todo. Parabéns.

[12] Comentário enviado por Thihup em 09/05/2015 - 13:40h


[11] Comentário enviado por SamL em 09/05/2015 - 12:50h

Legal cara, bem explicada a parte sobre colisão. Um bom artigo como um todo. Parabéns.


Valew Sam! Sempre me apoiando!

[]'s

T+

[13] Comentário enviado por Ang em 09/05/2015 - 16:14h

Oi, Thiago!
Dei uma rápida lida no seu artigo.
Está muito bom!
Continue assim, com essas ótimas contribuições!

Ang,
Manaus, AM, Brasil.
Usuário de sistemas operacionais livres/abertos tipo Unix ou tipo DOS,
Distros Favoritas: FreeBSD, Free-DOS, , PC-DOS, Bodhi Linux, Ubuntu, Big Linux, Kurumim, OpenSUSE, Slackware e Slax.

[14] Comentário enviado por Thihup em 09/05/2015 - 16:18h


[13] Comentário enviado por Ang em 09/05/2015 - 16:14h

Oi, Thiago!
Dei uma rápida lida no seu artigo.
Está muito bom!
Continue assim, com essas ótimas contribuições!

Ang,
Manaus, AM, Brasil.
Usuário de sistemas operacionais livres/abertos tipo Unix ou tipo DOS,
Distros Favoritas: FreeBSD, Free-DOS, , PC-DOS, Bodhi Linux, Ubuntu, Big Linux, Kurumim, OpenSUSE, Slackware e Slax.


Valew !
Obrigado por ter lido!

[]'s

T+


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts