Cartographie UV de la carte de déplacement ?
-
13-12-2019 - |
Question
Résumé
J'essaie d'appliquer une carte de déplacement (carte de hauteur) à un objet plutôt simple (plan hexagonal) et j'obtiens des résultats inattendus.J'utilise des niveaux de gris et, en tant que tel, j'avais l'impression que ma carte de hauteur ne devrait affecter que les valeurs Z de mon maillage.Cependant, la carte de déplacement que j'ai créée étend le maillage sur les plans X et Y.De plus, il ne semble pas utiliser le mappage UV que j'ai créé et auquel toutes les autres textures sont appliquées avec succès.
Modèle et carte UV
Voici des images de référence de mon maillage hexagonal et de sa carte UV correspondante dans Blender.
Textures diffuses et de déplacement
Ce sont les textures de carte diffuse et de déplacement que j'applique à mon maillage via Three.JS.
Rendus
Lorsque je restitue le plan sans carte de déplacement, vous pouvez voir que le plan hexagonal reste à l'intérieur des lignes.Cependant, lorsque j'ajoute la carte de déplacement, cela affecte clairement les positions X et Y des sommets plutôt que d'affecter uniquement le Z, élargissant ainsi le plan sur les lignes.
Code
Voici le code Three.js pertinent :
// Textures
var diffuseTexture = THREE.ImageUtils.loadTexture('diffuse.png', null, loaded);
var displacementTexture = THREE.ImageUtils.loadTexture('displacement.png', null, loaded);
// Terrain Uniform
var terrainShader = THREE.ShaderTerrain["terrain"];
var uniformsTerrain = THREE.UniformsUtils.clone(terrainShader.uniforms);
//uniformsTerrain["tNormal"].value = null;
//uniformsTerrain["uNormalScale"].value = 1;
uniformsTerrain["tDisplacement"].value = displacementTexture;
uniformsTerrain["uDisplacementScale"].value = 1;
uniformsTerrain[ "tDiffuse1" ].value = diffuseTexture;
//uniformsTerrain[ "tDetail" ].value = null;
uniformsTerrain[ "enableDiffuse1" ].value = true;
//uniformsTerrain[ "enableDiffuse2" ].value = true;
//uniformsTerrain[ "enableSpecular" ].value = true;
//uniformsTerrain[ "uDiffuseColor" ].value.setHex(0xcccccc);
//uniformsTerrain[ "uSpecularColor" ].value.setHex(0xff0000);
//uniformsTerrain[ "uAmbientColor" ].value.setHex(0x0000cc);
//uniformsTerrain[ "uShininess" ].value = 3;
//uniformsTerrain[ "uRepeatOverlay" ].value.set(6, 6);
// Terrain Material
var material = new THREE.ShaderMaterial({
uniforms:uniformsTerrain,
vertexShader:terrainShader.vertexShader,
fragmentShader:terrainShader.fragmentShader,
lights:true,
fog:true
});
// Load Tile
var loader = new THREE.JSONLoader();
loader.load('models/hextile.js', function(g) {
//g.computeFaceNormals();
//g.computeVertexNormals();
g.computeTangents();
g.materials[0] = material;
tile = new THREE.Mesh(g, new THREE.MeshFaceMaterial());
scene.add(tile);
});
Hypothèse
Je jongle actuellement avec trois possibilités pour expliquer pourquoi cela pourrait mal se passer :
- La carte UV ne s'applique pas à ma carte de déplacement.
- J'ai mal créé la carte de déplacement.
- J'ai raté une étape cruciale dans le processus qui verrouillerait le déplacement sur Z uniquement.
Et bien sûr, l'option secrète n°4 qui n'est rien de ce qui précède et je viens de vraiment je n'ai aucune idée de ce que je fais.Ou tout mélange de ce qui précède.
Exemple en direct
Vous pouvez voir un exemple en direct ici.
Si quelqu'un ayant plus de connaissances sur le sujet pouvait me guider, je lui en serais très reconnaissant !
Modifier 1:Conformément à la suggestion, j'ai commenté computeFaceNormals()
et computeVertexNormals()
.Bien que cela ait apporté une légère amélioration, le maillage est toujours déformé.
La solution
Dans votre matériel de terrain, définissez wireframe = true
, et vous pourrez voir ce qui se passe.
Votre code et vos textures sont fondamentalement bonnes.Le problème se produit lorsque vous calculez les normales des sommets dans la fonction de rappel du chargeur.
Les normales de sommet calculées pour l’anneau extérieur de votre géométrie pointent quelque peu vers l’extérieur.C'est très probablement parce que dans computeVertexNormals()
elles sont calculées en faisant la moyenne des normales de face de chaque face voisine, et les normales de face des "côtés" de votre modèle (la partie noire) sont moyennées dans le calcul des normales de sommet pour les sommets qui constituent l'anneau extérieur du "capuchon". ".
En conséquence, l'anneau extérieur du « capuchon » s'étend vers l'extérieur sous la carte de déplacement.
MODIFIER:Effectivement, directement à partir de votre modèle, les normales des sommets de l’anneau extérieur pointent vers l’extérieur.Les normales aux sommets des anneaux intérieurs sont toutes parallèles.Peut-être que Blender utilise la même logique pour générer des normales de sommets que computeVertexNormals()
fait.
Autres conseils
Le problème est de savoir comment votre objet est construit car le déplacement se produit le long du vecteur normal.
le code est ici.
https://github.com/mrdoob/trois.js/blob/master/examples/js/ShaderTerrain.js#L348-350
"vec3 dv = texture2D( tDisplacement, uvBase ).xyz;",
Cela prend le vecteur RVB de la texture de déplacement.
"float df = uDisplacementScale * dv.x + uDisplacementBias;",
cela ne prend que la valeur rouge du vecteur car uDisplacementScale est normalement 1,0 et uDisplacementBias est 0,0.
"vec3 displacedPosition = normal * df + position;",
Cela déplace la position le long du vecteur normal.
donc pour résoudre, vous mettez à jour les normales ou le shader.