Geração de Visão Estereoscópica

1.     Posicionamento do Observador

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.

1.1     Imagens Entrelaçadas: técnicas e dispositivos

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.

 

1.2     Imagens Alternadas: técnicas e dispositivos

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