Hola, estoy empezando a programar (o al menos intentarlo) un juego en OpenGL para PC.
Estoy intentando implementar sombras realistas pero no consigo hacerlas aparecer.... quiza el procedimiento que sigo no sea adecuado y por eso necesito ayuda.
El casting de caras afectadas por la luz lo hago y es relativamente acertado, asi komo crear la silueta a proyectar, y su proyeccion hacia un infinito cercano... creo ke el problema lo tengo a la hora de usar el stencil buffer...
Este es el codigo del casting de caras afectadas por la luz, marcar las aristas de silueta e intentar proyectar la sombra...
[PHP]
void MODEL::CastShadow(float *LightPos)
{
//Rotacion necesaria por la posicion inicial del modelo que cargo...
glRotatef(-90.0, 1.0, 0.0, 0.0);
glRotatef(-90.0, 0.0, 0.0, 1.0);
//Calculo caras afectadas por la luz
for(unsigned i=0; i { // Posicion de lus enfrente de plano?
if(PtrFaces[i].Plane.IsInFrontPlane(VECTOR3D(LightPos[0], LightPos[1], LightPos[2])))
PtrFaces[i].Visible=true;
else
PtrFaces[i].Visible=false;
}
//Busco aristas para formar la silueta de la sombra
for(unsigned i=0; i {
//La cara no se ve afectada por la luz?
if(!PtrFaces[i].Visible)
{ //No tiene bordes de silueta
for(unsigned j=0; i<3; i++)
PtrFaces[i].SilhouetteEdge[j]=false;
continue;
};
for(unsigned j=0; j<3; j++)
{ //Cara afectada por la luz y sin cara vecina o la cara vecina no afectada por la luz?
if(PtrFaces[i].NeighbourIndices[j]==-1 || !PtrFaces[PtrFaces[i].NeighbourIndices[j]].Visible)
PtrFaces[i].SilhouetteEdge[j]=true;
else
PtrFaces[i].SilhouetteEdge[j]=false;
};
};
glDisable(GL_TEXTURE_2D); //Desactivo texturas por prevencion
glDisable(GL_LIGHTING); //Desactivo iluminacion
glDepthMask(GL_FALSE);
glDepthFunc(GL_LEQUAL);
glEnable(GL_CULL_FACE); //Activo el cull facing
glCullFace(GL_BACK); //La cara trasera es la que no tiene que dibujarse ni operarse
glEnable(GL_STENCIL_TEST); //Activo stencil test
glColorMask(0, 0, 0, 0); //Mascara todo a falso
glStencilFunc(GL_ALWAYS, 1, 0xffffffff);
glFrontFace(GL_CCW); //Cara frontal en sentido contrario agujas de relo
glStencilOp(GL_KEEP, GL_KEEP, GL_DECR); //Primer paso, decremento el valor del stencil operation
for(unsigned i=0; i { // Cara visible?
if(PtrFaces[i].Visible)
{
for(unsigned j=0; j<3; j++)
{ // Arista de silueta?
if(PtrFaces[i].SilhouetteEdge[j])
{ //Calculo la longitud del vector que pasa por la luz, el vertice y va a un infinito cercano(100 unidades)
VECTOR3D V1((PtrFaces[i].Verts[j].Position.GetX()-LightPos[0])*100,
(PtrFaces[i].Verts[j].Position.GetY()-LightPos[1])*100,
(PtrFaces[i].Verts[j].Position.GetZ()-LightPos[2])*100);
VECTOR3D V2((PtrFaces[i].Verts[(j+1)%3].Position.GetX()-LightPos[0])*100,
(PtrFaces[i].Verts[(j+1)%3].Position.GetY()-LightPos[1])*100,
(PtrFaces[i].Verts[(j+1)%3].Position.GetZ()-LightPos[2])*100);
//Dibujo los poligonos
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(PtrFaces[i].Verts[j].Position.GetX(),
PtrFaces[i].Verts[j].Position.GetY(),
PtrFaces[i].Verts[j].Position.GetZ());
glVertex3f(PtrFaces[i].Verts[j].Position.GetX()+V1.GetX(),
PtrFaces[i].Verts[j].Position.GetY()+V1.GetY(),
PtrFaces[i].Verts[j].Position.GetZ()+V1.GetZ());
glVertex3f(PtrFaces[i].Verts[(j+1)%3].Position.GetX(),
PtrFaces[i].Verts[(j+1)%3].Position.GetY(),
PtrFaces[i].Verts[(j+1)%3].Position.GetZ());
glVertex3f(PtrFaces[i].Verts[(j+1)%3].Position.GetX()+V1.GetX(),
PtrFaces[i].Verts[(j+1)%3].Position.GetY()+V1.GetY(),
PtrFaces[i].Verts[(j+1)%3].Position.GetZ()+V1.GetZ());
glEnd();
};
};
};
};
glFrontFace(GL_CW); //Cara frontal en sentido e agujas del reloj
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); //Segundo paso, incremento el valor del stencil operation
for(unsigned i=0; i { // Cara visible?
if(PtrFaces[i].Visible)
{
for(unsigned j=0; j<3; j++)
{ // Arista de silueta?
if(PtrFaces[i].SilhouetteEdge[j])
{ //Calculo la longitud del vector que pasa por la luz, el vertice y va a un infinito cercano
VECTOR3D V1((PtrFaces[i].Verts[j].Position.GetX()-LightPos[0])*100,
(PtrFaces[i].Verts[j].Position.GetY()-LightPos[1])*100,
(PtrFaces[i].Verts[j].Position.GetZ()-LightPos[2])*100);
VECTOR3D V2((PtrFaces[i].Verts[(j+1)%3].Position.GetX()-LightPos[0])*100,
(PtrFaces[i].Verts[(j+1)%3].Position.GetY()-LightPos[1])*100,
(PtrFaces[i].Verts[(j+1)%3].Position.GetZ()-LightPos[2])*100);
//Dibujo los poligonos
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(PtrFaces[i].Verts[j].Position.GetX(),
PtrFaces[i].Verts[j].Position.GetY(),
PtrFaces[i].Verts[j].Position.GetZ());
glVertex3f(PtrFaces[i].Verts[j].Position.GetX()+V1.GetX(),
PtrFaces[i].Verts[j].Position.GetY()+V1.GetY(),
PtrFaces[i].Verts[j].Position.GetZ()+V1.GetZ());
glVertex3f(PtrFaces[i].Verts[(j+1)%3].Position.GetX(),
PtrFaces[i].Verts[(j+1)%3].Position.GetY(),
PtrFaces[i].Verts[(j+1)%3].Position.GetZ());
glVertex3f(PtrFaces[i].Verts[(j+1)%3].Position.GetX()+V1.GetX(),
PtrFaces[i].Verts[(j+1)%3].Position.GetY()+V1.GetY(),
PtrFaces[i].Verts[(j+1)%3].Position.GetZ()+V1.GetZ());
glEnd();
};
};
};
};
glFrontFace(GL_CCW); //Cara frontal en sentido contrario a las agujas del reloj
glColorMask(1, 1, 1, 1);
glStencilFunc(GL_NOTEQUAL, 0, 0xffffffff);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glDepthFunc(GL_LEQUAL);
glDepthMask(GL_TRUE);
glEnable(GL_LIGHTING);
glDisable(GL_STENCIL_TEST);
glShadeModel(GL_SMOOTH);
};
[/PHP]
Agradeceria cualquier tipo de ayuda, adjunto dos imagenes, una con el resultado que obtengo, es decir sin sombra ni nada... y otro en la ke pinto la proyeccion en rojo para comprovar si el casting de caras y la propia proyeccion es correcta respecto al foco de luz, representado por un circulito amarillo.
Gracias de antemano