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.
Parte 7: "Imagine" seu programa
Após saber colisão, já é possível criar alguns joguinhos. Mas espere, e as imagens?
Diferentemente do que devem estar pensando, colocar uma imagem no OpenGL é mais complexo do que o próprio SDL. Mas não desanimem, não é impossível!
Salve essa imagem como "sdl.bmp":
Segue o exemplo em código:
Esse exemplo não possui comentários explicando, mas deixe que eu explico:
#define TAMANHO_IMAGEM 128 :: Eu utilizei essa constante pois ajuda na hora de desenhar na tela. Se quiser, deixe como está, mas se sua imagem não for de 128x128, ela poderá ser deformada.
GLuint carregarImagem(const char *nomeImg) :: É a função encarregada de converter uma imagem carregada pelo SDL em textura do OpenGL (e retorna um GLuint, ou seja, um "unsigned int 'padronizado'".
glGenTextures(1, &textura) :: O OpenGL gera um "objeto de textura" que será encarregado de armazenar uma textura.
glBindTexture(GL_TEXTURE_2D, textura) :: O OpenGL "diz" ao "objeto de textura" que será carregado uma "GL_TEXTURE_2D", ou seja, carregará uma imagem em 2D.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
E:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); :: Definem as propriedades de "alongamento", ou seja, como será o preenchimento caso seja maior que a imagem. Por exemplo, a imagem é de 16x16 e será utilizado em um retângulo de 256x256 (por exemplo), com esses parametro irá definir como será a proporção.
glTexImage2D(GL_TEXTURE_2D, 0, 3, img->w, img->h, 0,
GL_RGR, GL_UNSIGNED_BYTE, img->pixels); :: Coloca a imagem do SDL na "textura" do OpenGL.
void colocandoImagemNaTela(GLuint textura, int x,int y) :: Essa função vai fazer o que o nome sugere: colocar a textura na tela.
glBindTexture(GL_TEXTURE_2D, textura); :: "Diz" ao próximos manipuladores que a textura a ser utilizada é a o conteudo da variavel "textura".
glTranslatef(x,y,0); :: Coloca a textura na posição X e Y
glTexCoord2f(0, 0); :: Aqui é a mesma regra do SDL_Rect, ou seja, o canto superior esquerdo = {0,0}, canto inferior esquero = {1,0},...
colocandoImagemNaTela(textura,50,50); :: Coloca a textura na posição X: 50 e Y: 50.
Bom, parece complicado. E é, mas após pegar o jeito isso daqui é moleza.
Com esse exemplo, se apenas modificarmos no Main, o "sdl.bmp" para outro nome de arquivo ou criar outra textura e colocar em outra posição também vai funcionar.
Temos um programa funcional. =D
Diferentemente do que devem estar pensando, colocar uma imagem no OpenGL é mais complexo do que o próprio SDL. Mas não desanimem, não é impossível!
Salve essa imagem como "sdl.bmp":

#include <SDL/SDL.h>
#include <SDL/SDL_opengl.h>
#include <time.h>
#define LARGURA 400
#define ALTURA 400
#define TAMANHO_IMAGEM 128
GLuint carregarImagem(const char *nomeImg) {
SDL_Surface *img = SDL_LoadBMP(nomeImg);
GLuint textura;
if(img == NULL) {
printf("Erro ao carregar a imagem %s: %s
",nomeImg,SDL_GetError());
SDL_FreeSurface(img);
exit(-1);
}
glGenTextures(1, &textura);
glBindTexture(GL_TEXTURE_2D, textura);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, 3, img->w, img->h, 0,
GL_RGR, GL_UNSIGNED_BYTE, img->pixels);
SDL_FreeSurface(img);
return textura;
}
void colocandoImagemNaTela(GLuint textura, int x,int y) {
glBindTexture(GL_TEXTURE_2D, textura);
glLoadIdentity();
glTranslatef(x,y,0);
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex2f(0, 0);
glTexCoord2f(1, 0);
glVertex2f(TAMANHO_IMAGEM, 0);
glTexCoord2f(1, 1);
glVertex2f(TAMANHO_IMAGEM, TAMANHO_IMAGEM);
glTexCoord2f(0, 1);
glVertex2f(0, TAMANHO_IMAGEM);
glEnd();
}
void inicializaOpenGL() {
glClearColor(255,255,255,1);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//Necessário para exibir a imagem
glEnable(GL_TEXTURE_2D);
gluOrtho2D(0,LARGURA,ALTURA,0);
glMatrixMode(GL_MODELVIEW);
glClear(GL_COLOR_BUFFER_BIT);
}
void GL_FillRect(SDL_Rect a,int r,int g,int b) {
glLoadIdentity();
glColor3ub(r,g,b);
glBegin(GL_QUADS);
glVertex2f(a.x,a.y);
glVertex2f(a.x+a.w,a.y);
glVertex2f(a.x+a.w,a.y+a.h);
glVertex2f(a.x,a.y+a.h);
glEnd();
}
int main(int argc,char *argv[]) {
if(SDL_Init(SDL_INIT_VIDEO) < 0) {
printf("Erro : %s
",SDL_GetError());
return -1;
}
srand((unsigned)time(NULL));
SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 2 );
SDL_Surface * tela = SDL_SetVideoMode(LARGURA,ALTURA,32,SDL_OPENGL);
if(tela == NULL) {
printf("Erro : %s
",SDL_GetError());
SDL_Quit();
return -1;
}
SDL_WM_SetCaption(""Imagenando"",NULL);
SDL_Event evento;
int estaRodando = 1;
inicializaOpenGL();
GLuint textura = carregarImagem("cb.bmp");
while(estaRodando) {
while(SDL_PollEvent(&evento)) {
switch(evento.type) {
case SDL_QUIT:
estaRodando = 0;
break;
default:
break;
}
}
glClear(GL_COLOR_BUFFER_BIT);
colocandoImagemNaTela(textura,50,50);
SDL_Delay(30);
SDL_GL_SwapBuffers();
}
SDL_Quit();
glDeleteTextures(1, &textura);
return 0;
}
Esse exemplo não possui comentários explicando, mas deixe que eu explico:
#define TAMANHO_IMAGEM 128 :: Eu utilizei essa constante pois ajuda na hora de desenhar na tela. Se quiser, deixe como está, mas se sua imagem não for de 128x128, ela poderá ser deformada.
GLuint carregarImagem(const char *nomeImg) :: É a função encarregada de converter uma imagem carregada pelo SDL em textura do OpenGL (e retorna um GLuint, ou seja, um "unsigned int 'padronizado'".
glGenTextures(1, &textura) :: O OpenGL gera um "objeto de textura" que será encarregado de armazenar uma textura.
glBindTexture(GL_TEXTURE_2D, textura) :: O OpenGL "diz" ao "objeto de textura" que será carregado uma "GL_TEXTURE_2D", ou seja, carregará uma imagem em 2D.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
E:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); :: Definem as propriedades de "alongamento", ou seja, como será o preenchimento caso seja maior que a imagem. Por exemplo, a imagem é de 16x16 e será utilizado em um retângulo de 256x256 (por exemplo), com esses parametro irá definir como será a proporção.
glTexImage2D(GL_TEXTURE_2D, 0, 3, img->w, img->h, 0,
GL_RGR, GL_UNSIGNED_BYTE, img->pixels); :: Coloca a imagem do SDL na "textura" do OpenGL.
void colocandoImagemNaTela(GLuint textura, int x,int y) :: Essa função vai fazer o que o nome sugere: colocar a textura na tela.
glBindTexture(GL_TEXTURE_2D, textura); :: "Diz" ao próximos manipuladores que a textura a ser utilizada é a o conteudo da variavel "textura".
glTranslatef(x,y,0); :: Coloca a textura na posição X e Y
glTexCoord2f(0, 0); :: Aqui é a mesma regra do SDL_Rect, ou seja, o canto superior esquerdo = {0,0}, canto inferior esquero = {1,0},...
Main
GLuint textura = carregarImagem("sdl.bmp"); :: Carrega a textura da imagem "sdl.bmp".colocandoImagemNaTela(textura,50,50); :: Coloca a textura na posição X: 50 e Y: 50.
Bom, parece complicado. E é, mas após pegar o jeito isso daqui é moleza.
Com esse exemplo, se apenas modificarmos no Main, o "sdl.bmp" para outro nome de arquivo ou criar outra textura e colocar em outra posição também vai funcionar.
Temos um programa funcional. =D