Calcul d'ombres

dmothes Messages postés 56 Date d'inscription mardi 17 décembre 2002 Statut Membre Dernière intervention 11 novembre 2005 - 6 mai 2004 à 07:48
dmothes Messages postés 56 Date d'inscription mardi 17 décembre 2002 Statut Membre Dernière intervention 11 novembre 2005 - 5 juil. 2004 à 10:33
quelqu'un pourrait-il m'expliquer comment faire du calcul d'ombre un OpenGL, ou me donner un lien vers un site (en français) qui l'explique.

2 réponses

lolquivole Messages postés 11 Date d'inscription dimanche 13 juillet 2003 Statut Membre Dernière intervention 20 juillet 2005
4 juil. 2004 à 01:29
L'ombre, c'est la projection de tout un objet sur un plan suivant la direction de la lumière.
C'est donc pour ca qu'il faut multiplier la matrice modelview par une matrice de projection (projection sur le plan // à la lumière).
Il ne faut pas dessiner l'objet tel quel dans ce plan: il faut la dessiner noire et un peu transparente, pour que ca ressemble à une ombre :)
Par contre il ne faut pas assombrir deux fois le même point : c'est là que le stencil buffer intervient :
Il faut donc incrémenter le stencil quand stencil test et depth test passent.
Si l'objet est au départ transparent, il ne faut pas utiliser cette technique: il y a un assombrissement proportionnel au nombre de surfaces.

Pour obtenir la matrice de projection: d'après la doc. de M.J. Kilgard :

/* Create a matrix that will project the desired shadow. */
enum { X = 0, Y, Z, W };
void shadowMatrix(GLfloat shadowMat[4][4], GLfloat groundplane[4], GLfloat lightpos[4])
{
GLfloat dot;

dot = groundplane[X] * lightpos[X] +
groundplane[Y] * lightpos[Y] +
groundplane[Z] * lightpos[Z] +
groundplane[W] * lightpos[W];

shadowMat[0][0] = dot - lightpos[X] * groundplane[X];
shadowMat[1][0] = 0.f - lightpos[X] * groundplane[Y];
shadowMat[2][0] = 0.f - lightpos[X] * groundplane[Z];
shadowMat[3][0] = 0.f - lightpos[X] * groundplane[W];

shadowMat[X][1] = 0.f - lightpos[Y] * groundplane[X];
shadowMat[1][1] = dot - lightpos[Y] * groundplane[Y];
shadowMat[2][1] = 0.f - lightpos[Y] * groundplane[Z];
shadowMat[3][1] = 0.f - lightpos[Y] * groundplane[W];

shadowMat[X][2] = 0.f - lightpos[Z] * groundplane[X];
shadowMat[1][2] = 0.f - lightpos[Z] * groundplane[Y];
shadowMat[2][2] = dot - lightpos[Z] * groundplane[Z];
shadowMat[3][2] = 0.f - lightpos[Z] * groundplane[W];

shadowMat[X][3] = 0.f - lightpos[W] * groundplane[X];
shadowMat[1][3] = 0.f - lightpos[W] * groundplane[Y];
shadowMat[2][3] = 0.f - lightpos[W] * groundplane[Z];
shadowMat[3][3] = dot - lightpos[W] * groundplane[W];
}

avec shadowMat la matrice à construire, groundpane l’équation du plan où projeter l’ombre (de type ax + by + cz + d = 0), et lightpos comme son nom l’indique (lightpos[3] de préférence à 0).

Et pour les coefficients du plan :

/* Find the plane equation given 3 points. */
enum { A = 0, B, C, D };
void findPlane(GLfloat plane[4], GLfloat v0[3], GLfloat v1[3], GLfloat v2[3])
{
GLfloat vec0[3], vec1[3];

/* Need 2 vectors to find cross product. */
vec0[X] = v1[X] - v0[X];
vec0[Y] = v1[Y] - v0[Y];
vec0[Z] = v1[Z] - v0[Z];

vec1[X] = v2[X] - v0[X];
vec1[Y] = v2[Y] - v0[Y];
vec1[Z] = v2[Z] - v0[Z];

/* find cross product to get A, B, and C of plane equation */
plane[A] = vec0[Y] * vec1[Z] - vec0[Z] * vec1[Y];
plane[B] = -(vec0[X] * vec1[Z] - vec0[Z] * vec1[X]);
plane[C] = vec0[X] * vec1[Y] - vec0[Y] * vec1[X];

plane[D] = -(plane[A] * v0[X] + plane[B] * v0[Y] + plane[C] * v0[Z]);
}

Les étapes de l’ombre sont alors :

-Limitation de l’ombre à la surface :

glEnable(GL_STENCIL_TEST);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
glStencilFunc(GL_ALWAYS, 1, 0xffffffff);

-On dessine la surface

glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glEnable(GL_DEPTH_TEST);
glDisable(GL_STENCIL_TEST);

-On dessine l’objet

-Calcul de la matrice de projection (avec vfloor des points de la surface) :
GLfloat floorPlane[4];
GLfloat floorShadow[4][4];
findPlane(floorPlane, vfloor[1], vfloor[2], vfloor[3]);
shadowMatrix(floorShadow, floorPlane, lightZeroPosition);

-On change les paramètres pour dessiner une surface noire transparente :

glStencilFunc(GL_EQUAL, 1, 0xffffffff);
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
glColor4f(0.0, 0.0, 0.0, 0.6);

-On dessine l'ombre

glPushMatrix();
glMultMatrixf((GLfloat *) floorShadow);
Dessin de l’objet
glPopMatrix();

-----------------------------------------

J'espère quand même que tu maîtrises le stencil buffer, te l'expliquer ici serait trop long...
0
dmothes Messages postés 56 Date d'inscription mardi 17 décembre 2002 Statut Membre Dernière intervention 11 novembre 2005
5 juil. 2004 à 10:33
merci
0
Rejoignez-nous