OpenGL: Stencil Buffer y reflejos

Una de los posibles usos del Stencil Buffer en OpenGL, es en la de añadir objetos reflejados, por ejemplo, en un suelo.

La estrategia a seguir es la siguiente: para simular un reflejo en OpenGL emplearemos un plano que actúe como suelo, y dibujaremos los objetos de nuestra escena dos veces, una de ellas boca abajo empleando un escalado (1,-1,1), que son los que actuarán como reflejo. Para que el reflejo no se salga del suelo haremos un recortado 2D empleando el Stencil Buffer, y para que el reflejo no esté nunca por encima del suelo haremos un recortado 3D con la ecuación del plano (0,-1,0,0).

Pasos a seguir:

1) Activar el Stencil buffer y pintar en él nuestro plano que actúa como suelo, sin dibujar éste en la pantalla (desactivando los canales de color), sólo en el Stencil buffer.
2) Acumular un escalado (1,-1,1) en la cámara (MODELVIEW) para ponerlo todo boca abajo. Resituar las luces invocando a la posición de las mismas para que el escalado S les afecte.
3) Activar el recortado 3D y el recortado 2D (con la función y operación Stencil adecuada).
4) Pintar los objetos (con lo canales de color activos).
5) Desactivar el recortado 2D y 3D. Eliminar el escalado de la matriz cámara (MODELVIEW), normalmente desapilando la misma de la pila de matrices de OpenGL.
6) Resituar las luces a su posición original, invocando su posición.
7) Pintar el suelo semitransparente, para que nos deje ver los objetos que actúan como “supuestos” reflejos.
8) Para terminar se pintan los objetos de la escena en su posición real.

Y el código en OpenGL:

void DrawFloor():

glNewList(FLOOR,GL_COMPILE);
glBegin(GL_QUADS);
glColorMaterial(GL_BACK,GL_SPECULAR);
glColor4f(1.0,1.0,1.0,1.0);
glColorMaterial(GL_BACK,GL_AMBIENT_AND_DIFFUSE);
glColor4f(1.0,1.0,1.0,1.0);
glNormal3f(0,1,0);
glTexCoord2f(0,1);
glVertex3f(-4.0,0.0,-4.0);
glNormal3f(0,1,0);
glTexCoord2f(0,0);
glVertex3f(-4.0,0.0,4.0);
glNormal3f(0,1,0);
glTexCoord2f(1,0);
glVertex3f(4.0,0.0,4.0);
glNormal3f(0,1,0);
glTexCoord2f(1,1);
glVertex3f(4.0,0.0,-4.0);
glEnd();
glEndList();

void RenderScene():

glMatrixMode(GL_MODELVIEW);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
double eqr[]={0.0f,-1.0f,0.0f,0.0f};
glColorMask(0,0,0,0);
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS,1,1);
glStencilOp(GL_KEEP,GL_KEEP,GL_REPLACE);
glDisable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
DrawFloor();
glDisable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glColorMask(1,1,1,1);
glStencilFunc(GL_EQUAL,1,1);
glStencilOp(GL_KEEP,GL_KEEP,GL_KEEP);
glEnable(GL_CLIP_PLANE0);
glClipPlane(GL_CLIP_PLANE0,eqr);
glPushMatrix();
glScalef(1.0f,-1.0f,1.0f);
DrawLights();
DrawObjects();
glPopMatrix();
DrawLights();
glDisable(GL_CLIP_PLANE0);
glDisable(GL_STENCIL_TEST);
glEnable(GL_BLEND);
glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
glColor4f(1.0,1.0,1.0,0.8);
glEnable(GL_LIGHTING);
DrawFloor;
DrawObjects();
glDisable(GL_BLEND);

  • Digg
  • Del.icio.us
  • StumbleUpon
  • Reddit
  • RSS

0 comentarios:

Publicar un comentario