Mapeamento UV do mapa de deslocamento?
-
13-12-2019 - |
Pergunta
Resumo
Estou tentando aplicar um mapa de deslocamento (mapa de altura) a um objeto bastante simples (plano hexagonal) e estou tendo alguns resultados inesperados.Estou usando tons de cinza e, como tal, tive a impressão de que meu mapa de altura deveria afetar apenas os valores Z da minha malha.No entanto, o mapa de deslocamento que criei estica a malha pelos planos X e Y.Além disso, parece não usar o mapeamento UV que criei e ao qual todas as outras texturas foram aplicadas com sucesso.
Modelo e Mapa UV
Aqui estão imagens de referência da minha malha hexagonal e seu mapa UV correspondente no Blender.
Texturas Difusas e Deslocadas
Estas são as texturas de mapa difuso e de deslocamento que estou aplicando à minha malha por meio do Three.JS.
Renderizações
Quando renderizo o plano sem um mapa de deslocamento, você pode ver que o plano hexagonal permanece dentro das linhas.No entanto, quando adiciono o mapa de deslocamento, ele afeta claramente as posições X e Y dos vértices, em vez de afetar apenas Z, expandindo o plano bem sobre as linhas.
Código
Aqui está o código Three.js relevante:
// 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);
});
Hipótese
Atualmente estou lidando com três possibilidades de por que isso pode estar dando errado:
- O mapa UV não se aplica ao meu mapa de deslocamento.
- Fiz o mapa de deslocamento incorretamente.
- Perdi uma etapa crucial no processo que bloquearia o deslocamento apenas para Z.
E, claro, a opção secreta nº 4, que não é nenhuma das opções acima e eu apenas realmente não tenho ideia do que estou fazendo.Ou qualquer mistura dos acima mencionados.
Exemplo ao vivo
Você pode ver um exemplo ao vivo aqui.
Se alguém com mais conhecimento no assunto pudesse me orientar ficaria muito grato!
Editar 1:Como sugestão, comentei computeFaceNormals()
e computeVertexNormals()
.Embora tenha feito uma ligeira melhoria, a malha ainda está distorcida.
Solução
No material do seu terreno, defina wireframe = true
, e você poderá ver o que está acontecendo.
Seu código e texturas estão basicamente bons.O problema ocorre quando você calcula normais de vértice na função de retorno de chamada do carregador.
As normais do vértice calculadas para o anel externo da sua geometria apontam um pouco para fora.Isto é mais provável porque em computeVertexNormals()
eles são calculados pela média das normais de face de cada face vizinha, e as normais de face dos "lados" do seu modelo (a parte preta) são calculadas em média no cálculo normal do vértice para os vértices que compõem o anel externo do "cap ".
Como resultado, o anel externo da “tampa” se expande para fora sob o mapa de deslocamento.
EDITAR:Com certeza, direto do seu modelo, os vértices normais do anel externo apontam para fora.As normais dos vértices dos anéis internos são todas paralelas.Talvez o Blender esteja usando a mesma lógica para gerar normais de vértices que computeVertexNormals()
faz.
Outras dicas
O problema é como o seu objeto é construído porque o deslocamento ocorre ao longo do vetor normal.
o código está aqui.
https://github.com/mrdoob/três.js/blob/master/examples/js/ShaderTerrain.js#L348-350
"vec3 dv = texture2D( tDisplacement, uvBase ).xyz;",
Isso pega o vetor RGB da textura de deslocamento.
"float df = uDisplacementScale * dv.x + uDisplacementBias;",
isso leva apenas o valor vermelho do vetor porque uDisplacementScale é normalmente 1,0 e uDisplacementBias é 0,0.
"vec3 displacedPosition = normal * df + position;",
Isso desloca a posição ao longo do vetor normal.
então para resolver você atualiza os normais ou o shader.