Calcul d'ombres

Signaler
Messages postés
56
Date d'inscription
mardi 17 décembre 2002
Statut
Membre
Dernière intervention
11 novembre 2005
-
Messages postés
56
Date d'inscription
mardi 17 décembre 2002
Statut
Membre
Dernière intervention
11 novembre 2005
-
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

Messages postés
11
Date d'inscription
dimanche 13 juillet 2003
Statut
Membre
Dernière intervention
20 juillet 2005

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...
Messages postés
56
Date d'inscription
mardi 17 décembre 2002
Statut
Membre
Dernière intervention
11 novembre 2005

merci