Author Topic: speculaire en tangent space  (Read 8467 times)

0 Members and 1 Guest are viewing this topic.

NoBrainNoBrain

  • Associate
  • Posts: 5
speculaire en tangent space
« on: November 03, 2011, 12:07:53 PM »
Salut à tous

J'ai un petit souci sur un shader pourtant simple: le calcul du spéculaire sur un shader doté d'une normal map.
En temps normal, je calcule cette valeur spéculaire en world space, un bête produit scalaire et c'est plié. Mais comme mon shader utilise une normal map, il fonctionne essentiellement en tangent space. Donc j'aimerais bien que mon spéculaire puisse être calculé dans le même repère, histoire de ne pas multiplier les transformations inutiles.

Ça semble simple comme tout, mais rien à faire, mon point spéculaire sur le mesh est dramatiquement allongé horizontalement. Pour tester, j'ai donc créé un autre shader sans normalMap, mais qui me calcule le spéculaire selon les deux modes: tangent et world space

vertex shader:
Code: [Select]
[Vertex_Shader]
varying vec3 lightVec;
varying vec3 eyeVec;
attribute vec3 vTangent;
varying vec3 normalWS;
varying vec3 lightWS;
varying vec3 eyeWS;

void main(void)
{
   gl_Position = ftransform(); //projection des vertex à l'écran
   gl_TexCoord[0] = gl_MultiTexCoord0; //transfer des coordonnées UV

   //calcul des 3 vecteurs du repère tangent
vec3 n = normalize(gl_NormalMatrix * gl_Normal); //vecteur normal
vec3 t = normalize(gl_NormalMatrix * vTangent); //vecteur tangent
vec3 b = cross(n, t); //vecteur binormal


/* projections des vecteurs classiques pour connaitre leurs coordonnées en tangent space */
vec3 vVertex = vec3(gl_ModelViewMatrix * gl_Vertex);
vec3 tmpVec = gl_LightSource[0].position.xyz - vVertex;

lightVec.x = dot(tmpVec, t);
lightVec.y = dot(tmpVec, b);
lightVec.z = dot(tmpVec, n);

tmpVec = -vVertex;
eyeVec.x = dot(tmpVec, t);
eyeVec.y = dot(tmpVec, b);
eyeVec.z = dot(tmpVec, n);

/*calcul des mêmes vecteurs en world space*/
normalWS = n;
lightWS = normalize(gl_LightSource[0].position.xyz - vVertex);
eyeWS = normalize(vec3(gl_ModelViewMatrix * gl_Vertex) * -1) ;

}

Code: [Select]
varying vec3 lightVec;
varying vec3 eyeVec;
uniform float invRadius;
varying vec3 normalWS;
varying vec3 lightWS;
varying vec3 eyeWS;

void main (void)
{
float distSqr = dot(lightVec, lightVec);
float att = clamp(1.0 - invRadius * sqrt(distSqr), 0.0, 1.0);
vec3 lVec = lightVec * inversesqrt(distSqr);
lVec = normalize(lightVec);

vec3 vVec = normalize(eyeVec);
vec3 bump = vec3(0.0,0.0,1.0);

float specularTS = pow(clamp(dot(reflect(-lVec, bump), vVec), 0.0, 1.0), gl_FrontMaterial.shininess );
float specularWS = pow(clamp(dot(reflect(-lightWS, normalWS), eyeWS), 0.0, 1.0), gl_FrontMaterial.shininess );
vec4 vSpecularWS=vec4(0.0,0.0,0.0,1.0);
vec4 vSpecularTS=vec4(0.0,0.0,0.0,1.0);
vSpecularWS.b = gl_LightSource[0].specular.r * gl_FrontMaterial.specular.r * specularWS;
vSpecularTS.g = gl_LightSource[0].specular.r * gl_FrontMaterial.specular.r * specularTS;

gl_FragColor = vec4(0.0,0.0,0.0,1.0);
gl_FragColor += vSpecularWS + vSpecularTS ;
}

le speculaire en world space (vSpecularWS) apparait en bleu
le speculaire en tangent space (vSpecularTS) apparait en vert

et rien à faire, ils sont dramatiquement différents.
Je suis sûr que c'est juste une erreur stupide dans le code, mais j'arrive pas à mettre le doigt dessus...

une idée?

merci !

JeGX

  • Global Moderator
  • Capo Crimine
  • *****
  • Posts: 2385
    • oZone3D.Net
Re: speculaire en tangent space
« Reply #1 on: November 08, 2011, 10:19:47 AM »
tu a regardé la demo GLSL_Bump_Mapping dans le code sample pack de GeeXLab? Cette demo utilise une normal map et il y a des reflets spéculaires...

NoBrainNoBrain

  • Associate
  • Posts: 5
Re: speculaire en tangent space
« Reply #2 on: November 08, 2011, 06:07:35 PM »
ok, je viens de regarder, et j'y ai trouvé une solution

mais c'est pas très clair dans mon esprit: dans la définition du shader, quel est le mot clé pour le vecteur tangent?
selon les sources, je trouve soit glTangent4f soit vTangent...
d'ailleurs, dans la doc, je ne trouve pas de référence à l'élement XML "vertex_attrib". Donc à défaut de savoir l'utiliser correctement, je fais de bons vieux copier/coller issus des samples. Ya-t-il une partie de la doc à coté de laquelle je suis passé?

merci

JeGX

  • Global Moderator
  • Capo Crimine
  • *****
  • Posts: 2385
    • oZone3D.Net
Re: speculaire en tangent space
« Reply #3 on: November 10, 2011, 01:47:32 PM »
Le vertex attrib predéfinit dans GeeXLab pour le vecteur tangent est glTangent4f.

La gestion des attributs generiques de vertex n'est pas super bien faite dans GXL. C'est quelque chose que je vais revoir dès que je peux.

Le truc c'est que le vecteur tangent, à la difference du vecteur normal, n'est pas automatiquement calculé. Il faut en faire la demande explicite au niveau XML
Code: [Select]
<mesh     compute_tangent_space="FALSE" />

ou en scripting (Lua et Python)
Code: [Select]
HYP_Object.ComputeTangentSpace(mesh_id)


« Last Edit: November 10, 2011, 01:50:02 PM by JeGX »

NoBrainNoBrain

  • Associate
  • Posts: 5
Re: speculaire en tangent space
« Reply #4 on: November 17, 2011, 10:12:33 AM »
ok je saisis mieux

par contre, il est fiable ce calcul de tangente? parce que j'ai fait quelques shaders de debug qui testent l'orthogonalité du vecteur tangent et de la normale, et il semble qu'il y ai des pains:

Code: [Select]
<material name="conjMat" shader_program="conjunctivaShader" />

<model name="Conjunctiva" filename="Data/Conjonctiva.obj" vbo="TRUE" average_normals="TRUE" compute_tangent_space="TRUE" >
<blending_params active="TRUE" />
</model>

Code: [Select]
[Vertex_Shader]
varying vec3 tagentDEBUG;
void main(void)
{
   gl_Position = ftransform();
   gl_TexCoord[0] = gl_MultiTexCoord0;
tagentDEBUG = glTangent4f.xyz;
}
Code: [Select]
[Pixel_Shader]
varying vec3 tagentDEBUG;
void main(void)
{
gl_FragColor = vec4(0.0,0.0,0.0,1.0);
gl_FragColor.x= dot( vec3(0.0,0.0,1.0), tagentDEBUG);
gl_FragColor.y=gl_FragColor.x;
gl_FragColor.z=gl_FragColor.x;
}

le résultat est cette image:


si maintenant je remplace mon fragment shader par
Code: [Select]
gl_FragColor.xyz=tagentDEBUG;

j'obtiens un truc avec des tangent qui ne sont smoothées que selon un axe




pour bien comprendre la structure du truc, voilà un wireframe: c'est donc un objet quasi sphérique que j'importe en obj, et qui contient normalement des normales lissées



et la planche UV




je fais quelque chose de travers ou ya effectivement un souci là dessus?

autre question, plus administrative que technique: quand on commande la licence via paypal, on reçois la version complète dans un délai court? je peux envisager la recevoir dans la journée?

JeGX

  • Global Moderator
  • Capo Crimine
  • *****
  • Posts: 2385
    • oZone3D.Net
Re: speculaire en tangent space
« Reply #5 on: November 17, 2011, 11:33:25 AM »
Oui le vecteur tangent est normalement fiable. Il est calculé à partir des coordonnées de texture et des normales. Et il est normalement bien orthogonal au vecteur normal de chaque vertex. Une petite renormalisation peut etre utile avant d'utiliser la vecteur tangent dans ton pixel shader.

Regarde si ce petit bout de GLSL peut te servir dans ton vertex shader:
Code: [Select]
vec3 n = normalize(gl_NormalMatrix * gl_Normal);
vec3 t = normalize(gl_NormalMatrix * glTangent4f.xyz);
vec3 b = cross(n, t);

Au niveau de ton fichier OBJ, si tu as les normales exportées (oui d'après tes explications), ce n'est pas la peine de les faire moyenner par GXL. Les normales exportées sont de bien meilleure qualité. Donc laisse average_normals à FALSE. Et verifie aussi que  compute_normals="FALSE" car je crois qu'il est à TRUE par defaut.

Pour la licence de GXL, si je suis devant mon ordi quand je reçois la confirmation de paypal, je t'envoie toutes les infos dans les minutes qui suivent. Sinon au plus tard c'est le lendemain.

NoBrainNoBrain

  • Associate
  • Posts: 5
Re: speculaire en tangent space
« Reply #6 on: November 18, 2011, 10:38:04 AM »
bon, j'ai testé tout ça, mais ça n'a malheureusement pas changé grand chose

par contre j'y vois plus clair sur le problème: ça le fait sur tous les modèles de ma scene. Je te passe les détails de mon enquête (j'ai testé plusieurs modèles et plusieurs soft de modélisation), mais j'ai identifié l'origine du problème. Quand j'applique ce shader à un modèle fraichement modélisé dans blender, ça se passe bien (pas de trace grise). Mais dés que je fais un unwrap de ce modèle, les taches grises/blanches réapparaissent.

en clair, dés que le modèle possède des coordonnées de texture, ça foire  :-\

JeGX

  • Global Moderator
  • Capo Crimine
  • *****
  • Posts: 2385
    • oZone3D.Net
Re: speculaire en tangent space
« Reply #7 on: November 19, 2011, 03:15:16 PM »
Quand j'applique ce shader à un modèle fraichement modélisé dans blender, ça se passe bien (pas de trace grise).
Les modèles fraichement modélisés ont-ils des coords de texture?

NoBrainNoBrain

  • Associate
  • Posts: 5
Re: speculaire en tangent space
« Reply #8 on: November 19, 2011, 05:31:06 PM »
justement non, c'est pour ça que ça se passe bien :(

JeGX

  • Global Moderator
  • Capo Crimine
  • *****
  • Posts: 2385
    • oZone3D.Net
Re: speculaire en tangent space
« Reply #9 on: November 23, 2011, 09:35:29 PM »
Tiens fais un test avec ce bout de code qui calcule les vecteurs tangents:

Code: [Select]

vec3  T, B;
vec3 v1 = vec3(0.0, 0.0, 1.0);
vec3 v2 = vec3(0.0, 1.0, 0.0);
vec3 c1 = cross(N, v1.xyz);
vec3 c2 = cross(N, v2.xyz);
if (length(c1) > length(c2))\n"
  T = c1;
else
  T = c2;
T = normalize(T);
B = normalize(cross(N, T));
Dans certains cas, le vecteur T sera légèrement faux mais cela te permettra de tester ton code.
J'ai récupéré ce code dans un des mes anciens tutos:
http://www.ozone3d.net/tutorials/mesh_deformer_p2.php#part_2