A idéia básica de criação de imagens estereoscópicas em OpenGL é geração de imagem diferente para cada olho a partir da mudança da posição do observador.
Uma forma simples de efetuar esta mudança de posição é apresentada na Figura 1.1 onde o observador é movido para a esquerda ou para a direita, conforme o olho para o qual se deseja gerar a cena.
//
*************************************************************
// void PosicUser()
// esta função define a posicão de cada um dos olhos do
// observador
//
// Variáveis usadas:
// DistOlhos: distância entre os olhos do usuário
//
// *************************************************************
void PosicUser(int Olho)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(80,ratio,0.01,200);
switch (Olho)
{
case ESQUERDO: // seta posição para o olho esquerdo
gluLookAt(-DistOlhos/2, 0, 5, 0, 0, 0, 0.0f,1.0f,0.0f);
break;
case DIREITO: // seta posição para o olho direito
gluLookAt(DistOlhos/2, 0, 5, 0, 0, 0, 0.0f,1.0f,0.0f);
break;
}
glMatrixMode(GL_MODELVIEW);
}
Figura 1.1 –
Posicionamento do Observador para geração de Imagens Estereoscópicas
Uma abordagem mais detalhada sobre o posicionamento do observador para a geração de imagens estereoscópicas pode ser encontrado em http://astronomy.swin.edu.au/~pbourke/opengl/stereogl.
Além de gerar duas imagens diferentes, é preciso exibi-las uma para cada olho. A forma de fazer esta exibição depende do tipo de dispositivo que está sendo usado. Nas seções a seguir são apresentadas duas formas de realizar esta tarefa, cada uma vinculada a um tipo de dispositivo.
No caso do uso de Óculos do tipo I-Glasses, a separação entre a imagem do olho esquerdo e do olho direito é feita pelo hardware do óculos que põe no visor do olho direito as imagens das linhas pares da tela, e no visor do olho esquerdo a imagem das linhas ímpares.
Maiores informações sobre este tipo de óculos podem ser obtidas no site http://www.i‑glassesstore.com. Atente para o fato de que nem todos os modelos disponíveis nesta página têm capacidade de exibir imagens estereoscópicas.
Para fazer a separação das imagens na tela, usa-se o stencil buffer, com o seguinte algoritmo:
· Bloqueia-se, através do stencil buffer, a exibição das imagens nas linhas impares;
· Exibe-se a imagem referente ao olho direito;
· Libera-se, através do stencil buffer, a exibição das imagens nas linhas impares;
· Bloqueia-se, através do stencil buffer, a exibição das imagens nas linhas pares;
· Exibe-se a imagem referente ao olho esquerdo
O bloqueio (ou desbloqueio) das linhas pares e ímpares neste caso é feito através da montagem de uma “máscara” no stencil, conforme a Figura 1.2. Esta máscara é, na verdade, um conjunto de linhas horizontais desenhadas no stencil, somente nas linhas pares da tela.
//
****************************************************************
// void DesenhaFundo()
// Inicializa o stencil com 1 nas linhas pares
//
// ****************************************************************
void DesenhaFundo(int Largura, int Altura )
{
//
Habilita o uso do Stencil
glEnable(GL_STENCIL_TEST);
//
Define que "0" será usado para limpar o Stencil
glClearStencil(0);
// limpa o Stencil
glClear(GL_STENCIL_BUFFER_BIT);
glStencilFunc(GL_ALWAYS, 1, 1);
glStencilOp(GL_REPLACE,GL_REPLACE,GL_REPLACE);
// desenha a máscara nas linhas pares
glMatrixMode(GL_PROJECTION);
//
glLoadIdentity ();
gluOrtho2D(0, Largura, 0, Altura);
glMatrixMode(GL_MODELVIEW);
glBegin(GL_LINES);
// inicializa apenas as linhas pares no stencil
for (int y= 0; y < Altura; y += 2)
{
DrawLine(0,y, Largura, y);
}
glEnd();
// volta à matriz de objetos
//glMatrixMode(GL_MODELVIEW);
}
Figura 1.2 - Marcação das linhas pares no stencil buffer
No momento da exibição dos objetos do cenário, o programador deve habilitar e desabilitar o desenho sobre as linhas marcadas no stencil. A Figura 1.3 demonstra este procedimento.
//
*****************************************************************
//
void HabilitaOlhoEsquerdo()
//
//
//
*****************************************************************
void HabilitaOlhoEsquerdo()
{
glStencilFunc(GL_NOTEQUAL,
1, 1);
glStencilOp(GL_KEEP,GL_KEEP,
GL_KEEP);
}
//
*****************************************************************
//
void HabilitaOlhoDireito()
//
//
//
*****************************************************************
void HabilitaOlhoDireito()
{
glStencilFunc(GL_EQUAL,
1, 1);
glStencilOp(GL_KEEP,GL_KEEP,
GL_KEEP);
}
//
*****************************************************************
//
//
//
*****************************************************************
void display( void )
{
// Limpa a tela
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
DefineLuz();
PosicUser(ESQUERDO);
// posiciona o observador no olho esquerdo
HabilitaOlhoEsquerdo();
DesenhaCena();
PosicUser(DIREITO);
// posiciona o observador no olho direito
HabilitaOlhoDireito();
DesenhaCena();
glutSwapBuffers();
}
Figura 1.3 –
Exibição de Cenas Estereoscópicas com Stencil Buffer
Neste link tem-se um exemplo de um programa que gera uma imagem estereoscópica entrelaçada.
O uso de imagens alternadas depende do uso de um óculos do tipo shutter-glasses e de uma placa de vídeo que suporte a geração de estéreo. O processo de posicionamento do observador continua sendo o mesmo descrito na seção 1.1.
Primeiramente o programador deve inicializar a biblioteca GLUT com a opção de estereoscopia. Caso a placa de vídeo não suporte esta característica, ocorrerá um erro neste momento. O comando para esta inicialização é:
glutInitDisplayMode(GLUT_DOUBLE
| GLUT_RGB | GLUT_STEREO);
No momento de exibir o cenário, o programador deverá definir para que olho está gerando a imagem, através da escolha do buffer de desenho. Na Figura 1.4 apresenta-se um trecho de código que faz esta tarefa.
void display( void )
{
// Limpa a tela
DefineLuz();
PosicUser(ESQUERDO);
// posiciona o observador no olho esquerdo
glDrawBuffer(GL_BACK_LEFT);
// ativa BUFFER ESQUERDO
glClearColor(1.0,
0.0, 0.0, 1.0); /* red */
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
DesenhaCena();
PosicUser(DIREITO); // posiciona o observador no olho direito
glDrawBuffer(GL_BACK_RIGHT);
// ativa BUFFER DIREITO
glClearColor(0.0,
0.0, 1.0, 1.0); /* blue */
glClear(GL_COLOR_BUFFER_BIT);
DesenhaCena();
glutSwapBuffers();
}
Figura 1.4 – Exibição de Cenas Estereoscópicas para shutter-glasses