Projeto – Computação Gráfica (IA725)
Jogo
Desenvolvido Em Opengl: Batalha Naval
Professora:
Dra. Wu Shin Ting
Aluno:
Roger F. Larico Chavez
q Aprender a utilizar as bibliotecas
gráficas OpenGL.
q Fazer o jogo “Batalha Naval”
utilizando OpenGL.
q Aplicar os conhecimentos 3D
da disciplina IA725 para o desenvolvimento.
Descrição:
versão em wiraframe (com 3 tipos distintos de navios e posicionamentos
arbitrários de câmera). A entrada das posições dos navios será por teclado
(x,y). Em resposta a cada tentativa do jogador, é adicionada na cena 3D uma
figura da ação correspondente.
Descrição:
versão com tonalização de Gouraud e a possibilidade de chaveamento do cenário
entre o diurno e o noturno (quando navios teráo luzes acesas).
Descrição:
Cenas texturizadas e o jogador seleciona a posição através do cursor.
O
Relatório Técnico é acumulativo (versão [N+1]=+ versão [N]).
Jogo Batalha naval é um jogo antigo que é adivinhar onde que tão os navios. O objetivo do jogador é afundar todos os navios posicionados secretamente pelo adversário. Agora neste projeto poderemos aplicar os conhecimentos de computação gráfica. Aplicaremos isto ao desenvolvimento do jogo. Este desenvolvimento será feito em cenas 3D. O jogo é de funcionamento simples, os jogadores têm que posicionar os seus navios e o adversário adivinhara atirando neles. O usuário poderá ter três respostas: se não atiro no navio, se atiro nele e se afundo a ele.
Ferramentas como OpenGL são utilizadas cada vez mais para aplicações como jogos, isto pela facilidade e potencia que as novas tecnologias dão.
A versão 0.1 é wireframe, tendo uma funcionalidade para 2 jogadores (em diferentes processos e configuráveis numa rede interna). O teclado é importante, nesta versão as coordenadas são dadas pelos números de teclado e as letras adjacentes a eles respectivamente. Será explicado na secção de lógica e funcionamento. Assim como os modelos e a criação das partes do jogo.
A versão 0.2 tem já luzes e iluminação. É aplicado o modelo
de tonalização de
Gouraud.
O jogo Batalha Naval tem uma lógica muito simples. O objetivo dele é destruir as naves do adversário. Mas elas são escondidas antes do adversário. A posição e a orientação das embarcações são escolhidas previamente pelo jogador sem conhecimento do adversário. Durante o jogo, quando uma embarcação é atingida, uma marca sinaliza o local do tiro. Se ela já afunda o navio, ele aparece para já não tentar mais nele. Neste trabalho se faz um protótipo de jogo em rede e solo é para 2 jogadores. Não foi programado para jogar com o computador.
As posições tem que se colocar num arquivo para cada um dos jogadores.
Interações com o usuário:
- Rotação, com o emprego das teclas X para o eixo x, de Y para o eixo y, de Z para o eixo z. desde a posição anterior.
- Zoom, as teclas + e – aumentam o diminuem o tamanho do conteúdo da janela.
- Translação, pode se movimentar com as teclas (i ,o) para eixo x, com as teclas (j ,h) para eixo y, com as teclas (k ,l) para eixo z,
- As posições (X,Y) para iniciar para atirar são:
- hjk
Posição |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
Xà |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
Yà |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
- As posições são uma trás outra, na tela “console” indica qual é o ordem.
- As teclas N e D são utilizadas para chavear o dia e a noite.
- ESC para sair.
-
Resumo: ver
Figura 1: Mapa de teclas a usar no jogo
Interações com o usuário:
- O mouse pode se movimentar (rotação) na direção do eixo X ou eixo Y.
As naves possuem a mesma estrutura, a visualização é dad pela função respectiva a ela.
struct Nave
{
int type;
char* descrip;
int large;
int position[4][2];
}NaveA,NaveB,NaveC;
O modelo A é um navio de tamanho menor, ou seja, ocupa 2 posições no tabuleiro.
Com iluminação pontual.
void DisplayListNaveA()
{
GLUquadricObj* q;
glNewList(NaveA.large-1 , GL_COMPILE);
q = gluNewQuadric();
glPushMatrix();
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
glClearDepth(1.0);
glTranslatef(0,5,1);
glRotatef(90, 1, 0, 0);
glPushMatrix();
glBegin(GL_TRIANGLES);
glVertex3f(15, -2.2, 7.5);
glVertex3f(23, 2.8, 0);
glVertex3f(15, 2.8, 7.5);
glVertex3f(15, 2.8, -7.5);
glVertex3f(23, 2.8, 0);
glVertex3f(15, -2.2, -7.5);
glVertex3f(15, 2.8, 7.5);
glVertex3f(23, 2.8, 0);
glVertex3f(15, 2.8, -7.5);
/**/
glVertex3f(23, 2.8, 0);
glVertex3f(15, -2.2, 7.5);
glVertex3f(15, -2.2, -7.5);
glEnd();
glPopMatrix();
/**/
glPushMatrix();;
glTranslatef(-5,15,0);
glBegin(GL_LINES);
glVertex3f(0, -5, 0);
glVertex3f(0, 0, 0);
glEnd();
float rnd1=random(0,90);
glRotatef(rnd1, 0, 1, 0);
gluCylinder(q,0.1,3,2,8,8);
glPopMatrix();
/**/
//glColor3f(0,0,1);
glPushMatrix();
glTranslatef(-8.3,8.5,4);
glRotatef(90, 0, 1, 0);
gluCylinder(q,1,1.3,2,8,8);
glRotatef(180, 0, 1, 0);
gluCylinder(q,1,1.3,2,8,8);
glPopMatrix();
glPushMatrix();
glTranslatef(-8.3,8.5,-4);
glRotatef(90, 0, 1, 0);
gluCylinder(q,1,1.3,2,8,8);
glRotatef(180, 0, 1, 0);
gluCylinder(q,1,1.3,2,8,8);
glPopMatrix();
/**/
//glColor3f(0.50,0.6,0.52);
glPushMatrix();
glScalef(6,1,3);
glTranslatef(0,0.35,0);
glutSolidCube(5);
glPopMatrix();
/**/
//glColor3f(0,1,0);
glPushMatrix();
glScalef(4,0.5,3);
glTranslatef(-1,8.35,0);
glutSolidCube(5);
glPopMatrix();
/**/
//glColor3f(1,0.5,0);
glPushMatrix();
glScalef(1,1,1);
glTranslatef(-6,8.15,0);
glutSolidCube(5);
glPopMatrix();
//glColor3f(1,1,1);
glPopMatrix();
gluDeleteQuadric(q);
glEndList();
}
O modelo B é um navio de tamanho médio, ou seja, ocupa 3 posições no tabuleiro.
Com iluminação pontual.
void DisplayListNaveB()
{
GLUquadricObj* q;
glNewList(NaveB.large-1, GL_COMPILE);
q = gluNewQuadric();
glTranslatef(0,15,10);
glRotatef(90, 1, 0, 0);
glPushMatrix();
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
glClearDepth(1.0);
glPushMatrix();
glScalef(2,1,2);
glRotatef(-45,0,1,0);
glTranslatef(7.02,0,0.05);
glutSolidCube(3);
glPopMatrix();
/**/
glPushMatrix();
glScalef(6.8,1,2.77);
glTranslatef(-0.01,0,3.62);
glutSolidCube(3);
glPopMatrix();
/**/
glPushMatrix();
glScalef(2,1,2);
glTranslatef(1,3,5);
glRotatef(-45,0,1,0);
glutSolidCube(3);
glPopMatrix();
/**/
glPushMatrix();
glTranslatef(-4,6,10);
glScalef(0.15,0.15,0.15);
glRotatef(-90, 1, 0, 0);
glCallList(7); //tower
glPopMatrix();
glPushMatrix();
glScalef(3.8,1,2.77);
glTranslatef(-1,3,3.62);
glutSolidCube(3);
glPopMatrix();
/**/
glPushMatrix();
glScalef(3.8,1,2.77);
glTranslatef(-1,5.8,3.62);
glutSolidCube(2);
glPopMatrix();
/**/
glPushMatrix();
glTranslatef(4,3,8);
glRotatef(90, 0, 1, 0);
gluCylinder(q,0.5,0.5,2.5,20,10);
glPopMatrix();
/**/
glPushMatrix();
glTranslatef(4,3,12);
glRotatef(90, 0, 1, 0);
gluCylinder(q,0.5,0.5,2.5,20,10);
glPopMatrix();
/**/
/**///janela lampada
glPushMatrix();
glTranslatef(0,6,10);
glRotatef(90, 0, 1, 0);
glTranslatef(-1.5,0,0);
glutSolidCube(1);
glTranslatef(1.5,0,0);
glutSolidCube(1);
glTranslatef(1.5,0,0);
glutSolidCube(1);
glPopMatrix();
glDisable(GL_DEPTH_TEST);
glPopMatrix();
gluDeleteQuadric(q);
glEndList();
}
O modelo C é um navio de maior tamanho, ou seja, ocupa 4 posições no tabuleiro.
Ele e uma porta aviões. Tem aviões na base dele.
Com iluminação pontual.
void DisplayListNaveC()
{
int i;
GLUquadricObj* q;
glNewList(NaveC.large-1, GL_COMPILE);
q = gluNewQuadric();
glTranslatef(0,15,10);
glRotatef(90, 1, 0, 0);
glPushMatrix();
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
glClearDepth(1.0);
/**/
glPushMatrix();
glScalef(2,1,2);
glRotatef(45,0,1,0);
glTranslatef(-7,0,0);
glutSolidCube(3);
glPopMatrix();
/**/
glPushMatrix();
glScalef(2,1,2);
glRotatef(-45,0,1,0);
glTranslatef(7,0,0);
glutSolidCube(3);
glPopMatrix();
/**/
glPushMatrix();
glTranslatef(0,2.2,12.5);
glScalef(0.4,0.4,0.4);
glRotatef(135, 0, 1, 0);
glCallList(6); //Jet
glTranslatef(-5,0,5);
glCallList(6); //Jet
glTranslatef(-5,0,5);
glCallList(6); //Jet
glTranslatef(-5,0,5);
glCallList(6); //Jet
glTranslatef(-5,0,5);
glCallList(6); //Jet
glTranslatef(-5,0,5);
glCallList(6); //Jet
glPopMatrix();
glPushMatrix();
glTranslatef(-10,4,12);
glScalef(0.1,0.1,0.1);
glRotatef(-90, 1, 0, 0);
glCallList(7); //tower
glPopMatrix();
glPushMatrix();
glTranslatef(-12,4,10);
glScalef(0.05,0.05,0.05);
glRotatef(-90,
1, 0, 0);
glRotatef(-90, 0, 0, 1);
glCallList(7); //tower
glPopMatrix();
glPushMatrix();
glTranslatef(-8,4,10);
glScalef(0.07,0.07,0.07);
glRotatef(-90, 1, 0, 0);
glRotatef(+90, 0, 0, 1);
glCallList(7); //tower
glPopMatrix();
glPushMatrix();
glTranslatef(19,3,8);
glScalef(0.4,0.4,0.4);
glRotatef(90, 0, 1, 0);
glRotatef(-25, 1, 0, 0);
glCallList(6); //Jet
glPopMatrix();
/**/
glPushMatrix();
glScalef(6.6,1,2.76);
glTranslatef(0,0,3.62);
glutSolidCube(3);
glPopMatrix();
/*luz pista: centro*/
glPushMatrix();
glScalef(0.5,0.2,0.2);
glTranslatef(-11,9,40);
for(i=0;i<16;i++)
{
glTranslatef(3,0,0);
glutSolidCube(2);
}
glPopMatrix();
/**/
/*luz pista: lados*/
glPushMatrix();
glTranslatef(-5,2,10);
for(i=0;i<24;i++)
{
glTranslatef(1,0,0);
glutSolidSphere(0.3,3,3);
glPushMatrix();
glTranslatef(0,0,-4);
glutSolidSphere(0.3,3,3);
glPopMatrix();
}
glPopMatrix();
/**/
/*pista de avioes*/
glPushMatrix();
glScalef(11,0.2,2.76);
glTranslatef(0,8,3.62);
glutSolidCube(3);
glPopMatrix();
glPushMatrix();
glScalef(11,0.2,1.76);
glTranslatef(0.3,8,4.62);
glutSolidCube(3);
glPopMatrix();
/**/
glPushMatrix();
glScalef(9.6,2,5.76);
glTranslatef(-1,1.5,1.8);
glutSolidCube(1);
glPopMatrix();
/**/
glDisable(GL_DEPTH_TEST);
glPopMatrix();
gluDeleteQuadric(q);
glEndList();
}
As posições de cada jogador estão num arquivo por defauld player1.bn, mas para o segundo jogador é necessário indicar outro arquivo.
O jogo é para duas pessoas com parâmetros de entrada assim:
GameBN.exe
E para o segundo jogador: (é necesario indicar o PATH correto pode ser em rede local)
GameBN.exe player2.bn
Para obter um modelo wireframe é utilizado:
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); //wireframe
A estrtutura é a seguinte:
#define N 10 //tamanho do tabuleiro (items)
//tabuleiro
struct TableGame
{
int list;
int table[N][N];
int dItem1,dItem2,dItem3;
int aItem1,aItem2,aItem3;
}Table;
A tabela é constituída pelas linhas horizontais e verticais.
void DisplayListTable(int
size,float sizeItemTable)
{
float isc=size*sizeItemTable/2;
glNewList(Table.list , GL_COMPILE);
/*PLANO DE TEXTURA DA AGUA*/
/*glPushMatrix();
glTranslatef(0,0,-1);
glColor3f(0,0.45,1);
glBegin(GL_QUADS);
glVertex3f(isc,-isc,0);
glVertex3f(isc,isc,0);
glVertex3f(-isc,isc,0);
glVertex3f(-isc,-isc,0);
glEnd();
glColor3f(1,1,1);
glPopMatrix();
/**/
glColor3f(0.73,0.74,1);
glPushMatrix();
glScalef(1,1,0.01);
glTranslatef(0,0,-24);
glutSolidCube(N*sizeItemTable);
glPopMatrix();
glColor3f(1,1,1);
/*RETICULADO items*/
glBegin(GL_LINES);
for(int i=-size/2;i<=size/2;i++)
{
glVertex3f(i*sizeItemTable,-isc,0);
glVertex3f(i*sizeItemTable, isc,0);
glVertex3f(-isc,i*sizeItemTable,0);
glVertex3f( isc,i*sizeItemTable,0);
}
glEnd();
/**/
glEndList();
}
Os cubos vermelhos são posições onde foi atirada alguma embarcação.
Os quadros defasados verdes são posições onde atiraram na água.
Quando uma nave é atingida totalmente, ela aparece na tela.
No jogo todas as embarcações são atingidas.
A tabela representa a água então se utilizara uma textura procedimental para representar as ondas aleatoriamente (não é apresentado).
//ondas : TEXTURA PROCEDIMENTAL ALEATORIA
for(i=0;i<N;i++)
for(j=0;j<N;j++)
{
SystemCoordenateGame(i,j,&x1,&y1);
SystemCoordenateGame(i+1,j+1,&x2,&y2);
glBegin(GL_TRIANGLES);
glVertex3f(x1,y1,0);
glVertex3f(x2,y2,0);
glVertex3f(x1,y1,random(0,sizeItem)/5);
glVertex3f(x1,y1,0);
glVertex3f(x2,y2,0);
glVertex3f(x2,y2,random(0,sizeItem)/5);
glVertex3f(x1,y1,0);
glVertex3f(x2,y2,0);
glVertex3f((x1+x2)/2,(y1+y2)/2,random(0,sizeItem)/5);
glEnd();
}
As seguintes telas foram capturadas depois de várias tentativas.
Depois de afundar todos as naves.
As seguintes telas foram capturadas depois de várias tentativas.
Depois de afundar todos as naves.
aqui se percebe a tonalização de Gouraud :
A simulação da iluminação do dia por ‘defauld’ é feita através da alteração das propriedades da fonte de luz.
glLightModelfv ( GL_LIGHT_MODEL_AMBIENT, ambient_light
);
glLightfv (GL_LIGHT0,GL_DIFFUSE,
source_light );
glLightfv (GL_LIGHT0,GL_SPECULAR, spec_light);
Os parâmetros iluminação de dia são:
GLfloat ambient_light[] = { 0.2, 0.2, 0.2, 1.0};
GLfloat source_light[] = { 1.0, 1.0, 1.0, 1.0};
GLfloat spec_light[] = { 1.0, 1.0, 1.0, 1.0};
Noite: tecla ‘n’
Os parâmetros iluminação de noite são:
GLfloat ambient_light_n[] = { 0.0, 0.0, 0.0, 1.0 };
GLfloat source_light_n [] = { 0.2, 0.2, 0.2,
1.0 };
GLfloat spec_light_n [] = { 1.0, 1.0,
1.0, 1.0};
A posição da fonte luminosa (sol ou lua) é:
GLfloat light_pos[] = { 7.0, 0.0, 0.0,
1.0};
Outras provas feitas. SPOT
Para outros parâmetros e provas com tonalidades em escala de cinza são: (versão com lâmpadas acesas):
Para: iluminação se utiliza os seguintes parâmetros:
GLfloat
ambient_light[] = { 0.2, 0.2, 0.2, 1.0};
GLfloat
source_light[] = { 1.0, 1.0, 1.0, 1.0};
GLfloat
spec_light[] = { 1.0, 1.0, 1.0, 1.0};
GLfloat light_pos[] = { 0, 25, 0, 1};//pontual
glEnable ( GL_LIGHTING );
//iniciamos
de dia
glLightModelfv (
GL_LIGHT_MODEL_AMBIENT, ambient_light );
glLightfv (GL_LIGHT0,GL_DIFFUSE,
source_light );
glLightfv (GL_LIGHT0,GL_SPECULAR,
spec_light);
glLightfv ( GL_LIGHT0,GL_POSITION, light_pos );
glLightf(GL_LIGHT0,GL_SPOT_CUTOFF,50);
//glLightf(GL_LIGHT0,GL_SPOT_EXPONENT,30);
//glLightf(GL_LIGHT0,GL_QUADRATIC_ATTENUATION,30);
//habilitar fonte de luz
glEnable ( GL_LIGHT0 );
glEnable ( GL_LIGHT1 );
//
Enable de las propiedades del material para la iluminación
glEnable ( GL_COLOR_MATERIAL );
glColorMaterial ( GL_FRONT, GL_AMBIENT_AND_DIFFUSE );
De noite:
Agora de com algumas jogadas: de dia e noite.
Quando a iluminação e quase nula – posição oposta -- se
percebe a luminancia das janelas e as luzes acesas dos navios.
- Na Versão 3. O mouse pode se escolher a casa onde atirar: ate agora é utilizado o comando gluPickMatrix( (GLdouble)x, (GLdouble) (ViewportCoordinates[3] - y),5.0,5.0,ViewportCoordinates). O desenvolvimento do mouse e como fazer um passo de 2D para #d e vise versa e com uma vista do plano asim:
- O código fonte e o seguinte:
void Mouse(int button, int state, int x, int y)
{
if(state)
{
Path SelectedPath;
int Seleccionado=0;
Seleccionado =
GetSelection(x,y,&SelectedPath);
if(Seleccionado)
{ TransXY(SelectedPath.Identifiers[SelectedPath.NIdentifiers-1],N);
printf("MOUSE: objeto escolhido : %i (x,y) = (%i ,%i)\n",SelectedPath.Identifiers[SelectedPath.NIdentifiers-1],X,Y);
Fire(Y,X);
glutPostRedisplay();
}else
{
X=-1;Y=-1;
}
modo de jogo para o Mouse:
Uso dos comandos de Textura para carregar imagens RGB:
void
carregar_texturas(void)
{
IMAGE *img;
GLenum gluerr;
/* textura do plano */
glGenTextures(1, &textura_plano);
glBindTexture(GL_TEXTURE_2D, textura_plano);
if(!(img=ImageLoad(TEXTURA_DO_PLANO))) {
fprintf(stderr,"Error reading a texture.\n");
exit(-1);
}
gluerr=gluBuild2DMipmaps(GL_TEXTURE_2D, 3,
img->sizeX, img->sizeY,
GL_RGB, GL_UNSIGNED_BYTE,
(GLvoid *)(img->data));
if(gluerr){
fprintf(stderr,"GLULib%s\n",gluErrorString(gluerr));
exit(-1);
}
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
/* textura do aviao */
glGenTextures(1, &textura_aviao);
glBindTexture(GL_TEXTURE_2D, textura_aviao);
if(!(img=ImageLoad(TEXTURA_DO_AVIAO))) {
fprintf(stderr,"Error reading a texture.\n");
exit(-1);
}
gluerr=gluBuild2DMipmaps(GL_TEXTURE_2D, 3,
img->sizeX, img->sizeY,
GL_RGB, GL_UNSIGNED_BYTE,
(GLvoid *)(img->data));
if(gluerr){
fprintf(stderr,"GLULib%s\n",gluErrorString(gluerr));
exit(-1);
}
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
}
Carregando o fundo de água: (textura em bmp mas foi criada
com o algoritmo CELLULAR)
As seguintes telas foram no
testador de modelos.
As Texturas for aplicadas:
arquivos:
água, camuflagem1,
camuflagem2 e textura de metal velho.
Telas
com algumas textura utilizadas
misturando texturas (camuflagem 1 e2 )
O modulo TestOpenGL é uma ferramenta que faz traslacoes, rotações, escalamentos para cada tipo dede modedlo utilizado neste projeto.
Ela foi desenvolvida para facilitar a visualização dos modedlos antes de ser colocados no jogo. Contem iluminação e tem as principais opções:
As figuras dos modelos na seção modelos são produzidas neste modulo de teste.
Com iluminação. Navios e detalhes de dia sem luzes acesas.
Com iluminação. Navios de noite com luzes acesas.
Escuridão Normal e Escuridão Total
(se percebe que as luzes acesas sempre estão ligadas)
A organização de arquivos é de um projeto em Visual C++. O arquivo principal é nomeado GameBN.cpp ele contem as funções de callback e da configuração da bibliotecas Glut e OpenGLe E a lógica do jogo. O arquivo struct.h possui as definições e estruturas dos navios. O arquivo models.h contem os modelos dos três tipos de navios.
Tabela de arquivos. |
||||||||||||||||||
|
* precisa-se de glut32.dll.
A Implementação e as funcionalidades foram atingidas. Além de apresentar, a versão 1 em wireframe como exigido,a apresenta desenhos completos e funcionalidades do mouse. A versão 2 tem naves com cores definidos com iluminação. A rotações do tabuleiro são efetuadas com o mouse e o teclado. A escolha das células para atirar é pelo teclado.
A utilização de OpenGL foi fundamental para facilitar o trabalho em 3D.
Os conceitos de computação gráfica, são utilizados diretamente em projetos de OpenGL.
O modelo de iluminação direcional (Gouraud) é o mais indicado para uma iluminação de dia ou noite real (aproximadamente).
A textura utilizada no jogo da realismo nas cenas utilizadas, mas o custo computacional aumenta.