Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Ayuda Stencil Buffer Sombras

Iniciado por videador, 10 de Enero de 2006, 11:36:39 PM

« anterior - próximo »

videador

 Saludos

Estoy intentando proyectar sombras de objetos sobre un plano delimitado.

Proyecto bien la sombra pero quiero utilizar el stencil buffer para que la sombra solo se proyecte en el plano.

Resulta que no consigo hacerlo. He mirado muchos codigos y sigo sin conseguirlo.

Os pego lo que yo tengo.

Se supone que esto pone a 1 los bits de los pixeles del plano -en el stencil buffer- para luego usar este como filtro al proyectar los demas objetos no es así?


       glEnable(GL_STENCIL_TEST);
       glStencilFunc(GL_ALWAYS, 1, 1);
       glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);

       drawPlane();  //Con GL_QUADS

       glDisable(GL_STENCIL_TEST);


Sin entrar en mejoras. Si yo vuelvo a activar el test y dibujo el objeto -proyectado, esa parte la tengo bien- solo se dibujara en el plano dibujado por drawPlane(), ¿no es así?

Entonces una vez multiplicado por la matrix de proyeccion segun luz y plano.
Hago lo siguiente. drawObj dibuja un cilindro con una cuadrica.


               glEnable(GL_STENCIL_TEST);

               glStencilFunc(GL_EQUAL, 1, 1);
               glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);

                       drawObj();   //Cilindro con cuadrica

               glDisable(GL_STENCIL_TEST);


Según tengo entendido se pone GL_ZERO para que cuando se dibuje el bit del pixel se vuelva a cero y no se vuelva a dibujar mas. y GL_EQUAL para dibujar si es igual a 1.

Bueno pues esto es lo que obtengo.



Sé que puede quedar mas bonito con transparencias y con mas soluciones, pero estoy intentando lo basico para ir poco a poco y me he quedado al principio. Tengo una Geforce FX 5200 o sea si tengo Stencil Buffer -o eso creo-.

Gracias de antemano!.

Pongo algo mas de código por si acaso que no he querido condensar arriba para una mayor legibilidad -aunque no es na de na-.

Pongo todo el codigo del render por si acaso, como veis esta en plan chapuza de tantas intentonas.



........

       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

       glClearStencil(0);

       glMatrixMode(GL_MODELVIEW);
       glLoadIdentity();

       glPushMatrix();

       setView();
       //Establecemos la luz, según la camara
       glLightfv(GL_LIGHT0,GL_POSITION,PosLuz);

       //Dibujamos la luz
       glPushMatrix();
       glColor4fv(yellow);
       glTranslatef(PosLuz[0],PosLuz[1],PosLuz[2]);
       GLUquadricObj* qobj=gluNewQuadric();
       gluSphere(qobj,3,15,15);
       glPopMatrix();
       ////////////////////

       //Dibujamos plano

       glEnable(GL_STENCIL_TEST);
       glStencilFunc(GL_ALWAYS, 1, 1);
       glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);

       drawPlane();

       glDisable(GL_STENCIL_TEST);

       /////////////////////////////////////////////

       /////////////////////////////////////////////
       //Dibujamos el cilindro
       glPushMatrix();

       glColor4fv(grey);
       drawObj();

       glPopMatrix();
       //////////////////////////////////////////////

       //Sombras

       GLfloat plano[4]={0,1,0,0};
       GLfloat floorshadow[4][4];

           glDisable(GL_LIGHTING);

           glColor4f(0.2f, 0.2f, 0.2f,0.5f);  /* shadow color */

           //Calculamos las ecuaciones del plano
           //findplane(GLfloat plane[4],GLfloat v0[3], GLfloat v1[3], GLfloat v2[3]);
           //Calculamos matriz de proyección de la sombra

           shadowmatrix(floorshadow, plano, PosLuz);

           //glEnable(GL_BLEND);
           //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

           glPushMatrix();

           glMultMatrixf((GLfloat *) floorshadow);


               glEnable(GL_STENCIL_TEST);

               glStencilFunc(GL_EQUAL, 1, 1);
               glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);

                       drawObj();

               glDisable(GL_STENCIL_TEST);

           glPopMatrix();

           //glDisable(GL_BLEND);

           glEnable(GL_LIGHTING);

       glPopMatrix();

.......


void drawPlane(){

       glPushMatrix();
       //glColor4fv(purple);
       glBegin(GL_QUADS);
               glNormal3f(0.0, 1.0, 0.0);
               glVertex3f(0,0,0);
               glNormal3f(0.0, 1.0, 0.0);
               glVertex3f(0,0,500);
               glNormal3f(0.0, 1.0, 0.0);
               glVertex3f(500,0,500);
               glNormal3f(0.0, 1.0, 0.0);
               glVertex3f(500,0,0);

       glEnd();
       glPopMatrix();

}








Pogacha

 La verdad es que le dudo a muchas cosas ... el orden de esto:
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

      glClearStencil(0);
Aun que no debiera importar realmente.

Es la tercera vez que leo el codigo y no estoy seguro de como es tu metodo, lo que sí me parece "raro" los comandos que usas para las operaciones de stencil, y la comparación

De todos modos, si lo primero que haces es esto       glEnable(GL_STENCIL_TEST);
      glStencilFunc(GL_ALWAYS, 1, 1);
      glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);

      drawPlane();  //Con GL_QUADS

      glDisable(GL_STENCIL_TEST);
, no entiendo contra que comparas con el stencil si lo acabas de borrar!, ya no recuerdo pero no deberias activar la escritura en stencil en vez de la comparación (test)?

Saludos.

videador

 Antes de nada, darte las gracias por mirar el problema.

Citar
no entiendo contra que comparas con el stencil si lo acabas de borrar!, ya no recuerdo pero no deberias activar la escritura en stencil en vez de la comparación (test)?

En OpenGL para activar el Stencil Buffer que yo tenga entendido solo es con GL_STENCIL_TEST, es la única forma.

El metodo según he leido en mil sitios es que:

-Activas el Stencil Buffer, para que pasen todos los pixeles y los que pasen les ponga un 1. (GL_ALWAYS)
-Dibujas el plano donde proyectara la sombra.
-Desactivas el Stencil.

Entonces se supone que el Stencil tienes los pixeles del plano marcados con un 1.

-Calculas la matrix de sombras.
-Activas el Stencil para que solo pasen los pixeles que tengan un 1, o sea los del plano, y que los demas
no se dibujen. (GL_EQUAL)
-Pintas el objeto proyectado -se supone que solo pasaran los que esten dentro del plano.
-Desactivas el Stencil Buffer.

Ese es el metodo. Pero no consigo que funcione. :(.



marcode

 hola

Quizás no tienes el formato de pixel creado con un buffer stencil. En glut hay que pasarle un flag que no me acuerdo ahora cuál es, y si has creado la ventana a pelo hay que indicar en el formato de pixel el número de bits del stencil buffer.
size=9]afortunadamente siempre ha habido alguien dispuesto a reinventar la rueda, de lo contrario seguiríamos usando un disco de piedra con un agujero.[/size]

Pogacha

 La verdad es que ese metodo no es el mejor de todos ... o sea, no te servirá para nada mas ...

Hace poco en otro thread alguien posteo este link con un buen tutorial, te diria que lo sigas para ver si puedes sacar algo de este:
http://www.geocities.com/duktroa/RealTimeS...dowTutorial.htm

Saludos, siento no poder hacer mas pero mi tiempo me está acogotando ...

Yoshi.css

 Hola.

Aprovecho este post para plantear mi duda, ya que mi problema va por el mísmo camino.

Bueno, esto ya es un poco a la desesperada, he mirado decenas de ejemplos, códigos, etc... y no hay forma de que funcione. No se si es fallo mío, o posible problema de mi tarjeta (GeForce 3Ti200). No se.  Os pongo un ejemplo muy sencillito que debería funcionar, sin embargo no hay forma:

Stencil Buffer en OpenGL
Tengo un simple triángulo, y un un cuadrado a recortar. Compruebo las posiciones y veo que el triángulo me tapa parte del cuadrado, por lo que voy a activar los píxeles de objeto a 1 en el stencil (el resto están a cero), y posteriormente dibujar el cuadrado solamente en aquellas posiciones donde el stencil esté a 1. En teoría, debería quedarme en pantalla la parte del cuadrado donde antes estaba el triángulo, pero me dibuja todo el cuadrado.

Código:
Citar
//Borramos los 3 búferes implicados.
glClear( GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT );
//Desactivamos el test de profundidad. En principio no lo necesitamos para dibujar en el Stencil Buffer
glDisable(GL_DEPTH_TEST);
//No queremos dibujar en el buffer de color.
glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);

//Activamos el Stencil test
glEnable(GL_STENCIL_TEST);
//Queremos que todos los píxeles del triángulo estén a uno.
glStencilOp(GL_REPLACE,GL_REPLACE,GL_REPLACE);
//Obligamos a que siempre pase el test.
glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF);

//El susodicho triángulo
DibujarTriangulo();

//Ahora le indicamos al programa que queremos dibujar en el buffer de color.
glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
//Activamos el test de profundidad, aunque creo que no lo necesito pues no tengo nada en el buffer de profundidad.
glEnable(GL_DEPTH_TEST);

//Importánte: ahora le decimos a OpenGL que deje seguir a los píxeles cuyo valor de stencil sea igual a 1.
glStencilFunc(GL_EQUAL, 1,0xFFFFFFFF);
//No queremos que modifique nada en el Stencil.
glStencilOp(GL_KEEP,GL_KEEP,GL_KEEP);

//El cuerpo del delito.
DibujarCuadrado();

//Desactivamos el test de stencil.
glDisable(GL_STENCIL_TEST);

En fín, a ver si veis vosotros algo que no vea yo.
Gracias por llegar hasta aquí.

PD: Videador, ¿eres de la Complutense? :D

Actualizado
No lo he dicho, pero utilizo Borland C++ Builder con OpenGL Panel. Sí, lo se, pero no tenemos otra opción para las prácticas.

Yoshi.css

 
Cita de: "marcode"hola

Quizás no tienes el formato de pixel creado con un buffer stencil. En glut hay que pasarle un flag que no me acuerdo ahora cuál es, y si has creado la ventana a pelo hay que indicar en el formato de pixel el número de bits del stencil buffer.
Vale, creo que ya se cual es el problema. Siguiendo la línea de pensamiento de Marcode, efectívamente me falta activar el PFD que permite el uso del Stencil Buffer. Lo más gracioso es que en el OpenGL Panel, todo está tan automatizado y tan cuco para activar y desactivar cosas con el ratón, que me veo imposibilitado para activar dicha opción. Vamos, que no lo han incluido.

Intentaré buscarme la vida con GLAUX.  (asco)

Gracias de todas maneras.

Un saludo.






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.