4

概要

ディスプレイスメント マップ (高さマップ) をかなり単純なオブジェクト (六角形の平面) に適用しようとしていますが、予期しない結果が得られます。私はグレースケールを使用しているため、高さマップはメッシュの Z 値にのみ影響するはずであるという印象を受けました。ただし、作成したディスプレイスメント マップは、メッシュを X 平面と Y 平面に広げます。さらに、他のすべてのテクスチャが正常に適用されている、私が作成した UV マッピングを使用していないようです。

モデルと UV マップ

これは、私の六角形メッシュの参照画像と、それに対応する Blender の UV マップです。

六角形モデルと UV マップ

拡散テクスチャとディスプレイスメント テクスチャ

これらは、Three.JS を使用してメッシュに適用している拡散マップ テクスチャとディスプレイスメント マップ テクスチャです。

六角形の拡散とディスプレイスメント テクスチャ

レンダリング

ディスプレイスメント マップを使用せずに平面をレンダリングすると、六角形の平面が線内にとどまっていることがわかります。ただし、ディスプレイスメント マップを追加すると、頂点の Z だけでなく X と Y の位置に明確に影響し、平面が線の上に拡張されます。

六角形平面レンダリング -- ディスプレイスメント マップあり/なし

コード

関連する Three.js コードは次のとおりです。

    // 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);
    });

仮説

なぜこれがうまくいかないのかについて、私は現在3つの可能性をジャグリングしています:

  1. UV マップがディスプレイスメント マップに適用されません。
  2. ディスプレイスメント マップを間違って作成しました。
  3. ディスプレイスメントを Z のみにロックするプロセスの重要なステップを見逃していました。

そしてもちろん、秘密のオプション #4 は上記のどれにも当てはまらず、自分が何をしているのかまったくわかりません。または前述の任意の混合物。

実際の例

ここで実例を見ることができます。

この件についてより多くの知識を持っている人が私を導くことができれば、私はとても感謝しています!

編集 1 : 提案に従って、私はコメントアウトしcomputeFaceNormals()computeVertexNormals(). わずかに改善されましたが、メッシュはまだ歪んでいます。

4

2 に答える 2

4

地形マテリアルで を設定wireframe = trueすると、何が起こっているかを確認できます。

コードとテクスチャは基本的に問題ありません。この問題は、ローダー コールバック関数で頂点法線を計算するときに発生します。

ジオメトリの外輪の計算された頂点法線は、やや外側を向いています。これはcomputeVertexNormals()、隣接する各面の面法線を平均することによって計算され、モデルの「側面」(黒い部分) の面法線が、 「キャップ」の外輪。

その結果、「キャップ」の外側のリングがディスプレイスメント マップの下で外側に拡張されます。

編集: 案の定、モデルから直接、外側のリングの頂点法線が外側を向いています。内側のリングの頂点法線はすべて平行です。おそらく、Blender は同じロジックを使用して頂点法線を生成してcomputeVertexNormals()います。

頂点法線

于 2012-10-03T20:27:38.153 に答える
1

問題は、変位が法線ベクトルに沿って発生するため、オブジェクトがどのように構築されるかです。

コードはここにあります。

https://github.com/mrdoob/three.js/blob/master/examples/js/ShaderTerrain.js#L348-350

"vec3 dv = texture2D( tDisplacement, uvBase ).xyz;",

これは、ディスプレイスメントテクスチャのrgbベクトルを取ります。

"float df = uDisplacementScale * dv.x + uDisplacementBias;",

uDisplacementScaleは通常1.0であり、uDisplacementBiasは0.0であるため、これはベクトルの赤の値のみを取ります。

"vec3 displacedPosition = normal * df + position;",

これにより、法線ベクトルに沿って位置が移動します。

したがって、解決するには、法線またはシェーダーを更新します。

于 2012-10-03T19:32:15.897 に答える