Author Topic: Recalcul de normales dans le vertex shader  (Read 2318 times)

0 Members and 1 Guest are viewing this topic.

Offline flure

  • Base
    • Pouet.net
    • View Profile
  • Ancienneté: 1998
  • Groupe: PoPsY TeAm
  • Rôle: Codeur Linux
  • Ville: Lyon
Recalcul de normales dans le vertex shader
« on: 16 June 2013 à 19:00:21 »
Salut,

Je bloque sur un point un peu chiant, et mes mathématiques sont un peu rouillées.
Je déforme un mesh dans le vertex shader, mais du coup il faut que je recalcule les normales aux vertex pour que l'éclairage soit bon. Je précise que je fais cette déformation à base de sinus et autres fonctions trigo.

En farfouillant, je suis tombé sur deux solutions éventuelles :
1) passer les vecteurs tangente et bitangente au vertex shader. Appliquer la déformation sur deux autres points de la surface en utilisant ces vecteurs, et recalculer la normale ainsi.
Le hic c'est que du coup ça fait beaucoup de données à passer en plus, sachant que j'ai vraiment beaucoup de vertices sur ce mesh, environ 20000 (enfin je pense que ça fait beaucoup...)

2) calculer la normale en utilisant une matrice jacobienne... Mais alors là par contre je ne capte rien à ce que j'ai pu trouver. Si j'ai bien compris, il faut que je crée une matrice 3x3 en utilisant les dérivées partielles des fonctions utilisées pour ma déformation. C'est là que je coince. C'est quoi une dérivée partielle ? Je la remplis comment cette matrice ? Bref je suis largué pour un problème de maths.

Autre solution : faire le calcul sur le CPU. C'est ce que je faisais avant de mettre la déformation dans le vertex shader, et la performance s'en ressent énormément donc c'est hors de question. Je suis passé de 15fps avec le calcul sur le CPU, à 1600fps avec le calcul dans le vertex shader..

Bref si quelqu'un peut m'aiguiller, je lui payerai volontiers une bière la prochaine fois qu'on se croise ! :)

Offline Patapom

  • Base
    • View Profile
    • www.patapom.com
  • Ancienneté: 1988
  • Groupe: Bomb!
  • Rôle: Coder
  • Ville: Lyon
Re : Recalcul de normales dans le vertex shader
« Reply #1 on: 16 June 2013 à 21:23:29 »
Une dérivée partielle de fonction c'est une dérivée qui ne prend en compte que la variation d'une des variables de ta fonction.

Par exemple, si tu as la position P de ta surface qui varie en fonction de x, y et z alors P(x,y,z). Un peu comme les y=f(x) qu'on étudiait il y a longtemps.

La dérivée partielle de P(x,y,z) selon x s'écrit:
La dérivée partielle de P(x,y,z) selon y s'écrit:
La dérivée partielle de P(x,y,z) selon z s'écrit:

En gros, ça revient à calculer le changement de valeur de P(x,y,z) quand tu fais bouger que x, ou que y ou que z.

Le vecteur s'appelle le "gradient de P", et c'est également la direction de la normale à ta surface.

Tu t'es jamais posé la question de ce que les gars faisaient pour calculer la normale d'un distance field ? Tu sais, ce bout de code-là :
Code: [Select]
vec3 calcNormal( in vec3 pos, float t )
{
float e = 0.001;
e = 0.001*t;
    vec3  eps = vec3(e,0.0,0.0);
    vec3 nor;
    nor.x = distance(pos+eps.xyy) - distance(pos-eps.xyy);
    nor.y = distance(pos+eps.yxy) - distance(pos-eps.yxy);
    nor.z = distance(pos+eps.yyx) - distance(pos-eps.yyx);
    return normalize(nor);
}

Bah voilà. Tu sais maintenant : calcul du gradient...

Du coup t'es pas obligé de calculer le jacobien de ta fonction, car ça te donne plus d'infos que ce dont t'as besoin.
Calculer les dérivées partielles selon x, y et z suffit.

Maintenant, comment on fait ? Bah il faut que tu files ta fonction pour ça...

Mais imagine juste que P(x,y,z) = sin(x)*sin(y)*sin(z) pour faire simple.

c'est la dérivée de P(x,y,z) en ne prenant en compte que les variations selon x. Les autres paramètres n'interviennent pas, ça veut dire qu'aux yeux de ta dérivée, sin(y)*sin(z) est une constante.

Donc tu peux écrire , avec k=sin(y)*sin(z).

Pareil pour les autres paramètres...

Tu vois l'idée ?
.  Pom  .

Offline flure

  • Base
    • Pouet.net
    • View Profile
  • Ancienneté: 1998
  • Groupe: PoPsY TeAm
  • Rôle: Codeur Linux
  • Ville: Lyon
Re : Recalcul de normales dans le vertex shader
« Reply #2 on: 17 June 2013 à 21:37:54 »
Bon ok. En fait j'ai rien capté. :(

Offline Elrick

  • Base
    • View Profile
  • Groupe: SFX
  • Rôle: Code / GFX
  • Ville: Lyon
Re : Recalcul de normales dans le vertex shader
« Reply #3 on: 18 June 2013 à 08:28:49 »
20k vertex c'est rien du tout !

Offline Ziple

  • Base
    • View Profile
  • Ancienneté: 2013
  • Ville: Paris
Re : Recalcul de normales dans le vertex shader
« Reply #4 on: 18 June 2013 à 11:44:11 »
Là Patappom t'a parlé de ce qu'on appelle les surfaces implicites en mathématiques: ce sont des surfaces constituées de points (x,y,z)  qui vérifient F(x,y,z)=0. Par exemple, pour une sphère on peut utiliser F(x,y,z) = x*x + y*y +z*z - r*r où r est le rayon.
Et Patapom t'a dit comment récupérer la normale à la surface en chaque point de la surface: il s'agit du gradient de F normalisé.

Pour calculer ce gradient, il y alors deux possibilités. Soit on connaît l'expression des dérivées partielles, soit on utilise la méthode numérique "à la raymarching" .
Pour calculer analytiquement la dérivée partielle selon la variable x de F, il suffit de dériver la fonction de la seule variable x (y et z étant considérés comme fixes). Par exemple, pour la sphère, F(x,y,z) = x*x + y*y + z*z - r*r. La dérivée partielle par rapport à x est donc (dF/dx)(x,y,z) = 2x.

Mais peut-être que ce que tu fais ne peut-être ramené à l'évaluation d'une surface implicite. Peut-être que le plus simple est alors de reconstruire les normales dans un geometry shader.