Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Problemas con shadow mapping

Iniciado por misscelan, 06 de Febrero de 2007, 12:23:23 PM

« anterior - próximo »

misscelan

Buenas,

Estoy intentando implementar shadow mapping con extensiones arb en mi aplicación y la cosa no funciona.

La teoría no sé si la tengo muy clara. Por lo que entiendo primero se debe hacer es colocarte en el lugar de luz y guardar el buffer de profundidad en una textura, después te desplazas al lugar donde está la cámara, tranformas los puntos actuales para poder compararlos con el buffer guardado y así poder distinguer cuales deberían estar en sombra o no.

La parte de generar el shadow map la tengo funcionando, pero ahí tengo mi primera duda, vi que en algunos ejemplos para poder debugear sacaban la textura por pantalla, yo lo hice y veo la imagen desde el punto de vista de luz, pero yo pensaba que los datos guardados en el buffer de profundidad era algo ilegible como poder sacarlo en una textura por pantalla.

La segunda parte por los ejemplos que tengo no me entero de nada.
Utilizan un  método para generar las coordenadas de la textura automáticamente.


float mRowTextures1[4] = {1.0f,0.0f,0.0f,0.0f};
   float mRowTextures2[4] = {0.0f,1.0f,0.0f,0.0f};
   float mRowTextures3[4] = {0.0f,0.0f,1.0f,0.0f};
   float mRowTextures4[4] = {0.0f,0.0f,0.0f,1.0f};
.
   glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
   glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
   glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
   glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
   glTexGenfv(GL_S, GL_EYE_PLANE, mRowTextures1);
   glTexGenfv(GL_T, GL_EYE_PLANE, mRowTextures2);
   glTexGenfv(GL_R, GL_EYE_PLANE, mRowTextures3);
   glTexGenfv(GL_Q, GL_EYE_PLANE, mRowTextures4);
   glEnable(GL_TEXTURE_GEN_S);
   glEnable(GL_TEXTURE_GEN_T);
   glEnable(GL_TEXTURE_GEN_R);
   glEnable(GL_TEXTURE_GEN_Q);

   glMatrixMode( GL_TEXTURE );
   glLoadIdentity();
   glTranslatef( 0.5f, 0.5f, 0.5f );                      // Offset
   glScalef( 0.5f, 0.5f, 0.5f );                          // Bias
   glMultMatrixf( mLightView.m );


La última parte entiendo que es para convertir los puntos para poder compararlos con el depth buffer y lo del offset y bias para evitar algunos problemas que se puedan dar.

Pero la primera parte no la entiendo, todo el tema de generación de las coordenadas, qué hace cada comando que sale ahí?

Bueno, si me solucionáis esto volveré con más.

Muchas gracias.

Un saludo.

misscelan

Hola,

Necesito retomar el post porque esto sigue sin ir bien.
Voy a poner algo más de código y algunas imágenes a ver si alguien me puede echar una mano.

Lo estoy intentando hacer con extensiones arb, en los foros de igda me han comentado que es mucho más fácil implementarlos con shaders directamente. Pero toda la información que encuentro sobre shadow mapping con shaders utilizan técnicas más avanzadas. ¿Alquien tiene info sobre shadow mapping básico con shaders?.

Bueno, estoy siguiendo de guía el código de pauls project http://www.paulsprojects.net/tutorials/smt/smt.html . He cambiado algunas cosas para adecuarlas a mi código.

Una foto de la escena inicial.



Esta es la función que genera el shadow map


glMatrixMode(GL_MODELVIEW);
   glPushMatrix();
   glLoadMatrixf(mLightView.m);


   glViewport(0, 0, TEXTURE_SHADOW_SIZE, TEXTURE_SHADOW_SIZE);


   glEnable(GL_CULL_FACE);
   glCullFace(GL_FRONT);
   glDisable(GL_LIGHTING);
   glShadeModel(GL_FLAT);
   //glDisable(GL_COLOR_MATERIAL);
   glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);

   draw_cube2();
   draw_cube3();

   //render_light();
   //bsp_render2();

   glEnable(GL_TEXTURE_2D);

   glBindTexture(GL_TEXTURE_2D, text_shadow);
   glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, TEXTURE_SHADOW_SIZE, TEXTURE_SHADOW_SIZE);

   glCullFace(GL_BACK);
   glShadeModel(GL_SMOOTH);
   glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
   //glEnable(GL_COLOR_MATERIAL);

   glDisable(GL_CULL_FACE);

   glClear(GL_DEPTH_BUFFER_BIT);

   //glMatrixMode(GL_PROJECTION);
   //gluPerspective(70.0f, conf_get_scr(SCR_WD)/conf_get_scr(SCR_HG), 10.0f, 7000.0f);
  // glPopMatrix();

   //glMatrixMode(GL_MODELVIEW);
   glPopMatrix();
   //glLoadIdentity();


   glViewport(0, 0, conf_get_scr(SCR_WD), conf_get_scr(SCR_HG));


Esta es una imagen del shadow map


Codigo de la segunda pasada

glLightfv(GL_LIGHT1, GL_POSITION, lightpos);
   glLightfv(GL_LIGHT1, GL_AMBIENT, white);
   glLightfv(GL_LIGHT1, GL_DIFFUSE, white);
   glLightfv(GL_LIGHT1, GL_SPECULAR, black);
   glEnable(GL_LIGHT1);
   glEnable(GL_LIGHTING);
   glDisable(GL_LIGHTING);

   draw_cube2();
   draw_cube3();


Y el código de la tercera.

 glLightfv(GL_LIGHT1, GL_DIFFUSE,  white);
   glLightfv(GL_LIGHT1, GL_SPECULAR, white);


   matriz mTexture;

   glPushMatrix();
   glLoadIdentity();
   glMultMatrixf(mBias.m);
   glMultMatrixf(mLightProj.m);
   glMultMatrixf(mLightView.m);
   glGetFloatv( GL_MODELVIEW_MATRIX, mTexture.m );
   glPopMatrix();

   float mRowTextures1[4];
   /*float mRowTextures1[4] = {1.0f,0.0f,0.0f,0.0f};
   float mRowTextures2[4] = {0.0f,1.0f,0.0f,0.0f};
   float mRowTextures3[4] = {0.0f,0.0f,1.0f,0.0f};
   float mRowTextures4[4] = {0.0f,0.0f,0.0f,1.0f};*/

   //transposeMatrix(mTexture.m);
   glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);

mRowTextures1[0] = mTexture.m[0];
mRowTextures1[1] = mTexture.m[1];
mRowTextures1[2] = mTexture.m[2];
mRowTextures1[3] = mTexture.m[3];
glTexGenfv(GL_S, GL_EYE_PLANE, mRowTextures1);
glEnable(GL_TEXTURE_GEN_S);

glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
mRowTextures1[0] = mTexture.m[4];
mRowTextures1[1] = mTexture.m[5];
mRowTextures1[2] = mTexture.m[6];
mRowTextures1[3] = mTexture.m[7];
glTexGenfv(GL_S, GL_EYE_PLANE, mRowTextures1);
glEnable(GL_TEXTURE_GEN_T);

glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
mRowTextures1[0] = mTexture.m[8];
mRowTextures1[1] = mTexture.m[9];
mRowTextures1[2] = mTexture.m[10];
mRowTextures1[3] = mTexture.m[11];
glTexGenfv(GL_S, GL_EYE_PLANE, mRowTextures1);
glEnable(GL_TEXTURE_GEN_R);

glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
mRowTextures1[0] = mTexture.m[12];
mRowTextures1[1] = mTexture.m[13];
mRowTextures1[2] = mTexture.m[14];
mRowTextures1[3] = mTexture.m[15];
glTexGenfv(GL_S, GL_EYE_PLANE, mRowTextures1);
glEnable(GL_TEXTURE_GEN_Q);

glBindTexture(GL_TEXTURE_2D, text_shadow);
glEnable(GL_TEXTURE_2D);

   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
   glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY);


   glAlphaFunc(GL_GEQUAL, 0.99f);
   glEnable(GL_ALPHA_TEST);

   draw_cube2();
   draw_cube3();

   glDisable(GL_TEXTURE_GEN_S);
   glDisable(GL_TEXTURE_GEN_T);
   glDisable(GL_TEXTURE_GEN_R);
   glDisable(GL_TEXTURE_GEN_Q);

   glDisable(GL_LIGHTING);
   glDisable(GL_ALPHA_TEST);

   glFinish();


El resultado final...


Parece que el problema está en el tema de la generación de las coordenadas de textura.

Alguién me puede contestar a algo?

Muchas gracias.

Un saludo.

marcode

Parece como si sólo se pintase la primera vez con la luz ambiente.

¿No será que falla siempre el test de profundidad en el tercer paso al compararse como menor con el primer render y deberías establecerlo como glDepthFunc(GL_LEQUAL); ?
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]

Prompt

Ese resultado de color plano sin textura lo suele dar por la coordenada Q que generas. En el caso de que esté mal asignada suele dar ese problema.


PD: una respuesta un poco tarde pero bueno :D

Prompt

Por si alguien le sirve de ayuda en el futuro, se debe pasar las coordenadas de textura al shader con:

glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, COORDENADAS[0][0]); <----------

Si no se hace esto despues de generar las coordenadas automaticamente el shader ni se entera.

misscelan

A ver si alguien me puede echar una mano porque sigo con problemas.
Al final usé glsl y la verdad es que simplifica mucho más las cosas (el procedimiento parece más lógico).

Ahora que tengo una versión inicial del shadow mapping funcionando me encuentro con todos los defectos de esta técnica (shadow acné, sombras con unos dientes enormes, etc...).

Para los dientes de sierra tengo pensado usar PCF, para el resto de cosas estuve buscando una técnica que no fuese muy difícil de implementar y ofreciese una solución algo decente, al final me quede con Second-depth, para los que no hayan oído hablar de ella, consiste en crear dos mapas de profundidad desde dos puntos y compararlos para así tratar de aliviar los problemas de precisión.

El caso es que después de implementarla los resultados que obtengo me gustan menos que los que obtenía con un solo mapa.

Usando la función "shadow2DProj(ShadowMap, ProjShadow).r" consigues obtener si el fragmento del shader está iluminado ahora mismo o no (0,1) según el mapa que selecciones.

El primer depth map lo creo desde la posición original de la luz, el segundo lo creo avanzando una cuarta parte de la profundidad en la dirección hacia donde mira la cámara.

Depués dentro de glsl tengo algo así:

float a = shadow2DProj(ShadowMap, ProjShadow).r; //primer depth map
float b = shadow2DProj(ShadowMap2, ProjShadow2).r; //segundo depth map



if ((a + b) > 0.0) {

 //pinto normal

}

else { //pinto sombra}

Si hago esto, supuestamente le estoy diciendo que si este fragmento esta iluminado en alguno de los dos, lo ilumine. El caso es el volumen de las sombras disminuye notablemente y siguen numeros defectos.

Si hago (a * b) > 0.

Las sombras tienen más volumen pero cojo los defectos de los dos.

Lo que no tengo muy seguro es si puedo comparar esos dos depth maps de esta manera. Cada uno tiene su matriz de proyección y vista independientes. Como he dicho la matriz de vista se diferencián en que una empieza un poco más delante que la anterior.

El caso es que descarté los shadow volumes porque me parecía un coñazo implementarlos y parecía mucho más sucio, pero joder para conseguir unas sombras con esto decentes!!!...

Resumiendo, ¿alguien tiene implementado second depth con resultados satisfactorios? ¿qué métodos usa para comparar los depth?.

Cual es para vosotros la mejor técnica (resultado-coste) para solventar los problemas del shadow mapping?.

Muchas gracias.

Un saludo.

BeRSeRKeR

Hace tiempo que le eché un vistazo al second-depth shadow mapping pero me parece recordar que como segunda profundidad pillaba las caras opuestas a la luz. Es decir, que renderizaba la escena con el ocultamiento de caras invertido (desde la posición de la luz, por supuesto).

Evidentemente, con esto seguirás teniendo problemas con los objetos con poco grosor y por supuesto con los objetos sin grosor.

Lo que no recuerdo es cómo fueron los resultados. Creo recordar que hacía su trabajo pero aún así teníamos otros problemas (típicos del shadow mapping). Pero bueno, ahora hay otras técnicas que parecen solventar esos problemas.

Me imagino que la técnica sigue conservándose en JadEngine.

Saludos.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!






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.